3 คะแนน โดย GN⁺ 2025-06-19 | 1 ความคิดเห็น | แชร์ทาง WhatsApp
  • crate bzip2 แทนที่ การพึ่งพาโค้ด C ทั้งหมด 100% ด้วยอิมพลีเมนเทชัน Rust
  • ประสิทธิภาพ โดยรวมดีขึ้นจากเดิม และคอมไพล์ข้ามแพลตฟอร์มได้ง่ายขึ้น
  • อิมพลีเมนเทชัน Rust ปรับปรุงทั้งความเร็วในการบีบอัดและคลายการบีบอัดเมื่อเทียบกับ เวอร์ชัน C
  • ปัญหาการพึ่งพาไลบรารี เช่น การชนกันของสัญลักษณ์ ลดลงอย่างมาก
  • ผ่านการตรวจสอบความปลอดภัยและแก้ไข บั๊กเชิงตรรกะที่สำคัญ แล้ว จึงยืนยันความเสถียรได้

เปิดตัว bzip2 crate 0.6.0 และเปลี่ยนสู่ Rust

  • วันนี้มีการปล่อย bzip2 เวอร์ชัน 0.6.0
  • ตอนนี้โดยค่าเริ่มต้นจะใช้อิมพลีเมนเทชันอัลกอริทึม bzip2 บนพื้นฐาน Rust ที่พัฒนาขึ้นเองคือ libbz2-rs-sys
  • การเปลี่ยนแปลงนี้ทำให้ bzip2 crate เร็วขึ้นและคอมไพล์ข้ามแพลตฟอร์มได้ง่ายขึ้น
  • crate libbz2-rs-sys สามารถบิลด์เป็นไลบรารีไดนามิกแบบ C ได้ด้วย ทำให้โปรเจกต์ C สามารถใช้ประโยชน์จากประสิทธิภาพที่ดีขึ้นนี้ได้

ทำไมถึงมีการเปลี่ยนแปลงนี้?

  • อัลกอริทึม bzip2 ถูกสร้างขึ้นในยุค 90 และแม้ปัจจุบันจะไม่ได้ใช้อย่างแพร่หลายแล้ว แต่ยังจำเป็นต่อ การทำตามสเปก ในหลายโปรโตคอลและไลบรารี
  • หลายโปรเจกต์อาจไม่ได้พึ่งพา bzip2 โดยตรง แต่ก็ยังพึ่งพาอยู่ลึกลงไปใน dependency tree
  • จากประสบการณ์ที่สะสมมาจาก zlib-rs เราจึงทำให้อิมพลีเมนเทชัน bzip2 ทันสมัยขึ้นในครั้งนี้
  • รายละเอียดการอิมพลีเมนต์ libbz2-rs-sys กล่าวไว้ในบล็อกโพสต์ก่อนหน้าแล้ว ที่นี่จะดูเฉพาะ ข้อดี ของการเปลี่ยนแปลงครั้งนี้

ประสิทธิภาพที่ดีขึ้น

  • อิมพลีเมนเทชัน Rust โดยรวมให้ ประสิทธิภาพ สูงกว่า เวอร์ชัน C
  • ในบางกรณีอาจได้ผลลัพธ์ใกล้เคียงกัน แต่ไม่มีกรณีที่ช้ากว่า
  • ประสิทธิภาพการบีบอัด: bzip2 มีตัวเลือก level แต่ส่งผลต่อประสิทธิภาพไม่มากนัก
  • จากผลทดสอบกับไฟล์ตัวอย่างหลัก เวอร์ชัน Rust เร็วขึ้นมากกว่า 10%

การบีบอัด:

ไฟล์ C(รอบการทำงาน) Rust(รอบการทำงาน) การเปลี่ยนแปลงสัมพัทธ์
sample3.ref (level 1) 38.51M 33.53M -14.87%
silesia-small.tar (level 1) 3.43G 3.00G -14.30%
silesia-small.tar (level 9) 3.47G 3.17G -9.66%

ในการคลายการบีบอัดก็แสดงให้เห็นว่าประสิทธิภาพดีขึ้นในทุกกรณี:

ไฟล์ C(รอบการทำงาน) Rust(รอบการทำงาน) การเปลี่ยนแปลงสัมพัทธ์
sample3.bz2 2.53M 2.42M -4.48%
sample1.bz2 9.63M 8.86M -8.63%
sample2.bz2 20.47M 19.02M -7.67%
dancing-color.ps.bz2 87.46M 83.16M -5.17%
re2-exhaustive.txt.bz2 1.89G 1.76G -7.65%
zip64support.tar.bz2 2.32G 2.11G -10.00%

อย่างไรก็ตาม ในสภาพแวดล้อม macOS บางครั้งอาจมีการเปลี่ยนแปลงของตัวเลขการคลายการบีบอัดเกิดขึ้น ซึ่งวิเคราะห์ได้ยากจากข้อจำกัดของเครื่องมือวัดประสิทธิภาพ

รองรับการคอมไพล์ข้ามแพลตฟอร์ม

  • การคอมไพล์ข้ามแพลตฟอร์มของโปรเจกต์ Rust ที่มี dependency เป็น C มักทำงานได้ดีเพราะอาศัย crate cc แต่หากล้มเหลวจะดีบักได้ยากมาก
  • ในขั้นตอนลิงก์กับ system library มักเกิดปัญหาที่ไม่คาดคิดได้ง่าย และในบางสภาพแวดล้อมรวมถึงการบิลด์ WebAssembly ก็กลายเป็นอุปสรรคจริงจัง
  • การเปลี่ยนมาใช้อิมพลีเมนเทชัน Rust ทำให้ปัญหาที่เกี่ยวข้องกับ C หายไปทั้งหมด
  • ตอนนี้สามารถคอมไพล์ข้ามแพลตฟอร์มไปยัง Windows, Android, WebAssembly และอื่น ๆ ได้โดยไม่มีข้อสังเกตพิเศษ
  • นี่เป็นข้อดีใหญ่ไม่ใช่แค่ต่อประสบการณ์ผู้ใช้ แต่รวมถึงมุมมองด้านการบำรุงรักษาด้วย

ไม่มีการชนกันของสัญลักษณ์ (export) โดยค่าเริ่มต้น

  • ในกรณี dependency แบบ C จำเป็นต้อง export สัญลักษณ์จากบล็อกภายนอกของ Rust ทำให้หาก dependency อื่น export สัญลักษณ์เดียวกันก็จะเกิดการชนกัน
  • libbz2-rs-sys ถูกออกแบบมาให้ ไม่ export สัญลักษณ์โดยค่าเริ่มต้น
  • ดังนั้นจึงไม่เกิดปัญหาสัญลักษณ์ชนกับไลบรารีภายนอกอื่น ๆ และหากจำเป็นก็สามารถเปิด export ได้ผ่าน feature flag

รันการทดสอบบนพื้นฐาน MIRI

  • หากต้องการอิมพลีเมนต์ bzip2 ใน Rust ให้มีประสิทธิภาพสูง ก็เลี่ยงการใช้ unsafe code ไม่ได้ และการจำลองอินเทอร์เฟซ C ก็ต้องใช้ unsafe code จำนวนมากเช่นกัน
  • โชคดีที่สามารถรันและทดสอบโค้ดนี้ในสภาพแวดล้อม MIRI ได้
  • ยิ่งไปกว่านั้น ตอนนี้ไลบรารีหรือแอปพลิเคชันระดับบนที่ใช้ bzip2 ก็สามารถทดสอบด้วย MIRI ได้เช่นกัน

สรุป

ตอนนี้ bzip2 crate เร็วขึ้นแล้ว และมอบประสบการณ์ที่ดีขึ้นอย่างเป็นธรรมชาติจนแทบไม่ต้องใส่ใจมันอีกต่อไป

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

 
GN⁺ 2025-06-19
ความคิดเห็นจาก Hacker News
  • เมื่อพิจารณาความเป็นไปได้ที่อิมพลีเมนเทชันของ Trifecta Tech จะมาแทนที่อิมพลีเมนเทชันทางการที่ลินุกซ์ดิสทริบิวชันใช้อยู่ ก็มีความเห็นว่าไม่ใช่เรื่องเป็นไปไม่ได้ เพราะก่อนหน้านี้ Fedora ก็เคยเปลี่ยนจาก Adler zlib เดิมไปเป็น zlib-ng มาแล้ว โดยประเด็นสำคัญคือแค่ต้องมี C ABI ที่เข้ากันได้กับต้นฉบับ
    • หากตั้งแต่ปี 2019 เป็นต้นมาไม่มี upstream release อีกเลย ก็มีการตั้งคำถามว่าอิมพลีเมนเทชันนี้อาจถือว่าเสร็จสมบูรณ์แล้วหรือไม่ ถ้าไม่มีบั๊กให้แก้หรือฟีเจอร์ให้เพิ่มอีก ก็อาจเพียงพอแล้วในตัวมันเอง
    • มีความเห็นว่าการเปลี่ยนลักษณะนี้มีโอกาสเกิดขึ้นได้มากพอ เพราะ Ubuntu ใช้ sudo ที่เขียนด้วย Rust อยู่แล้ว
    • มีความเห็นว่า Trifecta Tech จัดเตรียม C ABI ที่เข้ากันได้ไว้ค่อนข้างดี แต่สุดท้ายก็ต้องมีใครสักคนลงมือทำงานนี้จริง การเปลี่ยนแปลงจึงจะเกิดขึ้น
    • มีการกล่าวถึงว่าเป้าหมายของ uutils ก็อยู่ที่การเป็นตัวแทนทางการในลักษณะนี้เช่นกัน พร้อมแชร์ลิงก์ หน้าเว็บ uutils
    • จากที่ลองดูคร่าว ๆ พบว่ามีการตั้งค่า cargo-c อยู่แล้วจึงดูเป็นสัญญาณที่ดี แต่เนมสเปซต่างกัน ทำให้โปรแกรม C ยังไม่สามารถตรวจพบเป็น libbz2 เดิมโดยอัตโนมัติได้ อีกทั้งยังไม่คุ้นกับสัญลักษณ์ของ bzip2 มากพอ จึงบอกได้ยากว่าเข้ากันได้ในระดับ ABI จริงหรือไม่ และเพราะการดูแลอิมพลีเมนเทชันของ GNU operating system โดยตรงใช้เวลามาก จึงบอกว่าหากมีเวลาว่างก็ยินดีรับ PR ในโปรเจ็กต์เชิงทดลอง platypos
  • ฉันกำลังใช้ crate นี้ประมวลผลข้อมูล Common Crawl หลายร้อย TB อยู่ และพอใจกับความเร็วที่เพิ่มขึ้นมาก
    • มีการตั้งคำถามว่าทำไมถึงยังใช้ bz2 ในงานนี้ ได้ยินมาว่าถ้าจะทำการแปลงข้อมูลขนาดใหญ่เพียงครั้งเดียว การเปลี่ยนไปใช้ zstd จะได้ประโยชน์มาก และยิ่งอัตราการบีบอัดสูงเท่าไร ก็ยิ่งดีกว่า bzip2 แทบทุกด้าน
    • มีคำถามว่าข้อมูล Common Crawl เปิดเผยในรูปแบบทอร์เรนต์หรือไม่
    • มีการแชร์ความเห็นว่าการปรับปรุงความเร็วในการบีบอัด 14% นั้นถือว่ายอดเยี่ยมทีเดียว
  • มีคนสงสัยว่าอิมพลีเมนเทชันนี้แก้ CVE ที่ยังค้างอยู่ 11 รายการโดยปริยายหรือไม่ และชี้ให้เห็นอย่างประชดเล็กน้อยว่า crate bzip2 เองก็เคยมีการรายงาน CVE เช่นกัน พร้อมแชร์ ลิงก์ที่เกี่ยวข้อง
    • มีความเห็นว่าน่าสนใจที่เมื่อเทียบกันแล้ว ช่องโหว่ประเภท “รันไทม์ล้มเหลวกับไฟล์ขนาดใหญ่” ที่รายงานใน crate นี้ แตกต่างจากปัญหา “bounds miss” ในเวอร์ชันที่เขียนด้วย C และตั้งคำถามว่าช่องโหว่แบบ bounds miss เหล่านี้จะนำไปสู่การรันโค้ดได้จริงหรือไม่
    • มีการอ้างข้อความว่า “crate bzip2 มีช่องโหว่ในเวอร์ชันก่อน 0.4.4” พร้อมเสริมข้อมูลว่าในวันนี้มีการออกเวอร์ชัน 0.6.0
  • ต่อคำถามว่า “ทำไมต้องไปปรับปรุงอัลกอริทึมจากยุค 90” ก็มีความเห็นว่าอยากรู้ว่าปัจจุบันนิยมใช้อัลกอริทึมอะไรบ้าง โดยยก zstd ขึ้นมาและแชร์ ลิงก์เบนช์มาร์กเปรียบเทียบอัลกอริทึมบีบอัด
  • มีการตั้งคำถามว่าถ้าแบ็กเอนด์สำหรับ codegen ของคอมไพเลอร์ C และ Rust เป็นตัวเดียวกัน แล้วประสิทธิภาพที่เพิ่มขึ้นเกิดขึ้นได้อย่างไร พร้อมเสนอความเป็นไปได้หลายอย่าง เช่น auto-simd ของ Rust, การปรับแต่งด้วยมือ หรือการใช้ไลบรารีปรับแต่งแบบใหม่
    • เป็นการคาดเดาว่า Rust อาจให้คำใบ้กับตัวสร้างโค้ดได้มากกว่า ยกตัวอย่างเช่น ต่างจากพอยน์เตอร์ใน C ที่ต้องกังวลเรื่อง aliasing มากกว่า โดยแชร์ ลิงก์อธิบายเรื่อง aliasing
    • มีความเห็นว่า C เป็นภาษาที่ไม่ค่อยเหมาะนักสำหรับการเขียนโค้ดสมรรถนะสูงสมัยใหม่ โดยชี้ว่าในช่วงราว 20 ปีตั้งแต่ C99 ถึง C21 ตัวภาษาเองขาดความสามารถในการใช้คำสั่งใหม่ ๆ เช่น clz, popcnt, clmul, pdep เป็นต้น ในแบบที่สะอาด และประเมินว่าการรองรับคำสั่งเชิงนามธรรมเหล่านี้ช่วยการปรับแต่งโค้ดประเภทนี้ได้มาก
    • มีความเห็นว่าการเขียนใหม่ไม่ว่าจะด้วยภาษาใดก็ตามล้วนเป็นโอกาสในการเพิ่มความเร็ว และไม่ใช่การรับประกันความเร็วที่มีเฉพาะ Rust เท่านั้น
  • มีความหวังว่า Prossimo หรือคนอื่น ๆ จะช่วยเขียนใหม่ในลักษณะคล้ายกันสำหรับโปรโตคอลอินเทอร์เน็ตหลัก ๆ (เช่น BGP, OSPF, RIP) รวมถึงอิมพลีเมนเทชันด้าน routing และ DNS server
    • มีการแนะนำกองทุนที่ช่วงไม่กี่ปีมานี้สนับสนุนการรีไรต์เครื่องมือแกนหลักของอินเทอร์เน็ตและระบบปฏิบัติการด้วยภาษาแบบปลอดภัยอย่าง Rust พร้อมลิงก์ โครงการ NLnet และ Sovereign Tech Fund และยก โครงการ BGP in Rust เป็นตัวอย่างเพิ่มเติม
    • Memory Safety Initiative ก็แนะนำความพยายามในการรีไรต์บริการสำคัญอย่าง TLS และ DNS อย่างปลอดภัย ซึ่งมีบริบทสอดคล้องกับข้อเสนอของฉันบางส่วน
    • มีการเล่าว่านักพัฒนาคนหนึ่งสร้าง Ironsides DNS ด้วย SPARK Ada ซึ่งเป็นภาษาที่รองรับการพิสูจน์เชิงรูปนัยได้เข้มแข็งกว่า
  • มีความเห็นว่าบน macOS แม้ไม่มี perf profiler ก็ยังวิเคราะห์ประสิทธิภาพได้ดีพอด้วย dtrace โดยสคริปต์ flame graph ต้นฉบับที่เขียนด้วย Perl ก็ใช้ dtrace และ flame graph ฉบับเขียนใหม่ด้วย Rust ก็ใช้แนวทางเดียวกัน แม้จะขาดเมตริกบางอย่างอย่าง cache miss หรือ micro instruction retired แต่ก็ยังมีประโยชน์มาก
  • มีความเห็นเชิงล้อเล่นว่าควรเขียน Rust ใหม่อีกครั้งด้วย Javascript
  • มีคำถามว่ารองรับการคลายบีบอัดแบบขนานเหมือน lbzip2 หรือไม่ หรือรองรับการประมวลผลขนานผ่านวิธีอย่าง block magic pre-scan หรือไม่ และมีการแก้ไขเพิ่มเติมภายหลังว่าสรุปแล้ว “น่าจะยังไม่รองรับ”
  • มีการเล่าประสบการณ์ว่า Lbzip2 ให้ความเร็วในการคลายบีบอัดที่สูงมากด้วยการใช้ทุกคอร์ของ CPU อย่างเต็มที่ และแสดงความเสียดายว่าปี 2025 แล้วแต่โปรแกรมสำคัญจำนวนมากอย่าง Python ก็ยังใช้ได้แค่คอร์เดียว
    • มีคนชี้ว่าไม่ค่อยเข้าใจสถานการณ์ของ Python เท่าไร