রুবির পারফরম্যান্স ভার্সন বাদে ভার্সন উন্নত হচ্ছে… এবং রুবি ডেভেলপমেন্ট টিম রুবিকে আরও দ্রুত করার জন্য সবচেষ্টা করছে!
এই প্রচেষ্টার একটি হলো ৩x৩ প্রজেক্ট।
লক্ষ্য কী?
রুবি ৩.০, রুবি ২.০ থেকে ৩ গুন দ্রুত হবে।
এই প্রজেক্টের একটি অংশ হলো নতুন MJIT কম্পাইলার, যা এই আর্টিকেলের বিষয়।
MJIT ব্যাখ্যা
MJIT står করে "Method Based Just-in-Time Compiler"।
এটির অর্থ কী?
রুবি আপনার কোডকে YARV ইনস্ট্রাকশন-এ কম্পাইল করে, এই ইনস্ট্রাকশনগুলো রুবি ভার্চুয়াল মেশিন দ্বারা রান করা হয়।
JIT এখানে আরেকটি লেয়ার যোগ করে। এটি ব্যবহৃত হয় এমন ইনস্ট্রাকশনগুলোকে বাইনারি কোডে কম্পাইল করে। ফলাফল হলো একটি অপ্টিমাইজড বাইনারি যা আপনার কোড দ্রুত চালায়।
এটি কীভাবে কাজ করে
আসুন MJIT কীভাবে কাজ করে তা বুঝতে চেষ্টা করি।
আপনি রুবি ২.৬ এবং --jit অপশন দিয়ে JIT সক্ষম করতে পারেন।
এভাবে:
ruby --jit app.rb
রুবি ২.৬-এ JIT-স্পেসিফিক অপশনগুলো রয়েছে যা আমাদের কীভাবে কাজ করে সেটা বুঝতে সাহায্য করবে। আপনি ruby --help চালিয়ে এই অপশনগুলো দেখতে পারেন।
অপশনগুলো:
- --jit-wait
- --jit-verbose
- --jit-save-temps
- --jit-max-cache
- --jit-min-calls
এই verbose অপশনটি একটি ভালো স্টার্টিং পয়েন্ট मालूम হচ্ছে! আমরা --jit-wait ও ব্যবহার করব, যা রুবিকে জিট কোড কম্পাইলেশন শেষ হওয়া পর্যন্ত অপেক্ষা করবেছে রান করার আগে।
সামান্য অপারেশনে JIT একটি ওয়ার্কার থ্রেডে কোড কম্পাইল করে এবং সেটা ফিনিশ হওয়ার জন্য অপেক্ষা করে না।
এখানে একটি কমান্ড যা আপনি টেস্ট করতে পারেন:
ruby --disable-gems --jit --jit-verbose=1 --jit-wait -e "4.times { 123 }"
এটি প্রিন্ট করে:
Successful MJIT finish
খুব ইন্টারেস্টিং নয়, ঠিক? JIT কিছু করছে না। কেন? কারণ ডিফল্টভাবে, JIT তभी একশনে আসে যখন একটি মেথড ৫ বার কল করা হয় (jit-min-calls) বা তার বেশি।
আমরা যদি এটি চালাই:
ruby --disable-gems --jit --jit-verbose=1 --jit-wait -e "5.times { 123 }"
এখন কিছু ইন্টারেস্টিং পাই:
JIT success (32.1ms): block in <main>@-e:1 -> /tmp/_ruby_mjit_p13921u0.c
এটি কী বলে? JIT একটি ব্লক কম্পাইল করেছে কারণ আমরা এটি ৫ বার কল করলাম, এটি আপনাকে বলে:
- কতক্ষণ লেগেছে কম্পাইল করতে (
32.1ms), - স্পষ্টভাবে কী কম্পাইল হয়েছে (
block in <main>) - যে ফাইল জেনারেট হয়েছে (
/tmp/_ruby_mjit_p13921u0.c) কম্পাইলেশনের সোর্স হিসেবে
এই ফাইলটি C সোর্স কোড যা একটি অবজেক্ট ফাইলে (.o) কম্পাইল হয় এবং তারপর একটি শেয়ার্ড লাইব্রেরি ফাইলে (.so)। আপনি --jit-save-temps অপশন যোগ করে এই ফাইলগুলো অ্যাক্সেস করতে পারেন।
এখানে একটি উদাহরণ:

এটি আমার বর্তমান বোঝাপড়া JIT কীভাবে কাজ করে:
- মেথড কল কাউন্ট করা
- যখন একটি মেথড ৫ বার কল হয় (ডিফল্ট
jit-min-calls) JIT ট্রিগার করা - এই মেথডের ইনস্ট্রাকশন ধারণকারী একটি C ফাইল তৈরি করা (এগুলো YARV ইনস্ট্রাকশন, কিন্তু ইনলাইনড)
- ব্যাকগ্রাউন্ডে কম্পাইলেশন হওয়া (মাদ্রাসা
--jit-wait) একটি রেগুলার C কম্পাইলার যেমন GCC দিয়ে - কম্পাইলেশন শেষ হলে ফলাফল শেয়ার্ড লাইব্রেরি ফাইলটি ব্যবহার করা হয় যখন এই মেথড কল করা হয়
আসুন দেখি এটি কত কার্যকর।
MJIT টেস্ট করা: কি এটি সত্যিই দ্রুত?
MJIT-এর লক্ষ্য হলো রুবিকে দ্রুত করা। এখন এটি কত ভালো করছে?
আসুন জানি! প্রথমে, মাইক্রোবেঞ্চমার্ক:
| বেঞ্চমার্ক | ফলাফল (রুবি ২.৬ বিনা JIT-এর সাথে তুলনায়) |
|---|---|
| while | ৮ গুন দ্রুত |
| while with string append | ১০% দ্রুত |
| while with multiplication (Integer) | ৪ গুন দ্রুত |
| while with multiplication (Bignum) | ২০% স্লো |
| string upcase | ১০% দ্রুত |
| string match | ২% স্লো |
| string match? | ১০% দ্রুত |
| array with 10k random numbers | ২০% দ্রুত |
পারফরম্যান্স সব জায়গায় ছড়িয়ে পড়েছে লাগছে, কিন্তু এখান থেকে কিছু ডিডাক্ট করা যায়… MJIT খুব পছন্দ করে লুপ! কিন্তু একটি জটিল অ্যাপ্লিকেশনের সাথে কী অবস্থা?
আসুন একটি সিম্পল সিনাট্রা অ্যাপ দিয়ে ট্রাই করি:
require 'sinatra' get '/' do "apples, oranges & bananas" end
এটি দেখতে অনেক বয় না, কিন্তু এই ছোট কোডটি ৫০০টিরও বেশি মেথড কল করে। JIT-এর কাজ করার জন্য যথেষ্ট!
স্পেসিফিক করতে হলে, এটি সিনাট্রা ২.০.৪ উইথ থিন ১.৭.২।
আপনি বেঞ্চমার্ক এই কমান্ড দিয়ে চালাতে পারেন (apache bench):
ab -c 20 -t 10 https://localhost:4567/
ফলাফলগুলো:

এই ফলাফল থেকে বোঝা যায় রুবি ২.৬, ২.৫-র চেয়ে দ্রুত, কিন্তু JIT সক্ষম করলে সিনাট্রা ১১% স্লো হয়ে যায়!
কেন? আমি জানি না, হয়তো JIT-র ওভারহেডের কারণে, অথবা কোডটি ভালোভাবে অপ্টিমাইজড নয়। C প্রোফাইলার (callgrind) দিয়ে আমার টেস্টিং দেখায় JIT অপ্টিমাইজড কোডের ব্যবহার (যে কম্পাইলড C ফাইলগুলো আমরা আগে খুঁজে পেয়েছিলাম) সিনাট্রার জন্য খুব কম (২% এর নিচে), কিন্তু while স্টেটমেন্টের জন্য যা ৮ গুন স্পিড বুক দিয়েছে, সেটার জন্য খুব বেশি (২৪.২২%)।
JIT সহ while বেঞ্চমার্কের ফলাফল:

JIT সহ সিনাট্রা বেঞ্চমার্কের ফলাফল:

এই হতে পারে পার্শিয়াল রিজন, আমি কম্পাইলার এক্সপার্ট নয় তাই কোনো নিষ্কর্ষ টানে না।
সারসংক্ষেপ
MJIT হলো একটি "Just-in-Time Compiler" যা রুবি ২.৬-এ উপলব্ধ, --jit ফ্ল্যাগ দিয়ে সক্ষম করা যায়। MJIT перспек্টিভ এবং ছোট প্রোগ্রামগুলো স্পিড আপ করতে পারে, কিন্তু এখনও অনেক কাজ বাকি!
আপনি যদি এই আর্টিকেলটি পছন্দ করেন তবে আপনার রুবি বন্ধুদের সাথে শেয়ার करना ভুলবেন না 🙂
পড়ার জন্য ধন্যবাদ।