คลังข้อมูล less_slow.cpp ได้จุดประกายการสนทนาในหมู่นักพัฒนาเกี่ยวกับความแตกต่างของการปรับปรุงประสิทธิภาพในสภาพแวดล้อมการประมวลผลที่แตกต่างกัน แม้ว่าคลังข้อมูลนี้จะมุ่งเน้นไปที่การประมวลผลประสิทธิภาพสูงสำหรับสภาพแวดล้อมเดสก์ท็อปและเซิร์ฟเวอร์ แต่ข้อเสนอแนะจากชุมชนได้เน้นย้ำว่ากลยุทธ์การปรับปรุงประสิทธิภาพต้องปรับตัวให้เข้ากับข้อจำกัดของฮาร์ดแวร์ที่แตกต่างกันอย่างมาก
ข้อจำกัดด้านทรัพยากรนำไปสู่การจัดลำดับความสำคัญในการปรับปรุงประสิทธิภาพที่แตกต่างกัน
การทดสอบประสิทธิภาพของคลังข้อมูลแสดงให้เห็นถึงการเพิ่มประสิทธิภาพที่น่าประทับใจผ่านเทคนิค C++ ต่างๆ แต่นักพัฒนาที่ทำงานกับไมโครคอนโทรลเลอร์กลับเผชิญกับความท้าทายที่แตกต่างกันโดยสิ้นเชิง นักพัฒนาคนหนึ่งได้แบ่งปันประสบการณ์การทำงานกับระบบฝังตัวที่มีหน่วยความจำฮีปเพียง 256 KiB และสแต็ก 4 KiB ซึ่งแม้แต่ไลบรารี C++ สมัยใหม่อย่าง CTRE (Compile Time Regular Expressions) ก็สามารถทำให้เกิดสแต็กโอเวอร์โฟลว์ได้:
ฉันเคยลองตรวจสอบความถูกต้องของสตริงสำหรับการกำหนดค่าพร็อกซี HTTP ด้วย regex แบบละเอียด CTRE พยายามจัดสรรสแต็กขนาด 5 KiB จาก 40 เฟรมการเรียกและทำให้ระบบฝังตัวเกิดข้อผิดพลาดจากสแต็กโอเวอร์โฟลว์ ฉันต้องลบการตรวจสอบพอร์ตออกจาก regex และตรวจสอบส่วนนั้นด้วยตนเองแทน
สิ่งนี้แสดงให้เห็นว่าการจัดลำดับความสำคัญในการปรับปรุงประสิทธิภาพเปลี่ยนแปลงอย่างมากตามข้อจำกัดของฮาร์ดแวร์ ในขณะที่นักพัฒนาเดสก์ท็อปอาจมุ่งเน้นที่ปริมาณการประมวลผล นักพัฒนาระบบฝังตัวต้องให้ความสำคัญกับการใช้หน่วยความจำ ความลึกของสแต็ก และขนาดของโปรแกรม
ข้อพิจารณาสำคัญในการปรับแต่งประสิทธิภาพตามสภาพแวดล้อม
ไมโครคอนโทรลเลอร์:
- ข้อจำกัดด้านหน่วยความจำ (เช่น หน่วยความจำ heap 256 KiB, stack 4 KiB)
- ข้อจำกัดขนาดของโปรแกรม
- ปัญหาการแบ่งแยกหน่วยความจำแบบไดนามิก
- ข้อกำหนดด้านเวลาจริง/ความแปรปรวน
GPU:
- การจัดการลำดับชั้นหน่วยความจำ (50 KB constant, 50 MB shared, 50 GB global)
- การแสดงผลแบบบีบอัด
- รูปแบบการเข้าถึงหน่วยความจำแบบรวมกลุ่ม
ตัวเลือกประสิทธิภาพของ Regular Expression:
- CTRE: ประสิทธิภาพดีแต่ขึ้นอยู่กับคอมไพเลอร์
- HyperScan: ประสิทธิภาพสูงสุดสำหรับ x64 เฉพาะทางสำหรับ NIDS
- RE2: ประสิทธิภาพทั่วไปที่ดี
- PCRE2 ในโหมด JIT: ประสิทธิภาพที่ดีและสามารถพกพาได้
ความท้าทายในการเขียนโปรแกรมแบบ Async:
- ต้นทุนการทำงานสูงของแอบสแทรคชัน coroutine
- ขาดคำสั่ง CPU สำหรับการสลับบริบทแบบเบา
- ความแตกต่างของประสิทธิภาพระหว่างการใช้งานใน C++, Rust และ Python
รูปแบบที่คล้ายกันในระดับที่แตกต่างกัน
น่าสนใจที่รูปแบบการปรับปรุงประสิทธิภาพบางอย่างยังคงสอดคล้องกันในระดับการประมวลผลที่แตกต่างกัน ผู้มีส่วนร่วมในคลังข้อมูลสังเกตว่าการปรับปรุงประสิทธิภาพที่มุ่งเน้นหน่วยความจำที่คล้ายกันสามารถนำไปใช้เมื่อทำงานกับ GPU ซึ่งมีลำดับชั้นของหน่วยความจำที่มีข้อจำกัดที่สำคัญเมื่อเทียบกับสภาพแวดล้อม CPU:
คุณมีหน่วยความจำคงที่เพียง ~50 KB หน่วยความจำร่วมเพียง ~50 MB และหน่วยความจำรวมเพียง ~50 GB มันใหญ่เมื่อเทียบกับไมโครคอนโทรลเลอร์ แต่น้อยมากเมื่อเทียบกับขอบเขตของปัญหาที่มักแก้ไขบน GPU ดังนั้นการปรับปรุงประสิทธิภาพจำนวนมากจึงเกี่ยวข้องกับการแสดงข้อมูลแบบบีบอัดและการเข้าถึงหน่วยความจำแบบรวมกลุ่ม
รูปแบบการทำงานภายใต้ข้อจำกัดของหน่วยความจำนี้ปรากฏในสภาพแวดล้อมการประมวลผลต่างๆ ตั้งแต่ไมโครคอนโทรลเลอร์ขนาดเล็กไปจนถึง GPU ประสิทธิภาพสูง ซึ่งแสดงให้เห็นว่าความเข้าใจเกี่ยวกับลำดับชั้นของหน่วยความจำยังคงเป็นพื้นฐานสำหรับการปรับปรุงประสิทธิภาพโดยไม่คำนึงถึงขนาด
ปัญหาของ Coroutine
การสำรวจโมเดลการเขียนโปรแกรมแบบอะซิงโครนัสของคลังข้อมูลได้สร้างความสนใจเป็นพิเศษเกี่ยวกับ coroutine และผลกระทบต่อประสิทธิภาพในทางปฏิบัติ แม้ว่า coroutine จะมีความน่าดึงดูดในทางทฤษฎีสำหรับการปรับปรุงความอ่านง่ายของโค้ดในการเขียนโปรแกรมแบบอะซิงโครนัส แต่ประสิทธิภาพในโลกแห่งความเป็นจริงยังคงเป็นข้อกังวล
เมื่อถูกถามเกี่ยวกับเรื่องอะซิงโครนัสของ C++ สำหรับ io_uring ผู้เขียนคลังข้อมูลแสดงความผิดหวัง: น่าเสียดายที่ไม่ใช่ ฉันชอบคำสัญญาเรื่อง 'การใช้งานง่าย' ของ coroutine... แต่การทดลองของฉันแสดงให้เห็นว่าต้นทุนในการรันไทม์ของนามธรรมคล้าย coroutine ส่วนใหญ่นั้นสูงเกินไป
การประเมินอย่างปฏิบัตินิยมนี้ท้าทายสมมติฐานทั่วไปที่ว่าคุณสมบัติภาษาสมัยใหม่จะแปลเป็นประสิทธิภาพที่ดีขึ้นโดยอัตโนมัติ ผู้เขียนยังแนะนำว่าคำสั่ง CPU ใหม่ที่ออกแบบมาโดยเฉพาะสำหรับการทำงานแบบอะซิงโครนัสและการสลับบริบทแบบเบาอาจมีผลกระทบมากกว่าการปรับปรุง SIMD และการประมวลผลแบบซูเปอร์สกาลาร์
ความประหลาดใจในประสิทธิภาพของ Regular Expression
การสนทนาของชุมชนเปิดเผยสิ่งที่น่าประหลาดใจเกี่ยวกับประสิทธิภาพของ regular expression การทดสอบประสิทธิภาพของคลังข้อมูลแสดงให้เห็นว่า CTRE (Compile Time Regular Expressions) ให้ผลลัพธ์ที่ดีเกินคาด ซึ่งท้าทายการรับรู้ของนักพัฒนาบางคนที่มองว่ามันเป็นเพียงกลเม็ดมากกว่าเครื่องมือที่ใช้งานได้จริง
อย่างไรก็ตาม ประสิทธิภาพแตกต่างกันอย่างมีนัยสำคัญระหว่างคอมไพเลอร์ โดย MSVC มีปัญหากับเทคนิคเมตาโปรแกรมมิ่งที่ใช้ สำหรับสภาพแวดล้อมการผลิตที่ต้องการประสิทธิภาพ regex สูงสุด มีการแนะนำทางเลือกอย่าง HyperScan ของ Intel ว่าอาจเร็วกว่า Boost ถึง 10 เท่าในกรณีทั่วไป แม้ว่าจะมีข้อควรระวังเกี่ยวกับการมุ่งเน้นเฉพาะในระบบตรวจจับการบุกรุกเครือข่ายและขาดการสนับสนุน Unicode
การสนทนาเน้นย้ำว่าการทดสอบประสิทธิภาพเชิงประจักษ์ยังคงมีความสำคัญ เนื่องจากสมมติฐานทางทฤษฎีเกี่ยวกับประสิทธิภาพมักไม่ตรงกับผลลัพธ์ในโลกแห่งความเป็นจริงในคอมไพเลอร์และสภาพแวดล้อมที่แตกต่างกัน
การปรับปรุงประสิทธิภาพยังคงเป็นศาสตร์ที่มีความละเอียดอ่อนซึ่งต้องอาศัยความเข้าใจในข้อจำกัดเฉพาะของสภาพแวดล้อมเป้าหมาย ในขณะที่คลังข้อมูล less_slow.cpp ให้ข้อมูลเชิงลึกที่มีคุณค่าสำหรับสภาพแวดล้อมเดสก์ท็อปและเซิร์ฟเวอร์ การสนทนาของชุมชนเน้นย้ำว่ากลยุทธ์การปรับปรุงประสิทธิภาพต้องปรับตัวให้เข้ากับความท้าทายเฉพาะของบริบทการประมวลผลแต่ละแบบ ไม่ว่าจะเป็นไมโครคอนโทรลเลอร์ที่มีทรัพยากรจำกัด GPU เฉพาะทาง หรือเซิร์ฟเวอร์ประสิทธิภาพสูง
อ้างอิง: Learning to Write Less Slow C, C++, and Assembly Code
![]() |
---|
ภาพหน้าจอของที่เก็บข้อมูล GitHub 'less_slowcpp' แสดงให้เห็นโครงสร้างโค้ดและโครงสร้างที่เกี่ยวข้องกับการอภิปรายเรื่องการเพิ่มประสิทธิภาพการทำงาน |