mold 2.0.0 - ลิงเกอร์ความเร็วสูง
(github.com/rui314)- เปลี่ยนไลเซนส์จาก AGPL เป็น MIT ซึ่งเป็นการเปลี่ยนแปลงสำคัญของ mold 2.0.0
- แก้ไขบั๊กที่ทำให้ไม่สามารถสร้างไฟล์อ็อบเจ็กต์ที่มีเซกชันเกิน 65520 รายการได้เมื่อใช้
--relocatable -undefinedถูกตีความเป็นคำพ้องของ--undefinedแทน-u ndefinedเพื่อให้สอดคล้องกับการทำงานของ GNU linkers และ LLVM lld-nopieถูกจัดการเป็นคำพ้องของ--no-pie- รองรับรีโลเคชันประเภท
R_RISCV_SET_ULEB128และR_RISCV_SUB_ULEB128บน RISC-V - รองรับรีโลเคชันประเภท
R_PPC64_REL32บน PPC64
1 ความคิดเห็น
ความคิดเห็นจาก Hacker News
mold เป็นผลงานที่ยอดเยี่ยมมากสำหรับระบบสมัยใหม่
ช่วงหลังพยายามทำให้การ build โปรเจกต์เร็วขึ้น แล้วพบว่าขั้นตอน link เป็นคอขวดอย่างหนัก แม้จะใช้ 24 คอร์ * 2 เธรด ก็ยังมีสมรรถนะรวมราว 30% ที่ว่างงานเพราะ linker
เคยลอง build ด้วย mold มาก่อนแต่ตอนนั้นไม่ค่อยเวิร์ก คราวนี้ตั้งใจว่าจะลองอีกครั้ง
จำตัวเลขเป๊ะ ๆ ไม่ได้ แต่ต่างกันค่อนข้างมาก ประมาณว่า gold กับ lld ใช้เวลาหลายวินาที แต่ mold ลดลงมาเหลือน้อยกว่า 1 วินาที
เป็นโค้ด C++/Qt ที่ซับซ้อน
mold -run ninjaทำงานได้ดีมากในสภาพแวดล้อมของผมดีใจมากที่เห็นข่าว การเปลี่ยนไลเซนส์ หวังว่าโปรเจกต์จะทำเงินได้ด้วย แต่ถ้าเป็นไลเซนส์ MIT โอกาสที่จะนำไปผสานกับโปรเจกต์งานก็จะสูงขึ้นมาก
ถ้าได้ใช้งานจริง ผมจะลองโน้มน้าวให้บริษัทสนับสนุนโปรเจกต์นี้
AGPL ก็น่าจะจำกัดเฉพาะกรณีที่นำ linker ที่แก้ไขแบบส่วนตัวไปเผยแพร่เป็นบริการบนเครือข่าย ซึ่งไม่ใช่สถานการณ์ที่เป็นจริงสำหรับเครื่องมือพัฒนาพื้นฐาน
สงสัยเรื่องการเปลี่ยนไลเซนส์ อันนี้เป็น executable ไม่ใช่เหรอ? การเรียกเป็นโปรเซสแยกไม่ได้ทำให้ซอฟต์แวร์ที่เรียกต้องกลายเป็น GPL ดังนั้นในกรณีทั่วไป การเปลี่ยนเป็น MIT ไม่น่าจะมีผล
ถ้าผู้เขียนต้องการไลเซนส์ที่ผ่อนปรนกว่าจริง ๆ แทนที่จะ relicense จาก AGPL เป็น MIT ก็ควรเปลี่ยนเป็น AGPL ที่มี linking exception ตัวอย่างโปรเจกต์ GPL ที่มี linking exception คือ libgit2 https://github.com/libgit2/libgit2#license
ไลเซนส์แบบนี้ผ่อนปรนกว่า แต่ยังทำให้ขายไลเซนส์เชิงพาณิชย์ให้ฝ่ายที่สร้างการเปลี่ยนแปลงแบบปิดซอร์สได้
soldซึ่งเป็นเวอร์ชัน macOS ดูเหมือนจะเป็นข้อยกเว้นlinker ตัวนี้ช่วยเพิ่ม ความพึงพอใจในการพัฒนา อย่างเห็นได้ชัดใน repository Rust สำหรับสำรวจของผม ที่กำลังจะกลายเป็นเว็บ monolith ขนาดใหญ่ซึ่งใช้ SeaORM และ axum/tokio
คุณคงไม่อยากรู้ขนาดไดเรกทอรี
targetของผมหรอก แต่ incremental build ลื่นขึ้นมาก15:55 $ du -Hs --si target/11G target/Mold ยอดเยี่ยม และมีกรณีใช้งานที่ผมชอบอยู่หลายอย่าง
[target.x86_64-unknown-linux-gnu]linker = "clang"rustflags = ["-C", "link-arg=-fuse-ld=mold","-C", "target-cpu=native"]"-fuse-ld=mold"ลงใน CFLAGS จะทำให้makepkgเร็วขึ้นด้วยเป็นการตัดสินใจที่ฉลาดมาก บางครั้งในผลิตภัณฑ์หรือโค้ดของผมเองก็มีช่วงเวลายาก ๆ ที่ต้องยอมรับว่าบางอย่างไม่เหมาะกับการทำเงิน
ตลาดเป็นคนบอก และแม้น่าเสียดาย แต่สิ่งสำคัญคือหาสิ่งอื่นที่ตลาดให้รางวัล แทนที่จะไปสู้กับมัน
มีใครรู้ไหมว่าการเปลี่ยนไลเซนส์/กลยุทธ์ธุรกิจนี้จะใช้กับ sold ด้วยหรือไม่? sold คือ mold สำหรับ macOS
https://github.com/bluewhalesystems/sold
https://twitter.com/davidecci/status/1665835119331135488
“repository นี้มี linker mold เวอร์ชันฟรี หากคุณกำลังมองหาเวอร์ชันเชิงพาณิชย์ที่รองรับ macOS ให้ไปที่ repository ของ linker sold”
แค่จ่ายเงินก้อนงามให้กับงานนี้แล้วทำให้โลกดีขึ้นก็ได้แล้ว
สำหรับ Apple น่าจะเป็นเรื่องง่ายมาก
ไลเซนส์เปลี่ยนจาก AGPL เป็น MIT
แต่ช่างฝีมือยอดเยี่ยมแบบนี้ควรได้รับค่าตอบแทนอย่างไร และทำไมถึงยังไม่เป็นแบบนั้น? ผมคิดว่าบริษัทต่าง ๆ ไม่ว่าใหญ่เล็กควรจัดสรรงบประมาณบางส่วนให้ dependency หรือเครื่องมือหลัก และเปิดเผยไว้บนเว็บไซต์ทางการ ดูเหมือนเราต้องการบรรทัดฐานทางวัฒนธรรมแบบหนึ่งมากขึ้น
ลืมไปแล้วว่านี่เคยเป็นลิงเกอร์ที่เร็ว
“Mold 2.0.0 เป็นเมเจอร์รีลีสใหม่ของลิงเกอร์ความเร็วสูงของเรา ในรีลีสนี้ เราเปลี่ยนไลเซนส์จาก AGPL เป็น MIT โดยมีเป้าหมายเพื่อขยายฐานผู้ใช้ คนที่ติดตามความคืบหน้าคงทราบดีว่า นี่ไม่ใช่การตัดสินใจที่ง่าย เพราะเราเคยพยายามสร้างรายได้จากผลิตภัณฑ์ด้วยโมเดลไลเซนส์คู่แบบ AGPL/เชิงพาณิชย์ น่าเสียดายที่แนวทางนี้ไม่เป็นไปตามคาด การเปลี่ยนไลเซนส์เป็นผลจากการยอมรับความจริงข้อนี้ เราไม่อยากดันทุรังใช้กลยุทธ์ที่ไม่ได้ผลต่อไป”
มันแย่มาก และยังเป็นวิธีปฏิบัติต่อนักพัฒนาที่ใช้ซอฟต์แวร์สำหรับ OS ของตัวเองที่ห่วยแตกด้วย
พวกเราคุ้นเคยมานานมากกับการไม่จ่ายเงินให้เครื่องมือพัฒนาระดับต่ำ แต่ไปจ่ายเป็นค่าซัพพอร์ตแทน แค่การที่เคยพยายามทำไลเซนส์แบบนั้นก็น่าประหลาดใจแล้ว
ตลอดเวลาที่ผ่านมาเคยเห็นการถกเถียงเรื่องลิงเกอร์ที่เร็ว และเรื่องที่พอเปลี่ยนลิงเกอร์ตัวหนึ่งให้เป็นตัวที่เร็วกว่าแล้วเวลา compile ลดลงมากอยู่หลายครั้ง แต่โดยทั่วไปก็ยังไม่ค่อยรู้ว่า ทำไมลิงเกอร์ถึงช้า
ถ้ามีใครอธิบายได้ก็คงดี
การเพิ่มประสิทธิภาพส่วนใหญ่ได้มาจากการประมวลผลงานแบบขนาน และบน CPU มัลติคอร์ทรงพลังสมัยใหม่ก็ทำให้ดีขึ้นมาก
ถ้าอยากรู้เพิ่ม Rui มีพรีเซนเทชันดี ๆ เกี่ยวกับ Mold: https://www.youtube.com/watch?v=hAt3kCalE0Y
catเพราะแค่เอาไบนารีมาต่อกันแล้วก็จบ ในยุคที่ยังใช้ดิสก์จานหมุน ปัญหาอยู่ที่ I/O ของดิสก์ แต่ตอนนี้น้อยลงแล้วส่วนที่กินเวลาคืองานเขียนเนื้อหาซ้ำระหว่างทาง การไล่ตาราง relocation แล้วใส่แอดเดรสลงในโค้ดนั้นต้นทุนต่ำ และการทำ dead stripping ระดับ section ก็ค่อนข้างถูก แต่ถ้าจะ dead strip basic block แต่ละก้อนภายในฟังก์ชัน ก็ต้องวิเคราะห์มากกว่ามากเลยใช้เวลา
การกำจัดสตริงคงที่ที่ซ้ำกันเป็นไอเดียที่ดี แต่ต้องไหลทุกอย่างเข้าไปใน hash table รูปแบบใดรูปแบบหนึ่ง ถ้าต้องการให้ใช้ common suffix ร่วมกันได้ด้วย งานก็เพิ่มขึ้นอีก
การกำจัดข้อมูลซ้ำ, dead stripping และการเขียน debug information ใหม่ก็ใช้เวลาเช่นกัน ใน debug build อาจมี DWARF หลาย GB ที่ต้องเขียนใหม่
ที่น่าสนใจคือการที่ลิงเกอร์สามารถสคริปต์ได้และส่งโปรแกรมให้มันตีความได้นั้นดูเหมือนไม่ใช่ต้นทุนใหญ่ อาจเป็นเพราะสคริปต์ดังกล่าวค่อนข้างสั้นและความสามารถก็ถูกจำกัดในระดับหนึ่ง
ในอดีต เหตุผลที่ lld เร็วมากคือมันแทบไม่ประมวลผล debug information หรือทำการกำจัดข้อมูลซ้ำแบบอื่น ๆ lld รันได้เร็ว แต่ไบนารีที่ออกมามีขนาดใหญ่
ผมห่างจากงานด้านประสิทธิภาพการลิงก์มาหลายปีแล้ว เลยไม่ค่อยรู้สถานะปัจจุบัน โดยเฉพาะไม่รู้ว่า mold หรือ lld อยู่ตรงไหนระหว่างคุณภาพของผลลัพธ์กับประสิทธิภาพของตัวเอง
https://www.airs.com/blog/archives/38
“ขอย้ำอีกครั้งว่าเป้าหมายคือความเร็ว ในกรณีนี้คือให้เร็วกว่าลิงเกอร์ตัวที่สองของผม ลิงเกอร์ตัวนั้นช้าลงมากตลอดหลายปีที่ผ่านมา หลังจากมีการเพิ่มการรองรับ ELF และ shared library การรองรับนี้ไม่ได้ถูกออกแบบมาตั้งแต่ต้น แต่ถูกต่อเติมเข้าไป แผนในอนาคตของลิงเกอร์ตัวใหม่นี้ยังรวมถึงการรองรับ incremental linking ด้วย ซึ่งก็เป็นอีกวิธีหนึ่งในการเพิ่มความเร็ว”
ลองนึกถึงแอปในยุค Unix แรก ๆ ดู เป็นแอปเรียบง่ายที่มีวัตถุประสงค์เดียว น่าจะมีไฟล์ซอร์สเดียว อ็อบเจกต์เดียว และลิงก์แค่ libc เท่านั้น ไม่มีอะไรอย่าง shared library
ต่อมาเมื่อมีฟีเจอร์ที่ “จำเป็น” เพิ่มเข้ามา โค้ดของลิงเกอร์ก็โตขึ้นแบบออร์แกนิก โดยเฉพาะในยุคที่ดิสก์จานหมุนเป็นคอขวด ความถูกต้องของฟีเจอร์จึงสำคัญกว่าความเร็ว