bzip2 crate เปลี่ยนไปใช้การใช้งานด้วย Rust 100% แทน C
(trifectatech.org)bzip2crate 0.6.0 เลือกใช้libbz2-rs-sysซึ่งเป็นการใช้งานอัลกอริทึม bzip2 ด้วย Rust เป็นค่าเริ่มต้น ช่วยตัดการพึ่งพา C ออก และปรับปรุงทั้งความเร็วกับความสะดวกในการ cross-compile- bzip2 เป็นอัลกอริทึมเก่าที่มีการใช้งานลดลง แต่ โปรโตคอลและไลบรารี หลายตัวยังต้องรองรับเพื่อให้เป็นไปตามสเปก จึงยังคงอยู่ลึกใน dependency tree
- การใช้งานด้วย Rust ใช้ CPU cycles น้อยกว่า C ประมาณ 9.66~14.87% ในการบีบอัด และในการแตกไฟล์ก็ปรับปรุงขึ้น 4.48~10.00% ตลอดชุดทดสอบ
- การตัด C ออกทำให้การ build สำหรับ WebAssembly, Windows, Android ง่ายขึ้น และโดยค่าเริ่มต้นจะไม่ส่งออก symbol ของ
libbz2-rs-sysจึงลดความเสี่ยงของ symbol collision กับ dependency อื่น - การ audit พบและแก้บั๊กเชิงตรรกะแบบ off-by-one 1 รายการ รวมถึงปรับข้อจำกัดบางส่วนของ fuzzer และทำให้ไลบรารีกับแอปพลิเคชันระดับบนที่ใช้
bzip2สามารถรัน MIRI ได้ด้วย
การเปลี่ยน implementation เริ่มต้นของ bzip2 0.6.0
bzip2crate 0.6.0 ใช้libbz2-rs-sysซึ่งเป็นการใช้งานอัลกอริทึม bzip2 ด้วย Rust เป็นค่าเริ่มต้น- เมื่อตัด dependency C เดิมออก
bzip2crate จึงเร็วขึ้นและ cross-compile ได้ง่ายขึ้น libbz2-rs-syscrate สามารถ build เป็น ไลบรารี dynamic ของ C ได้ เพื่อให้โปรเจกต์ C ก็ใช้ประโยชน์จากการปรับปรุงนี้ได้- แม้ bzip2 จะไม่ค่อยถูกใช้งานมากในปัจจุบัน แต่โปรโตคอลและไลบรารีจำนวนมากยังต้องรองรับเพื่อให้เป็นไปตามสเปก และยังคงอยู่ลึกใน dependency tree ของหลายโปรเจกต์
- รายละเอียดการ implement ดูได้ในบทความก่อนหน้า Translating bzip2 with c2rust
ผลลัพธ์ด้านประสิทธิภาพที่ดีขึ้น
- โดยทั่วไป implementation ด้วย Rust เร็วกว่า implementation ด้วย C และในบางกรณีก็อยู่ในระดับใกล้เคียงกับประสิทธิภาพของ C
- เท่าที่ทราบ ไม่มีกรณีที่ช้ากว่าอย่างมีนัยสำคัญ
- ใน benchmark การบีบอัด CPU cycles ลดลงเมื่อเทียบกับ C
sample3.reflevel 1:38.51M→33.53M, -14.87%silesia-small.tarlevel 1:3.43G→3.00G, -14.30%silesia-small.tarlevel 9:3.47G→3.17G, -9.66%levelของ bzip2 หมายถึงปริมาณหน่วยความจำใช้งาน และไม่มีผลมากนักต่อประสิทธิภาพsample3.refจัดสรรหน่วยความจำมากกว่าขนาดไฟล์ตั้งแต่ level 1 แล้ว ดังนั้น level ที่สูงกว่าจึงเกี่ยวข้องน้อย
- ประสิทธิภาพการแตกไฟล์ก็ดีขึ้นตลอดชุดทดสอบ
sample3.bz2: -4.48%sample1.bz2: -8.63%sample2.bz2: -7.67%dancing-color.ps.bz2: -5.17%re2-exhaustive.txt.bz2: -7.65%zip64support.tar.bz2: -10.00%
- บนเครื่อง benchmark ที่ใช้ macOS บางครั้งตัวเลขประสิทธิภาพการแตกไฟล์ออกมาต่ำ
- ยังไม่ทราบสาเหตุ และบน macOS การทำให้เครื่องมือติดตามประสิทธิภาพแบบ
perfทำงานอัตโนมัติทำได้ยาก
- ยังไม่ทราบสาเหตุ และบน macOS การทำให้เครื่องมือติดตามประสิทธิภาพแบบ
การ build และการลดปัญหา symbol collision
- การ cross-compile โปรเจกต์ Rust ที่มี dependency C มักทำงานได้ทันทีด้วย
cccrate แต่ถ้าล้มเหลว การ debug ข้อผิดพลาดอาจทำได้ยาก- การ link กับไลบรารีของระบบก็อาจสร้างปัญหาที่สับสนและทำซ้ำได้ยาก
- การ compile bzip2 เป็น WebAssembly มีปัญหามานานแล้ว
- เมื่อตัด dependency C ออกและใช้เฉพาะโค้ด Rust การ build สำหรับ WebAssembly, Windows, Android จึงทำงานได้ง่ายขึ้น
- โดยค่าเริ่มต้น
libbz2-rs-sysจะไม่ export symbol- หากใช้ dependency C ต้อง export symbol เพื่อให้บล็อก
externของ Rust หาเจอ - ชื่อที่ export อาจชนกันเมื่อ dependency อื่นประกาศ symbol เดียวกัน
- หากโปรเจกต์ Rust ต้องการ export symbol ก็เปิดใช้ได้ด้วย feature flag
- หากใช้ dependency C ต้อง export symbol เพื่อให้บล็อก
ผลการตรวจสอบและ audit
- implementation ของ bzip2 ที่มีประสิทธิภาพจำเป็นต้องมี unsafe code บางส่วน และการจำลอง interface ของ C ด้วย Rust ต้องใช้ unsafe code มากขึ้น
- โค้ดดังกล่าวสามารถรันใน MIRI ได้
- ไลบรารีระดับสูงหรือแอปพลิเคชันที่ใช้
bzip2ตอนนี้ก็สามารถรันด้วย MIRI ได้เช่นกัน
- การ audit พบ บั๊กเชิงตรรกะแบบ off-by-one 1 รายการ และแก้ข้อจำกัดบางส่วนของ fuzzer
- นอกเหนือจากนั้นไม่มีประเด็นสำคัญที่พบ
- การ audit ดำเนินการโดย Radically Open Security และรายงานฉบับเต็มดูได้ที่ รายงาน audit PDF
- งานครั้งนี้ได้รับความช่วยเหลือจาก Alex Crichton ผู้ดูแล
bzip2crate, Radically Open Security ที่ให้การ audit และความเชี่ยวชาญ, และ NLnet Foundation ซึ่งให้ทุนสนับสนุนผ่าน e-Commons Fund
ยังไม่มีความคิดเห็น