Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> Ruby

JIT Compilers สำหรับ Ruby &Rails:เพิ่มประสิทธิภาพด้วย YJIT, MJIT และ TenderJIT

โปรแกรมถูกคอมไพล์ขณะรันไทม์โดยใช้วิธีการอื่นจากการคอมไพล์ก่อนดำเนินการ กระบวนการนี้เรียกว่าการรวบรวมแบบทันเวลาหรือการแปลแบบไดนามิก

ในโพสต์นี้ เราจะดูว่าเหตุใดการคอมไพล์ JIT จึงเป็นตัวเลือกที่ดีสำหรับแอป Ruby on Rails ของคุณ ก่อนที่จะดูตัวเลือกบางส่วนที่มี (YJIT, MJIT และ TenderJIT) และวิธีการติดตั้ง

แต่ก่อนอื่น:การคอมไพล์ JIT ทำงานอย่างไร

JIT Compiler ทำงานอย่างไร

การคอมไพล์แบบทันเวลาเป็นวิธีการรันโค้ดคอมพิวเตอร์ที่ต้องมีการคอมไพล์ในขณะที่รันโปรแกรม

ซึ่งอาจรวมถึงการแปลซอร์สโค้ด แต่มักทำโดยการแปลงโค้ดไบต์เป็นโค้ดเครื่อง ซึ่งจะรันโดยตรง

รหัสที่กำลังดำเนินการมักจะถูกวิเคราะห์อย่างต่อเนื่องโดยระบบโดยใช้คอมไพเลอร์ JIT ข้อมูลนี้จะระบุส่วนของโค้ดที่ประโยชน์ของการคอมไพล์หรือการคอมไพล์ใหม่ (ในแง่ของความเร็ว) มีมากกว่าต้นทุน

ประโยชน์ของการรวบรวม JIT สำหรับ Ruby

การคอมไพล์ JIT รวมข้อดีบางประการ (และข้อบกพร่อง) ของวิธีการทั่วไปสองวิธีสำหรับการแปลงโปรแกรมเป็นรหัสเครื่อง:การตีความและการคอมไพล์ล่วงหน้า (AOT)

โดยคร่าวๆ จะรวมความยืดหยุ่นในการตีความเข้ากับความเร็วของโค้ดที่สร้างขึ้น และค่าใช้จ่ายเพิ่มเติมในการคอมไพล์และลิงก์ (ไม่ใช่แค่การตีความ)

การคอมไพล์ JIT เป็นการคอมไพล์แบบไดนามิกประเภทหนึ่งที่เปิดใช้งานเทคนิคการปรับให้เหมาะสมแบบปรับเปลี่ยนได้ รวมถึงการคอมไพล์ใหม่แบบไดนามิกและการเร่งความเร็วที่ปรับให้เหมาะกับสถาปัตยกรรมไมโครบางอย่าง เนื่องจากความสามารถของระบบรันไทม์ในการจัดการประเภทข้อมูลที่ถูกผูกไว้ล่าช้าและกำหนดการรับประกันความปลอดภัย ภาษาการเขียนโปรแกรมแบบไดนามิก เช่น Ruby จึงเหมาะอย่างยิ่งสำหรับการตีความและการคอมไพล์ JIT

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

เมื่อคำสั่งของคุณถึงระดับกลางในระหว่างการคอมไพล์ GCC จะส่งผ่านเพิ่มเติมเพื่อเร่งการดำเนินการของ CPU ตามคำสั่งของคุณ

คอมไพเลอร์ JIT สำหรับ Ruby:YJIT, MJIT และ TenderJIT

ตอนนี้ เรามาสำรวจคอมไพเลอร์ JIT ต่างๆ สำหรับ Ruby — YJIT, MJIT และ TenderJIT — และวิธีตั้งค่าคอมไพเลอร์เหล่านี้

MJIT (คอมไพเลอร์ทันเวลาตามวิธีการ) สำหรับ Ruby

Vladimir Makarov ใช้ MJIT และเป็นวิธีคอมไพเลอร์ตัวแรกที่ใช้ใน Ruby โดยใช้ภาษา C โดยใช้ได้กับ Ruby 2.6 ใช้คำสั่ง YARV และคอมไพล์คำสั่งที่มักใช้ในรหัสไบนารี่

สำหรับโปรแกรมที่ไม่ถูกผูกไว้กับอินพุต/เอาท์พุต MJIT จะเพิ่มประสิทธิภาพ

YJIT ดีกว่าคอมไพเลอร์ที่ใช้ C ดั้งเดิมในแง่ของประสิทธิภาพ JIT ของ Ruby 3 เป็น JIT ที่เร็วที่สุดที่ MRI เคยมีมา ซึ่งเกิดขึ้นได้จากผลงานอันยอดเยี่ยมของ MJIT

วิธีใช้ MJIT

หากต้องการใช้ MJIT คุณสามารถเปิดใช้งาน JIT ใน Ruby 2.6 และด้วย --jit ตัวเลือก

 

หากคุณข้ามส่วนนี้ MJIT จะแสดงข้อผิดพลาด

 

ชุดการตั้งค่าเฉพาะของ JIT ที่รวมอยู่ใน Ruby 2.6 ช่วยให้เราเข้าใจว่ามันทำงานอย่างไร เรียกใช้ ruby --help เพื่อดูตัวเลือกเหล่านี้

กล่าวโดยสรุป MJIT ดำเนินการในเธรดอื่นและไม่พร้อมกัน โดยจะเริ่มการรวบรวมแบบทันเวลาหลังจากการคำนวณห้าครั้งแรก

YJIT สำหรับ Ruby on Rails

คอมไพเลอร์ JIT ล่าสุดชื่อ YJIT เปิดตัวพร้อมกับ Ruby 3.1 รับประกันว่าจะมีการปรับปรุงมากมายและประสิทธิภาพที่ดีขึ้น ยังคงเป็นโปรเจ็กต์ที่กำลังดำเนินการซึ่งออกแบบโดย Shopify พร้อมผลการทดลอง ต้องใช้ด้วยความระมัดระวัง โดยเฉพาะในแอปพลิเคชันขนาดใหญ่

ด้วยเหตุนี้ YJIT จึงปรับปรุงประสิทธิภาพของแอปพลิเคชัน Ruby on Rails ประโยชน์ส่วนใหญ่ของซอฟต์แวร์ในโลกแห่งความเป็นจริงจากการอุ่นเครื่องอย่างรวดเร็วและการปรับปรุงประสิทธิภาพที่ได้รับจากคอมไพเลอร์ JIT เวอร์ชันบล็อกพื้นฐานของ YJIT

คอมไพเลอร์ JIT จะค่อยๆ ถูกสร้างไว้ใน CRuby โดยเป็นส่วนหนึ่งของโปรเจ็กต์ YJIT และจะแทนที่ล่ามสำหรับการเรียกใช้โค้ดส่วนใหญ่ในที่สุด

มาตรฐานอย่างเป็นทางการ — ดู 'YJIT:การสร้างคอมไพเลอร์ JIT ใหม่สำหรับ CRuby' - แสดงให้เห็นว่า YJIT ปรับปรุงประสิทธิภาพเหนือล่าม CRuby เริ่มต้นโดย:

  • 20% บน Railsbench
  • 39% สำหรับการเรนเดอร์เทมเพลตของเหลว
  • 37% ในบันทึกที่ใช้งานอยู่

อย่างไรก็ตาม:

คำสั่งใน Railsbench เพียงประมาณ 79% เท่านั้นที่ดำเนินการโดย YJIT และส่วนที่เหลือรันในล่ามเริ่มต้น

ที่มา:YJIT:การสร้างคอมไพเลอร์ JIT ใหม่สำหรับ CRuby

ซึ่งหมายความว่ายังต้องทำอีกมากเพื่อปรับปรุงผลลัพธ์ปัจจุบันของ YJIT

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

วิธีใช้ YJIT

หมายเหตุ :ปัจจุบัน YJIT จำกัดเฉพาะ macOS และ Linux บนแพลตฟอร์ม x86-64 นอกจากนี้ ตามที่กล่าวไว้ YJIT ยังไม่แนะนำสำหรับแอปพลิเคชันขนาดใหญ่ (ยัง)

YJIT ถูกปิดใช้งานตามค่าเริ่มต้น หากคุณต้องการเปิดใช้งาน ให้ระบุ --yjit ก่อน ตัวเลือกบรรทัดคำสั่ง

คุณต้องตรวจสอบว่ามีการติดตั้งหรือไม่ ดังนั้นให้รัน ruby --enable-yjit -v . ถ้า warning: unknown argument for --enable: yjit'' ปรากฏขึ้น คุณต้องติดตั้งมัน

จากนั้นเปิด irb และตั้งค่า RUBY_YJIT_ENABLE=1 . คุณสามารถออกได้ และตอนนี้คุณก็พร้อมที่จะใช้ YJIT แล้ว คำสั่ง ruby --enable-yjit -v ต้องส่งคืนค่าเช่น ruby 3.1.0p0 (2021-12-25 revision fb4df44d16) [arm64-darwin21]

อ่อนโยน JIT

ด้วยการออกแบบที่มีพื้นฐานมาจาก YJIT เป็นส่วนใหญ่ TenderJIT จึงเป็นคอมไพเลอร์ JIT รุ่นทดลองสำหรับ Ruby สิ่งที่แตกต่างเกี่ยวกับ TenderJIT ก็คือมันเขียนด้วย Ruby ล้วนๆ

นี่เป็นโปรเจ็กต์สาธิตและมีจุดมุ่งหมายเพื่อจัดส่งให้เป็นอัญมณี ในระหว่างนี้ คุณสามารถทดลองใช้ได้ แต่โปรดจำไว้ว่ามันยังอยู่ในระหว่างดำเนินการ ต้องใช้ Ruby 3.0.2 หรือใหม่กว่าสำหรับ TenderJIT

วิธีใช้ TenderJIT

TenderJIT ไม่ได้ทำการคอมไพล์เมธอดโดยอัตโนมัติ หากต้องการคอมไพล์วิธีการ คุณต้องกำหนดค่า TenderJIT ด้วยตนเอง

โคลนที่เก็บและรันคำสั่งต่อไปนี้:

 

คุณต้องตั้งค่าด้วยตนเองในโค้ดของคุณ:

 

คำสั่ง YARV แต่ละรายการในวิธีการเป้าหมายจะถูกอ่านโดย TenderJIT ซึ่งจะแปลงเป็นรหัสเครื่อง

หากต้องการตัวอย่างเพิ่มเติมเกี่ยวกับ TenderJIT โปรดดูหนึ่งในวิดีโอเหล่านี้:คอมไพเลอร์ JIT สำหรับ Ruby กับ Aaron Patterson และการแฮ็กบน TenderJIT!

สรุป

ในโพสต์นี้ เราได้ดูคอมไพเลอร์ JIT สามตัวสำหรับ Ruby ได้แก่ MJIT, YJIT และ TenderJIT อย่างรวดเร็ว และวิธีการตั้งค่า แต่ละตัวเลือกเป็นการทดลองและมีข้อจำกัดของตัวเอง

อย่างไรก็ตาม YJIT เป็นผู้ใหญ่มากที่สุดในขณะนี้ และมีศักยภาพสูงสุดในการเติบโตและขยายขนาด มันแสดงให้เห็นถึงประสิทธิภาพที่ดีกว่า Ruby JIT อื่นๆ ซึ่งได้รับการพัฒนาด้วย Ruby 3.1.0 และกำลังกลายเป็นส่วนสำคัญของ CRuby อย่างรวดเร็ว

ลองอ่านโพสต์นี้หากคุณต้องการสร้างคอมไพเลอร์ของคุณเองสำหรับ Ruby

ขอให้สนุกกับการเขียนโค้ด!

ปล. หากคุณต้องการอ่านโพสต์ Ruby Magic ทันทีที่เผยแพร่ สมัครรับจดหมายข่าว Ruby Magic ของเราและไม่พลาดแม้แต่โพสต์เดียว! JIT Compilers สำหรับ Ruby &Rails:เพิ่มประสิทธิภาพด้วย YJIT, MJIT และ TenderJIT

เรนาตา มาร์เกส

Renata ผู้เขียนรับเชิญของเราเป็นวิศวกรซอฟต์แวร์และนักวิทยาศาสตร์คอมพิวเตอร์ที่เน้นเรื่อง Ruby และ Javascript เธอสนุกกับการช่วยเหลือชุมชนนักพัฒนาด้วยการมีส่วนร่วมในโครงการโอเพ่นซอร์ส ในเวลาว่าง เธอชอบดูและพูดคุยเกี่ยวกับภาพยนตร์และรายการทีวี อ่านหนังสือ ฟังเพลง การถ่ายภาพ และการทำวิดีโอ

บทความทั้งหมดโดย Renata Marques