Monday, September 22, 2014

জাভা কীভাবে কাজ করে এবং কীভাবে ভাল পারফর্ম করে

জাভা কোড প্রথমে বাইটকোডে কম্পাইলড হয়, তারপর সেটিকে জাভা ভার্চুয়াল মেশিন এক্সিকিউট করে। বাইটকোড হচ্ছে এক ধরনের ইন্টারমিডিয়েড ল্যাংগুয়েজ যা কিনা ঠিক মানুষের পাঠ উপযোগী নয়, আবার মেশিনের জন্য ও নয়। এটি শুধুমাত্র জাভা ভার্চুয়াল মেশিন (JVM)পড়তে পারে। বাইটকোডকে এক্সিকিউট করার জন্য জাভা ভার্চুয়াল মেশিন জাস্ট ইন টাইম (JIT) কম্পাইলার ব্যবহার হরে। JIT বাইটকোড কে সরাসরি ইন্টারপ্রেট করে। এটি রানটাইম-এ বাইটকোড কে ইন্টারপ্রেট করে মেশিন কোড-এ রূপান্তরিত করে যা কিনা সিপিইউ রান করে। এখানে একটি ইন্টারেস্টিং প্রশ্ন হতে পারে, জাভা কি তাহলে ইন্টারেপ্রেটেট ল্যাংগুয়েজ নাকি কম্পাইল্ড ল্যাংগুয়েজ? উত্তর কিন্তু দুটোই । জাভা একি সঙ্গেসঙ্গে কম্পাইলড এবং ইন্টারপ্রেটেড ল্যাংগুয়েজ।


উপরের লাইনগুলো পড়ে আপনি মনে করতেই পারেন যে, JIT আসলে জাভাকে স্লো করে দিচ্ছে, কারণ এটি প্রোগ্রাম যখন চলে তখন ইন্টারপ্রেট করছে। এই উপসংহার হয়তো ইনটিউটিভ, তবে সঠিক নয়। JIT আসলে অনেক ভাল ভাবেই কাজ করে।


C/C++-কে সাধারণভাবে ধরা হয় যে জাভা থেকে বেশি ভাল পারফর্ম করে। জাভা যেহেতু অন-দ্যা-ফ্লায় এক্সিকিউট করে, এজন্য অনেকটা এভাবে চিন্তা করা হয়। কোড-কে মেশিন কোড-এ রূপান্তরিত করার জন্য আসলে খুব বেশি সময় লাগে না, তারপরও যদি কোনো ল্যাংগুয়েজের কোডকে এক্সিকিউট করার আগে তাকে মেশিন কোড এ রূপান্তরিত করতে না হয়, তাহলে ধরা হয়, সেই ল্যাংগুয়েজ অনেকটা ফাস্টার। মজার ব্যপার হচ্ছে কোন কম্পাইলার-ই কিন্তু টপ-নচ এসেম্বলি প্রোগ্রামারদের মতো যারা কিনা কোনো হার্ডওয়্যারকেকে টার্গেট করে মেশিন কোডকে সরাসরি মেনিপুলেট করতে পারে, তাদের মতো মেশিন কোড তৈরি করতে পারে না, যা কিনা অনেক বেশি পার্ফরমেন্ট হবে। C/C++ কিংবা জাভা সবগুলোর-ই কিছু না কিছু সমস্যা আছে। জাভাকে রান করার আগে অন-দ্যা-ফ্লায় মেশিন কোড তৈরি করতে হয়, C/C++ এর কোড ও কিন্তু অনেকটা জেনেরিক ভাবেই কম্পাইলড হয়। C/C++ এ কিন্তু সরাসরি একটি নির্দিষ্ট হার্ডওয়্যারকে টার্গেট করে কোড লেখা হয় না সবসময়।

মজার ব্যপার হচ্ছে, জাভা ভার্চুয়াল মেশিন কিন্তু খুব-ই ইন্টেলিজেন্ট এনভায়রনমেন্ট এবং JIT নিজেও খুব-ই ইন্টেলিজেন্ট কম্পাইলার। উদাহরণস্বরূপ- JVM জানে যেকোনো মেথড কতবার কল করা হচ্ছে, কারণ JVM মেথড কল কাউণ্ট করে । যখন এই কাউন্ট একটি নির্দিষ্ট থ্রেসহোল্ডের বাইরে চলে যায়, তখন সেই মেথড-এর মেশিন কোডJVM রেখে দেয়, পরের বার আবার কল করা হলে, সেটি আর সেই মেথডকে ইন্টারপ্রেট না করে সরসরি সেই রেখে দেওয়া মেশিন কোড-কে দিয়ে দেয় যা কিনা বারবার বাইটকোড থেকে মেশিনকোড-এ ট্রান্সলেশান করার কস্ট কমিয়ে দেয়। আরও মজার ব্যাপার হচ্ছে, JIT কম্পাইলার, যে সব কোড খুব বেশিবার ব্যবহার করা হয়, সেগুলোকে অপটিমাইজ করে। JIT নানা ধররণের স্ট্যাটিসটিক্স কালেক্ট করে থাকে। রিসার্সে দেখা গেছে যে, 80% সময়ে আসলে মোট কোডবেইস এর 20% কোড এক্সিকিউট করা হয়। সুতরাং এই 20% কোড গুলো যদি আলাদা করা যায়, এবং এদেরকে অপটিমাইজ করা যায়, তাহলে কিন্তু হিউজ পারফরমেন্স গেইন করা যাবে। মজার ব্যপার হচ্ছে JIT আসলে তাই করে। এটি (hotcode) এই 20% কোড কে আলাদা করতে পারে এবং এদেরকে অপটিমাইজ করতে পারে। ওরাকলের জাভা ভার্চুয়াল মেশিন হটস্পট (hotspot)-এরf নাম হয়তো অনেকেই জানি, এটির নামকরণ করা হয়েছে এই জন্য যে, এটি এই হট স্পট গুলোকে আলাদা করতে পারে। জাভা যেহেতু JVM এর জন্য লেখা হয়, এবং JIT সেটিকে মেশিন কোড এ রূপান্তরিত করে, এটি কিন্তু রানটাইমে হার্ডওয়্যার এর ইনফরমেশন একসেস করতে পারে এবং তার উপর ভিত্তি করে অপটিমাইজ মেশিন কোড তৈরি করে পারে, যা কিনা C/C++ এর ক্ষেত্রে অনেক সময়ই সম্ভব হয়ে উঠে না।


সুতরাং উপসংখ্যার হচ্ছে, জাভা আসলে অনেক বেশি ভাল পারফর্ম করে, কিন্তু সেটা হয়তো একটি ছোট হ্যালোওয়ার্ল্ড টাইপ অ্যাপ্লিকেশন লিখলে দেখা সম্ভব হবে না, কিন্তু আমরা যদি অনেক বড়ো বড়ো অ্যাপ্লিকেশন রান করি, এটি খুব ভাল ভাবে, অন্যান্য ল্যাংগুয়েজ থেকেও অনেক বেশি ভালভাবে কাজ করবে ।