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

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

โปรแกรมถูกคอมไพล์ใน runtime โดยใช้วิธีที่แตกต่างจาก pre-execution compilation กระบวนการนี้เรียกว่า just-in-time compilation หรือ dynamic translation

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

แต่ก่อน: JIT compilation ทำงานอย่างไร?

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

Just-in-time compilation เป็นวิธีการรันโค้ดคอมพิวเตอร์ที่ต้องการ compilation ขณะรันโปรแกรม

สิ่งนี้อาจหมายถึงการแปล source code แต่บ่อยที่สุดทำโดยการแปลง bytecode เป็น machine code ซึ่งจะถูก run โดยตรง

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

ประโยชน์ของ JIT Compilation สำหรับ Ruby

JIT compilation รวมประโยชน์ (และข้อบกพร่อง) บางส่วนของสองวิธีแบบดั้งเดิมสำหรับแปลงโปรแกรมเป็น machine code: interpretation และ ahead-of-time compilation (AOT)

พูดคร่าวๆ มันรวมความยืดหยุ่นของ interpretation กับความเร็วของ generated code และ overhead เพิ่มเติมของการ compile และ link (ไม่ใช่แค่ interpret)

JIT compilation เป็นประเภทหนึ่งของ dynamic compilation ที่เปิดใช้ adaptive optimization techniques รวมถึง dynamic recompilation และ speed-ups ที่ปรับแต่งสำหรับ microarchitectures เฉพาะ เนื่องจากความสามารถของ runtime system ในการจัดการ late-bound data types และบังคับ security guarantees ภาษา dynamic programming เช่น Ruby เหมาะอย่างยิ่งสำหรับ interpretation และ JIT compilation

Optimizing compiler เช่น GCC สามารถ optimize instructions ได้อย่างมีประสิทธิภาพมากขึ้น — ข้อได้เปรียบสำคัญของการ採用 register-oriented architecture Compilers ทำงานบน intermediate representation ด้วย register-based architecture

เมื่อ instructions ของคุณถึง intermediate representation ระหว่าง compilation GCC จะทำ additional passes เพื่อเร่งการ execute instructions ของ CPU

JIT Compilers สำหรับ Ruby: YJIT, MJIT, และ TenderJIT

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

MJIT (Method-based Just-in-time Compiler) สำหรับ Ruby

Vladimir Makarov implement MJIT และมันคือ compiler methodology แรกที่ implement ใน Ruby based on C language มันทำงานกับ Ruby 2.6 ใช้ YARV instructions และ compile instructions ที่ใช้บ่อยใน binary code

สำหรับโปรแกรมที่ไม่ได้ input/output-bound MJIT เพิ่มประสิทธิภาพ

YJIT ดีกว่าตัว compiler C-based ต้นฉบับนี้ในแง่ของประสิทธิภาพ JIT ของ Ruby 3 เป็น JIT ที่เร็วที่สุดที่ MRI เคยมี ทำได้เพราะงานยอดเยี่ยมของ MJIT

วิธีใช้ MJIT

เพื่อใช้ MJIT คุณสามารถ enable JIT ใน Ruby 2.6 ด้วย option --jit

 

หากคุณข้ามส่วนนี้ MJIT จะแสดง error

 

มีการรวบรวม JIT-specific settings ใน Ruby 2.6 ช่วยให้เราเข้าใจว่ามันทำงานอย่างไร รัน ruby --help เพื่อดู options เหล่านี้

สรุป MJIT execute ใน thread แยกและเป็น asynchronous มันจะเริ่ม just-in-time compilation หลังจากรันการคำนวณ 5 ครั้งแรก

YJIT สำหรับ Ruby on Rails

JIT compiler ใหม่ล่าสุดชื่อ YJIT ถูก release พร้อม Ruby 3.1 มันสัญญาว่าจะมี improvements มากและประสิทธิภาพที่ดีกว่า ยังเป็น work-in-progress project ที่ออกแบบโดย Shopify ด้วย experimental results ต้องใช้ด้วยความระมัดระวัง โดยเฉพาะบนแอปพลิเคชันขนาดใหญ่

ด้วยนั้น YJIT เพิ่มประสิทธิภาพของแอปพลิเคชัน Ruby on Rails ส่วนใหญ่ของ real-world software ได้รับประโยชน์จาก fast warm-up และ performance enhancements ที่ให้โดย YJIT basic block versioning JIT compiler

JIT compiler จะถูก built เข้า CRuby อย่างค่อยเป็นค่อยไปเป็นส่วนหนึ่งของ YJIT project ในที่สุดจะแทนที่ interpreter สำหรับ code execution ส่วนใหญ่

Official benchmarks — ดู 'YJIT: Building a New JIT Compiler for CRuby' — แสดงว่า YJIT ปรับปรุงประสิทธิภาพมากกว่า default CRuby interpreter โดย:

  • 20% บน railsbench
  • 39% บน liquid template rendering
  • 37% บน activerecord

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

เพียงประมาณ 79% ของ instructions ใน railsbench ถูก execute โดย YJIT ส่วนที่เหลือรันใน default interpreter

แหล่งที่มา: YJIT: Building a New JIT Compiler for CRuby

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

即便如此 YJIT ทำงานได้ดีอย่างน้อยเท่า interpreter บนทุก benchmark แม้บนตัวที่ยากที่สุด และถึง near-peak performance หลังเพียงหนึ่ง iteration ของทุก benchmark

วิธีใช้ YJIT

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

YJIT disabled by default หากคุณต้องการ enable ให้ระบุ command-line option --yjit ก่อน

คุณต้องตรวจสอบว่าติดตั้งแล้ว รัน ruby --enable-yjit -v หาก warning: unknown argument for --enable: yjit'` แสดงขึ้น คุณต้องติดตั้งมัน

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

TenderJIT

ด้วย design ที่ based largely off YJIT TenderJIT เป็น experimental JIT compiler สำหรับ Ruby สิ่งที่แตกต่างของ TenderJIT คือมันเขียนใน pure Ruby

นี่คือ demo project และเป้าหมายคือ ship มันเป็น gem ในระหว่างนั้น คุณสามารถทดลองกับมันได้ แต่จำไว้ว่ามันยัง work in progress ต้องการ Ruby 3.0.2 หรือใหม่กว่าสำหรับ TenderJIT

วิธีใช้ TenderJIT

TenderJIT ไม่ได้ทำ method compilation อัตโนมัติในปัจจุบัน เพื่อ compile เมธอด คุณต้อง config TenderJIT ด้วยตนเอง

Clone repository และรันคำสั่งต่อไปนี้:

 

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

 

แต่ละ YARV instruction ใน target method ถูกอ่านโดย TenderJIT ซึ่งจากนั้นแปลงเป็น machine code

สำหรับตัวอย่างเพิ่มเติมกับ TenderJIT ดูวิดีโอหนึ่งในนี้: A JIT compiler for Ruby with Aaron Patterson และ Hacking on TenderJIT!

สรุป

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

อย่างไรก็ตาม YJIT เป็นตัวที่ mature ที่สุดในตอนนี้ และมี potential ใหญ่ที่สุดในการเติบโตและขยายสเกล มันแสดงประสิทธิภาพดีกว่า Ruby JITs อื่นๆ พัฒนากับ Ruby 3.1.0 และเร็วๆ นี้จะกลายเป็นส่วนสำคัญของ CRuby

ดูโพสต์นี้หากคุณต้องการสร้าง compiler ของคุณเองสำหรับ Ruby

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

P.S. หากคุณต้องการอ่านโพสต์ Ruby Magic ทันทีที่เผยแพร่ สมัครรับจดหมายข่าว Ruby Magic และจะไม่พลาดโพสต์ใดๆ!

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

Renata Marques

ผู้เขียน אורח Renata เป็น software engineer และ computer scientist โฟกัสที่ Ruby และ Javascript เธอเพลิดเพลินช่วยชุมชนนักพัฒนาโดย contribute ให้ open source projects ในเวลาว่าง เธอชอบดูและพูดคุยหนังและรายการทีวี อ่านหนังสือ ฟังเพลง ถ่ายรูป และทำวิดีโอ

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