আপনি যখন কোড রান করেন, মেমরি ব্যবহার করেন। রুবি যেন ভাষায় লিখলে মনে হয় আপনার উপলব্ধ মেমরি অনন্ত। আপনি সিস্টেমের ফিক্সড মেমরি বাবদ চিন্তা না করে চলতে থাকতে পারেন। এই রুবি ম্যাজিক পর্বে আমরা ব্যাখ্যা করব এটি কীভাবে কাজ করে!
কয়েকটি ইতিহাস
পুরোনো দিনে, রুবি যেন স্ক্রিপ্টিং ভাষা অস্তিত্বে নেই। লোকেরা শুধু C যেন লো-লেভেল প্রোগ্রামিং ভাষায় কোড লিখত। এই ভাষাগুলোকে লো-লেভেল 만드는 কারণগুলোতে একটা হলো: আপনাকে নিজে ক্লিন-আপ করতে হতো। উদাহরণস্বরূপ, যখনই আপনি একটি String সংরক্ষণের জন্য মেমরি অ্যালোকেট করেন, আপনাকে সেটি কখন ক্লিন-আপ করবেন সেটিও দরকার হতো।
ম্যানুয়াল ক্লিন-আপ
এটি মੋਕ রুবি কোডে কিছুটা এইরকম দেখাবে। এখানে একটি ভেরিয়েবল ডিক্লেয়ার করা হয়েছে এবং free মেথড (এটি রুবিতে আসলে নেই) ব্যবহার করে আমরা যে মেমরি ব্যবহার করেছি সেটি কাজ শেষে ক্লিন-আপ করা হয়েছে।
1_000_000.times do |i| variable = "Variable #{i}" puts variable free(variable) endএকটি ক্লান্তিকর প্রোগ্রামিং পদ্ধতি
আপনি ইতিমধ্যে বুঝতে পারছেন এখানে রিস্ক রয়েছে: আপনি যদি ভুলে free করতে থাকেন? সেক্ষেত্রে সেই ভেরিয়েবলের কন্টেন্ট মেমরিতে প্রক্রিয়া শেষ না হওয়া পর্যন্ত পড়ে থাকবে। যদি আপনি এটা বারবার করেন, মেমরি শেষ হয়ে যাবে এবং আপনার প্রক্রিয়া ক্র্যাশ করবে।
পরবর্তী উদাহরণে আরেকটি সাধারণ সমস্যা দেখানো হয়েছে:
1_000_000.times do |i| variable = "Variable #{i}" free(variable) puts variable endআমরা ভেরিয়েবল ডিক্লেয়ার করি এবং free করি। কিন্তু তারপর আবার সেটি ব্যবহার করার চেষ্টা করি, যা অসম্ভব কারণ সেটি আর নেই। যদি এটি C হত, আপনার প্রোগ্রাম এখন segfault দিয়ে ক্র্যাশ করত। ওহ!
মানুষ ভুল করার মেশিন
মানুষ এই ধরণের ভুল বারবার না করার বিষয়ে খুব খারাপ। তাই মেমরি স্বয়ংক্রিয়ভাবে ক্লিন-আপ করার একটি পদ্ধতির প্রয়োজন হয়। এর সবচেয়ে জনপ্রিয় পদ্ধতি — যা রুবিও ব্যবহার করে — হলো গার্বেজ কালেকশন (GC)।
গার্বেজ কালেকশন (GC) কীভাবে কাজ করে
GC ব্যবহারকারী ভাষায়, আপনি অবজেক্ট তৈরি করতে পারেন ম্যানুয়ালি সেগুলো ক্লিন-আপ না করেই। আপনি যখন একটি অবজেক্ট তৈরি করেন, সেটি গার্বেজ কালেক্টরের সাথে নিবন্ধিত হয়। GC আপনার এই অবজেক্টের সকল রেফারেন্স ট্র্যাক করার চেষ্টা করে। যখন এটি নির্ধারণ করে আপনি আর অবজেক্টটি ব্যবহার করছেন না, তবে সেটিকে ক্লিন-আপের জন্য মার্ক করা হয়। সময়ে সময়ে গার্বেজ কালেক্টর আপনার প্রোগ্রাম একটু পজ করে এবং সব মার্ক করা অবজেক্ট ক্লিন-আপ করে দেয়।
কয়েকটি উদাহরণ দেখা যাক
আমরা যা সহজ লুপ ব্যবহার করেছিলাম, সেটিতে GC-র কাজ অনেক সহজ। লুপের প্রতিটি ইটারেশনে ভেরিয়েবল আর কোথাও ব্যবহার করা হয় না। তাই ভেরিয়েবলটি তাত্ক্ষণিক ক্লিন-আপের জন্য মার্ক করা যায়।
1_000_000.times do |i| variable = "Variable #{i}" puts variable endপরবর্তী উদাহরণে আমরা ভেরিয়েবলটিকে puts_later মেথডে পাস করি যা ৩০ সেকেন্ড ওপেক্ষা করে তারপর ভেরিয়েবলটি puts করে।
def puts_later(variable) Thread.new do sleep 30 puts variable end end 1_000_000.times do |i| variable = "Variable #{i}" puts_later variable endএই আপেক্ষিক সহজ উদাহরণেও গার্বেজ কালেক্টর-র কাজ ইতিমধ্যে বেশ জটিল। এটিকে বুঝতে হয় আমরা puts_later মেথডে ভেরিয়েবলটি রেফারেন্স করেছি। কারণ মেথডটি একটি থ্রেড শুরু করে, গার্বেজ কালেক্টরকে থ্রেডটিও ট্র্যাক করতে হয় এবং তার শেষ হওয়া অপেক্ষা করতে হয়। শুধু তখন ভেরিয়েবলটি ক্লিন-আপের জন্য মার্ক করা যায়।
যখন এটি জটিল হয়
জটিল উদাহরণে না যেতে হয়, আমার কথা মেনে নিন, গার্বেজ কালেক্টর-র কাজ খুব কঠিন। এটিই ব্যাখ্যা করে কেন GC আপনার প্রোডাকশন এনভায়রনমেন্টে ওভারহেড এবং সমস্যা সৃষ্টি করতে পারে। আপনার প্রোগ্রামে কী হচ্ছে সেটি বুঝতে এটিকে খুব বিস্তারিত বোঝার প্রয়োজন, যা সঠিকভাবে মেমরি ক্লিয়ার করার জন্য বেশ কিছু CPU সাইকেল নেয়। কিন্তু হে, এটি নিজে নিজে ক্লিন-আপ করার চেয়ে ভালো!
গার্বেজ কালেকশন সম্পর্কে আরও কিছু আছে
এটি শুধু আমাদের গার্বেজ কালেকশনের পরিচিতি। ভবিষ্যতে আমরা দেখব রুবিতে এটি সঠিকভাবে কীভাবে কাজ করে, এবং আপনি কীভাবে GC পরিমাপ ও টিউন করে আপনার অ্যাপ্লিকেশনের পারফরম্যান্স উন্নত করতে পারেন।
আপডেট: পরের পর্ব এখানে উপলব্ধ।