তিন বছরেরও বেশি সময় ধরে এলিক্সির সাথে কাজ করার পর, আমি চাই এলিক্সির কিছু অসাধারণ দিক নিয়ে কথা বলতে। এই লেখাটি একটি ধারাবাহিকের প্রথম, যেখানে আমি প্রতি মাসে অন্তত দুটি করে নিবন্ধ লিখব, যা এলিক্সির বিভিন্ন সমস্যার সমাধান নিয়ে আলোচনা করবে। যারা নতুন শিখছেন এবং যারা পেশাদার, দু’জনেরই জন্য এই নিবন্ধগুলো তথ্যপূর্ণ হবে। আমি চাই এটি বাংলায় ও ইংরেজিতে লিখতে, যাতে সবাই উপকৃত হতে পারেন।
আমার সম্পর্কে
আমি মাসুদ রানা, এবং আমি বিভিন্ন প্রোগ্রামিং ভাষায় আট বছরের বেশি অভিজ্ঞতা নিয়ে কাজ করছি—এর মধ্যে রয়েছে এলিক্সির পাশাপাশি C#, Go, Python, Java ইত্যাদি। যদিও আমার ব্যাকগ্রাউন্ড কম্পিউটার সায়েন্স নয়, আমি ২০১৪ সালে মেকানিক্যাল ইঞ্জিনিয়ারিংয়ে স্নাতক ডিগ্রি সম্পন্ন করি। পরবর্তীতে সফটওয়্যার ডেভেলপমেন্টের প্রতি আগ্রহের কারণে, নিজে থেকেই C++, C# শিখে বিভিন্ন প্রজেক্টে কাজ শুরু করি। ২০২০ সালে আমি টার্টু বিশ্ববিদ্যালয়ে মাস্টার্স করার সময় এলিক্সির সাথে পরিচিত হই এবং ২০২১ সালে এটি নিয়ে পেশাদার ভাবে কাজ শুরু করি।
…
কেন এলিক্সির?
যখন আমাদের চারপাশে Java, C#, Python এর মতো ভাষা রয়েছে, তখন নতুন একটি ভাষা এলিক্সির কেন দরকার? আসলে, প্রতিটি প্রোগ্রামিং ভাষা কোন না কোন বিশেষ সমস্যার সমাধানের জন্য তৈরি হয়েছে। যেমন Java তৈরি করা হয়েছিল বিভিন্ন ডিভাইস ও প্ল্যাটফর্মে একই সফটওয়্যার চালানোর জন্য, আর Python এমনভাবে তৈরি হয়েছিল যাতে প্রোগ্রামিং আরও সহজ ও প্রোডাক্টিভ করা যায়।
তাহলে এলিক্সির কেন তৈরি হয়েছে? ২০১১ সালে জোসে ভ্যালিম এই ভাষা তৈরি করেন এমন একটি সিস্টেমের জন্য, যেটি একই সাথে অনেক কাজ করতে পারে, ত্রুটি-সহনশীল এবং স্কেলেবল হবে। অন্য ভাষাগুলির তুলনায় এলিক্সির এমন সব সুবিধা দেয় যা আজকের সময়ে প্রচুর ব্যবহারকারীর চাপ সামলাতে পারে।
আধুনিক সফটওয়্যারে সমান্তরালতা
আজকাল আমাদের অনেকগুলো কাজ একসাথে করার প্রয়োজন পড়ে—একই সাথে হাজার হাজার ব্যবহারকারী যখন একটি ওয়েবসাইট ব্যবহার করে। ধরুন আপনি একটি ই-কমার্স ওয়েবসাইট চালাচ্ছেন, সেখানে একসাথে অনেকেই অর্ডার দিচ্ছে, পণ্য দেখছে। এক্ষেত্রে, কীভাবে এত কাজ একসাথে সামলাবেন?
এখানে এলিক্সির বড় সুবিধা হলো তার প্রসেস মডেল। এলিক্সির প্রতিটি কাজ আলাদা প্রসেসের মাধ্যমে চালায় যা খুবই হালকা এবং নিজেদের মধ্যে কোন মেমোরি শেয়ার করে না। একটি প্রসেস মাত্র ৪ কেবি মেমরি নিয়ে কাজ শুরু করতে পারে। এতে অনেকগুলো কাজ একসাথে করতে কোন সমস্যা হয় না।
অন্যান্য ভাষায়ও এ ধরনের সুবিধা থাকতে পারে, যেমন Java তে আছে গ্রীন থ্রেডস। তবে, এলিক্সির প্রসেস মডেল আরও সহজ এবং কার্যকর, বিশেষ করে বড় স্কেলের সিস্টেমে। এর ত্রুটি-সহনশীলতা এবং প্রসেস আলাদাভাবে চলতে পারার ক্ষমতা এটি আরও নির্ভরযোগ্য করে তোলে।
এখানে মূল পার্থক্যগুলো সহজ ভাষায় ব্যাখ্যা করা হলো:
১. মেমোরি শেয়ারিং:
এলিক্সির প্রসেসগুলো মেমোরি শেয়ার করে না, তাই রেস কন্ডিশন এড়ানো যায়। অন্যদিকে, গ্রীন থ্রেডসগুলো সাধারণত মেমোরি শেয়ার করে এবং যদি সঠিকভাবে রিসোর্স লকিং না করা হয়, তাহলে রেস কন্ডিশন হতে পারে।
২. শিডিউলিং:
এলিক্সির প্রসেসগুলো BEAM ভার্চুয়াল মেশিন দ্বারা নিয়ন্ত্রিত হয়, যেখানে গ্রীন থ্রেডসগুলো রন্টাইম এনভায়রনমেন্ট দ্বারা পরিচালিত হয়।
৩. ফল্ট টলারেন্স:
এলিক্সির প্রসেসগুলো অ্যাক্টর মডেল এ কাজ করে, যা ফল্ট টলারেন্স নিশ্চিত করে। কোন প্রসেস ব্যর্থ হলে, এটি সুপারভাইজার দ্বারা পুনরায় শুরু করা যায়। এলিক্সির ইকোসিস্টেমে এর জন্য প্রয়োজনীয় টুলগুলো সহজলভ্য, যা Erlang OTP নামে পরিচিত।
BEAM মিলিয়নগুলো প্রসেস একসাথে পরিচালনা করতে পারে সামান্যই ওভারহেড নিয়ে। এর বিপরীতে, গ্রীন থ্রেডসের কার্যকারিতা তার ইমপ্লিমেন্টেশনের উপর নির্ভর করে, যা প্রায়ই এলিক্সির প্রসেসের পারফরমেন্সের সাথে মেলে না। গ্রীন থ্রেডে রেস কন্ডিশন এড়ানোর দায়িত্বও ডেভেলপারদের নিতে হয়।
কেন Java তে এলিক্সির মতো কনকারেন্সি মডেল পাওয়া যায় না?
উচ্চ পর্যায়ে, এলিক্সির কনকারেন্সি মডেল সফল কারণ এর প্রসেস আইসোলেশন, ইম্যুটেবিলিটি, এবং মেসেজ পাসিং। এর বিপরীতে, Java ভিত্তিক শেয়ারড মেমোরি, মিউটেবল স্টেট, এবং অবজেক্ট-ওরিয়েন্টেড ডিজাইন। এই পার্থক্যের কারণেই Java এলিক্সির মতো কনকারেন্সি মডেল পেতে ব্যর্থ হয়।
১. অবজেক্ট-ওরিয়েন্টেড ডিজাইন ও শেয়ারড মেমোরি:
Java মূলত ক্লাস এবং অবজেক্ট এর ভিত্তিতে তৈরি। এক ক্লাস অন্য ক্লাসের রেফারেন্স ধরে রাখতে পারে, যা মেমোরি শেয়ার করার সুযোগ দেয়। অন্যদিকে, এলিক্সির প্রতিটি প্রসেসের নিজস্ব আলাদা মেমোরি থাকে এবং তারা অন্য প্রসেসের মেমোরি সরাসরি এক্সেস করতে পারে না।
উদাহরণ: Java-তে দুইটি ক্লাসের মধ্যে মেমোরি শেয়ারিং দেখা যায়, যেমন Car ও Driver ক্লাস। Driver ক্লাস Car ক্লাসের মডেল পরিবর্তন করতে পারে। একাধিক থ্রেড যদি একসাথে একই অবজেক্ট মডিফাই করে, তখন রেস কন্ডিশন ঘটতে পারে। এর সমাধান হিসেবে ডেভেলপারদের থ্রেড সিঙ্ক্রোনাইজেশন ব্যবহার করতে হয়, যা কোড জটিল করে তোলে।
২. মিউটেবিলিটি ও রেস কন্ডিশন:
Java-তে মিউটেবিলিটি অর্থাৎ অবজেক্টের স্টেট পরিবর্তন করা যায়, যা অনেক সময় সুবিধাজনক হলেও রেস কন্ডিশন তৈরি করতে পারে। একাধিক থ্রেড একসাথে একই ডেটা পরিবর্তন করতে গেলে সমস্যা হতে পারে।
৩. অ্যাক্টর মডেল বনাম থ্রেডস:
এলিক্সির কনকারেন্সি মডেল অ্যাক্টর মডেল ভিত্তিক, যেখানে প্রতিটি প্রসেস আলাদা এবং মেসেজ পাসিং এর মাধ্যমে যোগাযোগ করে। এতে রেস কন্ডিশনের ঝুঁকি থাকে না, কারণ এক প্রসেস আরেকটির স্টেট সরাসরি মডিফাই করতে পারে না। Java-তে থ্রেড ব্যবহারের ক্ষেত্রে এই ধরনের স্বাচ্ছন্দ্য পাওয়া যায় না।
৪. এফিশিয়েন্ট শিডিউলিং (BEAM VM বনাম JVM):
BEAM VM এলিক্সির প্রসেসগুলোকে দক্ষতার সাথে পরিচালনা করে, প্রতিটি প্রসেস মাত্র ৪ কেবি মেমোরি ব্যবহার করে। Java তে থ্রেডগুলো অনেক বেশি মেমোরি ব্যবহার করে এবং এদের মধ্যে সমন্বয় করতে বেশি সময় লাগে, যা এলিক্সির তুলনায় কম কার্যকর।
৫. সুপারভিশন ও ফল্ট টলারেন্স:
এলিক্সির কনকারেন্সি মডেল নিজেই ফল্ট টলারেন্ট। প্রসেস ব্যর্থ হলে অন্য প্রসেসগুলো প্রভাবিত হয় না, এবং সুপারভিশন ট্রি এর মাধ্যমে প্রসেস পুনরায় চালু করা যায়। Java-তে এই সুবিধা নেই, ফলে ম্যানুয়ালভাবে ত্রুটি নিরসন ও পুনরুদ্ধার করতে হয়।
…
ভবিষ্যতের নিবন্ধগুলোতে আমি এলিক্সির ইকোসিস্টেমের অন্যান্য দিক যেমন Erlang OTP, Phoenix framework, Ecto নিয়ে আলোচনা করব।
English version with expanded context available at: Exploring Elixir: A Series on Its Unique Aspects