1 คะแนน โดย GN⁺ 6 시간 전 | 1 ความคิดเห็น | แชร์ทาง WhatsApp
  • การปรับแต่งประสิทธิภาพเป็นวิธีทรงพลังในการทำความเข้าใจระบบที่ซับซ้อนและปรับปรุงผลิตภัณฑ์ แต่แม้ผลลัพธ์จะ เร็วขึ้น 10 เท่า ก็อาจยังไม่เปลี่ยนวิธีทำงานจริงหรือปริมาณงานที่ทำได้
  • แม้จะลดเวลาตอบสนองของคิวรีจาก 5–10 นาที เหลือ 30 วินาที–1 นาที ได้ แต่หากยังเกิน เกณฑ์ราว 10 วินาที ที่มนุษย์ยังคงรักษาความสนใจไว้ได้ ผลที่ผู้ใช้รับรู้ก็อาจมีจำกัด
  • หากงานถูกจำกัดเป็นหน่วยแบบจำนวนเต็ม เช่น วันละ 1 หรือ 2 งาน การปรับปรุงเพียง 25–50% อาจไม่พอ และเมื่อรวมเวลาเดินทางแล้ว แต่ละงานต้องใช้เวลา ไม่เกิน 4 ชั่วโมง จึงจะทำได้วันละ 2 งาน
  • ใน data pipeline ขั้นตอนที่ช้าจะสร้าง backpressure ไปยังส่วนต้นน้ำ ดังนั้นแม้บางขั้นตอนจะเร็วขึ้นมาก ก็อาจยังไม่เพิ่ม throughput แบบ end-to-end จนกว่าคอขวดทั้งหมดจะถูกคลี่คลาย
  • การประเมินการปรับปรุงประสิทธิภาพควรยึดตามผลลัพธ์ที่ต้องการ ไม่ใช่ benchmark ของแต่ละส่วน และหากยังไม่ข้ามข้อจำกัดอย่างการรักษาความสนใจ การเพิ่มจำนวนหน่วยงาน หรือ throughput โดยรวมได้ แม้การปรับปรุงครั้งใหญ่ก็อาจมีผลในทางปฏิบัติน้อย

ทำไมตัวเลขประสิทธิภาพกับผลลัพธ์จริงจึงไม่สอดคล้องกัน

  • งานด้านประสิทธิภาพเป็นงานที่คุ้มค่า เพราะช่วยทำให้ระบบมีประสิทธิภาพมากขึ้นและเปิดความเป็นไปได้ใหม่ให้ลูกค้า
  • ยังช่วยให้เข้าใจ เชิงประจักษ์ ว่าระบบซับซ้อนที่มีสเกลและโหลดทำงานสัมพันธ์กันอย่างไร
  • ระหว่างที่ลงมือใกล้ชิดกับระบบ ก็มักเกิดไอเดียในการปรับปรุงผลิตภัณฑ์และบริการ ซึ่งบางส่วนก็ไม่ได้เกี่ยวกับ performance optimization โดยตรง
  • แต่ถึงจะเป็นผลลัพธ์ที่ดูดีอย่าง “เร็วขึ้น 10 เท่า” หรือ “ลดทรัพยากรลง 50%” หากยังข้ามข้อจำกัดที่ซ่อนอยู่ไม่ได้ ก็อาจสร้างการเปลี่ยนแปลงตามที่คาดหวังได้ยาก

เกิน 10 วินาทีเมื่อไร ผู้ใช้ก็หลุดจากความสนใจ

  • มีกรณีที่ปรับปรุงประสิทธิภาพคิวรีของฐานข้อมูลใหม่ ทำให้คิวรีที่แพงที่สุดบนฐานข้อมูลเดิมจากเดิมใช้เวลา 5–10 นาที ลดลงเหลือ 30 วินาที–1 นาที
  • ผลลัพธ์นี้ถือว่าดีขึ้นระดับ 10 เท่า แต่หากจะเปลี่ยนประสบการณ์ผู้ใช้จริง ก็ยังต้องการการปรับปรุงครั้งใหญ่อีกครั้ง
  • งานวิจัยด้านปฏิสัมพันธ์มนุษย์-คอมพิวเตอร์มองว่าขีดจำกัดที่คนจะยังคงรักษาความสนใจต่อทั้งงานไว้ได้อยู่ที่ประมาณ 10 วินาที
    • 0.1 วินาที คือเกณฑ์ที่รับรู้ว่าเป็น feedback ทันที
    • ประมาณ 1 วินาที คือเกณฑ์ที่ flow ของงานยังต่อเนื่อง
    • ประมาณ 10 วินาที คือเกณฑ์ที่ยังรักษาความสนใจต่อทั้งงานไว้ได้
    • feedback อย่างตัวบอกความคืบหน้าหรือเวลาที่คาดไว้ ช่วยพยุงความสนใจได้
  • ทั้ง 30 วินาทีและ 5 นาทีต่างก็เกิน 10 วินาที ผู้ใช้จึงมักหันไปเช็กข้อความ ไปหยิบกาแฟ เริ่มคุยกับคนอื่น หรือสลับไปทำงานอย่างอื่น
  • หากผู้ใช้กลับมาอีกไม่กี่นาทีหรือหลายชั่วโมงต่อมาแล้วพบว่า UI โหลดเสร็จแล้ว เวลารอจริงจะเป็น 30 วินาทีหรือ 5 นาที ก็อาจไม่สร้างความต่างใหญ่ต่อรูปแบบการทำงาน
  • ในโปรเจ็กต์นั้น สุดท้ายสามารถลดคิวรีจำนวนมากให้เหลือ ต่ำกว่า 10 วินาที ได้ และยังทำให้บางคิวรีที่เดิมทำไม่ได้เพราะ timeout กลับมาทำได้
    • ไม่ได้มีแค่ latency ของ data query เท่านั้นที่สำคัญ แต่ latency ของ metadata query และเวลา render หน้าเว็บก็สำคัญต่อการปรับปรุงประสิทธิภาพโดยรวมเช่นกัน
    • ยังมีโอกาสปรับปรุงได้อีกระดับ 10 เท่าจาก asynchronous I/O และการปรับปรุง data aggregation ซึ่งหากทำได้ คิวรีที่เดิมใช้เวลาหลายนาทีอาจตอบกลับในเวลาไม่ถึง 1 วินาที

จุดเปลี่ยนจากวันละ 1 งานเป็น 2 งาน

  • ในโปรเจ็กต์หนึ่ง มีการลดทั้งกระบวนการจากหลายชั่วโมงให้เหลือ ต่ำกว่า 1 ชั่วโมงอย่างสม่ำเสมอ ด้วยการทำงาน manual ให้เป็นอัตโนมัติ ตัดขั้นตอนที่ไม่จำเป็น เพิ่มความขนานในบางส่วน และเลื่อนบางขั้นตอนไปทำแบบ asynchronous ในภายหลัง
  • แม้การปรับปรุงจะอยู่ราว 25–50% แต่กระบวนการทั้งหมดกลับยังไม่เปลี่ยนไปเพราะข้อจำกัดด้านโลจิสติกส์
  • ลองนึกถึงช่างประปา ช่างไฟ หรือช่างไม้ ที่ต้องนัดหมาย เดินทางไปยังสถานที่ และทำงานให้เสร็จ
    • หากทำงานวันละ 8 ชั่วโมง และงานในหนึ่งสถานที่ใช้เวลา 8 ชั่วโมง ต่อให้ประหยัดเวลาได้ 2–3 ชั่วโมง ก็ยังไม่มีเวลาพอจะเดินทางไปที่ใหม่และทำงานอีกงานให้เสร็จ
    • ถ้าแต่ละงานรวมเวลาเดินทางแล้วยังใช้เกิน 4 ชั่วโมง ก็จะยังทำได้ไม่ถึงวันละ 2 งาน
  • ก่อนจะข้ามเกณฑ์นี้ได้ การเพิ่มประสิทธิภาพในขั้นกลาง ๆ จะยังไม่แปลงเป็นการเพิ่มผลผลิต
  • อย่างไรก็ตาม การโฟกัสเรื่อง performance ก็อาจนำไปสู่ การปรับปรุงด้านคุณภาพและความเสถียร ที่ส่งผลโดยตรงต่อประสบการณ์ลูกค้าได้ด้วย
    • แม้การปรับปรุง performance เล็ก ๆ จะยังไม่ใช่จุดเปลี่ยนใน production แต่ก็อาจช่วยให้การวนรอบในสภาพแวดล้อมทดสอบเร็วขึ้น ทำให้พัฒนาฟีเจอร์และแก้บั๊กได้ไวขึ้น

คอขวดใน pipeline ที่มี backpressure

  • โครงสร้างพื้นฐานของซอฟต์แวร์ธุรกิจจำนวนมากประกอบด้วย data pipeline ที่ประมวลผล event จากหลายแหล่ง เช่น รถยนต์ อุปกรณ์ในโรงงาน โทรศัพท์มือถือ หรือธุรกรรมการเงิน
  • โดยทั่วไป event จะถูกเก็บไว้ใน log ที่คงทน และบริการปลายน้ำจะดึงไปประมวลผลต่อ
  • เพื่อรองรับขนาดใหญ่และ throughput สูง log จำเป็นต้องแบ่ง partition และบริการปลายน้ำก็มักใช้เทคนิคอย่าง batching, pipelining, parallelism, การจัดสรรหน่วยความจำอย่างมีประสิทธิภาพ และ dynamic scaling
  • คอขวดของ data pipeline หาได้ยาก เพราะพฤติกรรมของระบบแต่ละส่วนเชื่อมโยงกัน
    • ขั้นตอนที่ช้าจะจงใจสร้าง backpressure ไปยังขั้นตอนต้นน้ำ
    • หากมีคอขวดหลายจุด throughput โดยรวมจะยังไม่เพิ่มจนกว่าจะกำจัดคอขวดจุดสุดท้ายได้
  • การแบ่ง pipeline ออกเป็นหลายขั้นและทำความเข้าใจคุณลักษณะด้านประสิทธิภาพกับข้อจำกัดของแต่ละขั้น เป็นแนวปฏิบัติทางวิศวกรรมที่ดี
  • แต่ถึงจะปรับปรุงเพียงขั้นตอนเดียวให้ดีขึ้นหลายหลัก ก็อาจไม่ส่งผลต่อ throughput โดยรวมเลย
  • สำหรับการปรับปรุง throughput ตัวเลขที่สำคัญไม่ใช่ benchmark ของแต่ละขั้น แต่คือ throughput แบบ end-to-end

วิธีเชิงประจักษ์ในการหาคอขวด

  • หากต้องการเข้าใจพลวัตของระบบและคอขวดของระบบประเภทนี้ วิธีที่มีประโยชน์คือการตรวจสอบเชิงประจักษ์โดยเริ่มจากต้นทางของ pipeline
  • ตัวอย่างเช่น เริ่มจากขั้นตอนที่อ่าน event จาก distributed log แล้วทิ้งมันไปก่อน
    • ถ้าแค่ขั้นตอนนี้ยังไปไม่ถึง throughput เป้าหมาย การไป optimize ขั้นปลายน้ำก็เป็นการเสียเวลา
  • benchmark ฝั่งปลายน้ำ เช่น ฐานข้อมูลสามารถ insert ได้กี่แถวต่อวินาที ก็อาจยังสำคัญ แต่การวิเคราะห์ควรเริ่ม จากต้นน้ำ
  • การทำ simulation ก็เป็นวิธีที่มีคุณค่าในการทำความเข้าใจระบบซับซ้อนและประสิทธิภาพ

เกณฑ์ของการปรับปรุงประสิทธิภาพคือผลลัพธ์ที่ต้องการ

  • งานด้านประสิทธิภาพแม้จะยาก แต่ก็เป็นการฝึกให้เข้าใจระบบซับซ้อนอย่างลึกซึ้งและสร้างผลิตภัณฑ์ที่ดีกว่าเดิม
  • หากต้องการรักษาความสนใจของมนุษย์ไว้ ควรตอบสนองภายในประมาณ 10 วินาที
  • หากข้อจำกัดอยู่ที่หน่วยงานทั้งหมด การปรับปรุงแบบเป็นเปอร์เซ็นต์อย่างเดียวไม่พอ แต่ต้องข้ามจากวันละ 1 งานเป็น 2 งานได้จริง
  • หากต้องการเพิ่ม throughput ของ pipeline ที่มี backpressure ให้สูงสุด มักต้องแก้คอขวดทั้งหมด ไม่ใช่แค่หนึ่งหรือสองจุด
  • หากยังข้ามข้อจำกัดเหล่านี้ไม่ได้ แม้การปรับปรุงประสิทธิภาพระดับ 10 เท่าก็อาจไม่สร้างผลลัพธ์ตามที่ต้องการ

1 ความคิดเห็น

 
GN⁺ 6 시간 전
ความคิดเห็นบน Lobste.rs
  • ถ้าเป็นกรณีที่ปรับปรุงขั้นตอนหนึ่งได้หลายสิบเท่าแต่กลับผิดหวัง เพราะมันไม่มีผลต่อ throughput โดยรวม ก็ควรพูดถึง กฎของ Amdahl ที่นี่

    • สงสัยว่ามีอะไรคล้าย ๆ รวมรายชื่อกฎต่าง ๆ ในแวดวงวิทยาการคอมพิวเตอร์ทั้งหมดไหม
      ได้ยินกฎใหม่ ๆ อยู่เรื่อย ๆ แต่หลายอันเป็นเรื่องเฉพาะทางจนไม่ได้ใช้บ่อย เลยลืมไปอีก ไม่ได้หมายความว่ากฎเหล่านั้นไม่ถูกต้องหรือไม่มีประโยชน์ในฐานะความรู้สืบทอดระหว่างรุ่น
  • สงสัยตั้งแต่แรกว่าทำไมถึงไป optimize ส่วนที่กินเวลาโดยรวมเพียงเศษเสี้ยวเล็กมาก
    ไม่รู้ว่าเป็นเพราะ คำแนะนำไม่ดี หรือเครื่องมือวัด performance ไม่พอ คนที่ตั้งใจทำงานที่แทบไม่มีผลกระทบมีไม่มาก โดยปกติมักมีปัญหาใหญ่กว่านั้นซ่อนอยู่

    • เส้นทางหนึ่งที่ทำให้เรื่องแบบนี้เกิดขึ้น น่าจะประมาณนี้
      กำลังดูปัญหาบางอย่างอยู่ แล้วผล sampling แสดงให้เห็นว่าฟังก์ชันหนึ่งเด่นขึ้นมา พอดูคร่าว ๆ ก็เหมือนว่าจะปรับปรุง implementation ได้ค่อนข้างง่าย แต่ตอนนั้นกำลังทำงานอื่นอยู่ เลยเลื่อนไว้ว่า “ค่อยจัดการทีหลัง”
      ต่อมานึกถึงการปรับปรุงง่าย ๆ นั้นแล้วเริ่มลงมือ แต่พอแก้จริง ๆ กลับซับซ้อนกว่าที่คิด ก็เกิด tunnel vision และอยากแก้ปริศนาให้สำเร็จ จนใช้เวลาไปมาก
      ความจริงแล้วปัญหา performance นั้นเป็นเรื่องเล็กน้อยเท่านั้น มันอาจดูใหญ่ในเชิงสัดส่วนภายในบริบทที่กำลังดูอยู่ตอนนั้น หรือเวลาแบบ absolute อาจไม่มีความหมายมาก หรืออาจเป็นสถานการณ์ที่ติด I/O ไม่ใช่ CPU ก็ได้ คล้ายกับการโดน nerd sniping จากตัวเอง
    • ครั้งหนึ่งที่ Google มีข้อเสนอให้ optimize ส่วนหนึ่งของ pipeline และหลายคนอธิบายว่าส่วนนั้นคิดเป็น น้อยกว่า 0.1% ของปริมาณการคำนวณทั้งหมด ดังนั้นผลได้โดยรวมตามนิยามก็ต้องน้อยกว่า 0.1%
      แต่ก็ยังเพิกเฉยและเดินหน้า optimize ต่อ แล้วก็แปลกใจเมื่อผลปรับปรุงโดยรวมออกมาต่ำกว่า 0.1% ถ้ามีความรู้โดเมนก็จะรู้โดยสัญชาตญาณอยู่แล้วว่าส่วนนั้นไม่แพง แต่เพื่อไม่ให้เสียเวลา ยังช่วยวัดต้นทุน performance จริงให้ด้วย
    • อาจขับเคลื่อนด้วยการเดา หรือซึมซับ best practices ที่ใช้เสมอจนเป็นนิสัย หรือ generalize ปัญหาจริงที่เคยเห็นในสถานการณ์จำกัดมากเกินไป
      หรือ benchmark อาจทำให้เข้าใจผิดก็ได้ ไม่ใช่ทุกระบบจะแสดงต้นทุนของทุกเมธอดหรือโปรเซสใน production environment ได้ง่าย
      คำอธิบายเหล่านี้ทั้งหมดต่างก็ใกล้เคียงกับ dysfunction ในระดับมากน้อยต่างกัน บางอย่างใกล้เป็นปัญหาของบุคคล บางอย่างใกล้เป็นปัญหาของสภาพแวดล้อม
    • เหตุผลที่เป็นไปได้มีหลายข้อ
      1. วิศวกร junior ที่มีความสามารถได้เรียนรู้การแก้ปัญหาแล้ว แต่ยังไม่ได้เรียนรู้ วิธีเลือกปัญหาที่คุ้มค่าแก่การแก้ จึงโจมตีทุก inefficiency ที่พบโดยไม่สนผลกระทบแบบ end-to-end ถ้าโชคดีจะมีคนสอนให้ ไม่อย่างนั้นก็จะหยุดอยู่ที่การเป็นวิศวกร senior ที่ PM ต้องคุมเข้ม
      2. มอง performance แบบ end-to-end ไม่ได้อย่างถูกต้อง มี performance degradation อยู่ที่ไหนสักแห่งในระบบ ผู้บริหารก็กดดัน แต่ไม่ได้รับอำนาจให้ติดตั้ง monitoring ที่เหมาะสม จึงใช้การเดาไปแตะหลาย ๆ component แล้วหวังว่าจะมีอันหนึ่งถูก พอไฟไหม้เฉพาะหน้าดับลง ก็กลับไปปล่อยฟีเจอร์ผู้ใช้ต่อ
      3. ตอนนี้ยังไม่ใช่ปัญหา แต่กลัวว่าจะเป็นปัญหาในไม่ช้า จึงแก้ไว้ล่วงหน้า ถ้ามีอิทธิพลพอหรือสามารถดันให้ทำงานล่วงเวลาได้ ก็จะเดินหน้าทั้งที่ยังไม่เห็นผลทันที วิศวกรที่ยอดเยี่ยมก็ใช้ทุนทางการเมืองกับเรื่องแบบนี้ถ้าเชื่อว่ามันจะสำคัญในอนาคต ส่วนวิศวกรที่ไม่ดีนักก็เผามันจนหมด
        3.1. ถ้าทำงานที่ hyperscaler แค่ ลดปริมาณการคำนวณ 0.1% ที่ผู้ใช้มองไม่เห็นเลย ก็อาจมีผลต่อกำไรขาดทุนมากพอจะจ่ายค่าบ้านริมทะเลได้
      4. เป็นกรณีที่ทนต่อความท้าทายไม่ได้ รู้ดีว่าในทางปฏิบัติจะไม่มีอะไรเปลี่ยน แต่เบื่อกับการทำ CRUD app อย่างเดียว และได้โอกาสลองสิ่งที่เคยอ่านในบล็อก เหมือนเป็นการ nerd snipe ตัวเองเพื่อลดน้ำหนักของความไร้ความหมาย
    • ตรงข้ามกับความเชื่อทั่วไป ระบบจำนวนมากไม่ได้ประกอบด้วยคอขวดเพียงไม่กี่จุด
      แนวปฏิบัติการเขียนโปรแกรมที่พบได้ทั่วไปมักทำให้ทั้งระบบช้าอยู่แล้ว ตัวอย่างเช่นนึกถึงโค้ดเชิงวัตถุที่เต็มไปด้วย pointer และมี heap allocation ผ่าน allocator ทั่วไปจำนวนมหาศาล ไม่ว่าจะแก้ตรงไหนก็เป็นเพียงเศษเล็กของเวลารวม ในกรณีแย่ที่สุดก็แก้ไม่ได้เว้นแต่จะ rewrite ใหม่ทั้งหมด ถ้าโชคดีก็อาจ rewrite แบบค่อยเป็นค่อยไปได้
      ต่อให้มีคอขวดแค่สองจุด แต่ถ้าสองจุดนั้นอยู่ห่างกันไม่ถึงระดับหลายเท่าแบบเลขหลักเดียว แม้จะแก้คอขวดที่แย่ที่สุดได้สมบูรณ์ ก็ยังไม่ได้ improvement ถึงหลายเท่าแบบเลขหลักเดียวด้วยซ้ำ ในหลายกรณี อย่างที่บทความบอกไว้ ถ้าจะได้ผลลัพธ์ที่มีความหมาย ต้องก้าวข้ามให้มากกว่านั้นอีกมาก
      อีกอย่าง คอมพิวเตอร์ก็คล้ายกับระบบกระจายศูนย์ที่ทำงานขนานกัน มี CPU หลายตัว, GPU, ดิสก์, Ethernet ฯลฯ และความเร็วของโปรเซสถูกจำกัดโดยขั้นตอนที่ช้าที่สุดใน pipeline พอแก้ขั้นตอนนั้น ขั้นตอนที่ช้าที่สุดถัดไปก็จะเป็นตัวจำกัด และในกรณีแย่ที่สุด มีขั้นตอนที่ช้าที่สุดหลายขั้น แก้แค่อันเดียวก็ไม่ได้ประโยชน์อะไร
      ถึงอย่างนั้นนี่เป็นการตีความแบบให้ประโยชน์แห่งความสงสัย บางครั้งก็แค่หลงเข้าไปในเกม optimize จนเสีย ลำดับความสำคัญ หรือทำพลาด
  • แม้ผู้ใช้จะไม่สังเกตเห็น การ ลดเวลาคำนวณ ของซอฟต์แวร์ก็ยังเป็นเรื่องดี
    เพราะช่วยลดต้นทุนและทำให้ scale ได้ง่ายขึ้น

    • เรื่องนั้นขึ้นอยู่กับต้นทุนด้าน complexity
      ถ้าการทำให้โค้ดเร็วขึ้นแลกมาด้วย ความซับซ้อน ที่มากเกินไป ต่อให้ไม่นับ maintainability ก็จะมีผลตามมาในระยะยาวที่ทำร้าย performance ได้ เพราะเมื่อเปลี่ยนโครงสร้าง โค้ดที่ตอนนี้ไม่จำเป็นแล้วจะยังคงอยู่ และการจะเข้าใจหรือลบมันออกต้องเข้าใจความซับซ้อนทั้งหมดให้ครบถ้วน
      เหตุผลว่า “มันเร็วขึ้น” ไม่ควรเป็น ใบอนุญาตให้ละเลย ความกังวลเรื่อง complexity หรือ maintainability
  • ตอนนี้อยู่ในสถานการณ์คล้ายกัน และกำลังทำหลายโปรเจกต์เล็ก ๆ เพื่อลด query ที่เคยใช้เวลา 5 นาที ให้เหลือน้อยกว่า 30 วินาที
    บอกทีมอยู่ว่าในระยะยาวมันยังไม่พอ แต่แน่นอนว่านี่คือการปรับปรุงและมีผลกระทบมาก
    ในมุมมองลูกค้า การรอคอยลดจากระดับเดือดดาลเหลือแค่ระดับน่ารำคาญ
    โฟกัสตอนนี้ไม่ใช่ performance ต่อผู้ใช้แต่ละราย แต่เป็น performance โดยรวม ถ้า optimize โปรเซสจำนวนมากที่ใช้เวลา 5 นาที, 10 นาที, 30 นาทีได้ จะลด การแย่งชิงทรัพยากร กับส่วนอื่นของระบบลงได้มาก การกระหน่ำฐานข้อมูลเป็นเวลา 10 นาทีถือว่านานมาก และท้ายที่สุดทุกอย่างก็เร็วขึ้น ทุกคนได้ประโยชน์