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

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

depjs/canary নামক একটি প্রজেক্ট এই সমস্যাটিকে কন্টেন্ট ক্যালেন্ডার সংক্রান্ত কাজ হিসেবে না দেখে একটি মেশিনের দায়িত্ব হিসেবে বিবেচনা করে। এটি একটি জীবন্ত বেঞ্চমার্ক যা npm, pnpm, Yarn, এবং dep-এর ওপর নজর রাখে এবং তাদের মধ্যে যেকোনো একটি নতুন ভার্সন প্রকাশ করার সাথে সাথে তার পুরো স্যুট পুনরায় চালায়। এর ফলাফলগুলো প্রকাশ্য, নিরবচ্ছিন্ন এবং এড়ানো অসম্ভব। যখন কিছু ভেঙে পড়ে, রিপোজিটরিটি লাল (error state) থাকে যতক্ষণ না এটি ঠিক হয়। এখানে কোনো চেরি-পিকিং নেই, কোনো পুরনো ব্লগ পোস্টের আড়ালে লুকিয়ে থাকা নেই, এবং গত মাসের বিজয়ী এখনও শীর্ষে থাকবে—এমন কোনো ধারণা নেই।

কেন গতির দাবিগুলোর একটি মেয়াদ থাকা প্রয়োজন

JavaScript প্যাকেজ ম্যানেজারগুলো স্থির থাকে না। মাইনর ভার্সনগুলোর মধ্যকার ব্যবধানের মধ্যে নতুনভাবে লেখা রেজোলিউশন অ্যালগরিদম, পরিবর্তিত হোইস্টিং স্ট্র্যাটেজি বা গ্লোবাল ক্যাশ কীভাবে কি (key) করা হবে তার পরিবর্তন থাকতে পারে। একটি বেঞ্চমার্ক যা npm 10.2.1 এবং pnpm 8.11.0-কে ক্যাপচার করে, তা আপনাকে প্রায় কিছুই বলতে পারে না যে দুটি রিলিজ পরে সেই একই টুলগুলো কেমন আচরণ করবে। তবুও, ওয়েব এমন অনেক নিশ্চিত বক্তব্যের জন্য পূর্ণ যা ঠিক এই ধরনের স্থির স্ন্যাপশটের ওপর ভিত্তি করে তৈরি, যেমন— "টুল X তিনগুণ দ্রুততর"।

আরও খারাপ বিষয় হলো, অনেক টেস্ট সেই পরিস্থিতিগুলোকে উপেক্ষা করে যা একজন ডেভেলপারের প্রকৃত সমস্যা বা কষ্ট নির্ধারণ করে। একটি প্যাকেজ ম্যানেজার একটি উষ্ণ (warm) এবং সুসজ্জিত পরিবেশে দ্রুত ইন্সটল সম্পন্ন করতে পারে, কিন্তু একটি CI রানারে যেখানে খালি ডিস্ক দিয়ে শুরু হয়, সেখানে সেটি ধীরগতিতে চলতে পারে। উভয় চরম পরিস্থিতি পরীক্ষা না করলে, বেঞ্চমার্কটি ব্যবহারযোগ্য ইঞ্জিনিয়ারিং ডেটার পরিবর্তে কেবল একটি প্রেস রিলিজ হয়ে দাঁড়ায়।

কীভাবে Canary তুলনা প্রক্রিয়াটি স্বয়ংক্রিয় করে

প্রতি দুই ঘণ্টা অন্তর একটি জব npm রেজিস্ট্রি পোল (check) করে। যদি npm, pnpm, Yarn, বা dep-এর নতুন কোনো ভার্সন দেখা দেয়, তবে canary জেগে ওঠে। এটি কোনো মানুষের চ্যানজলগ দেখার জন্য অপেক্ষা করে না। এটি অবিলম্বে একটি পূর্ণাঙ্গ টেস্ট ম্যাট্রিক্স কার্যকর করে যা চারটি ম্যানেজারকে পাঁচটি জনপ্রিয়, বাস্তবধর্মী প্যাকেজের বিপরীতে পরীক্ষা করে। এই নির্বাচনের মধ্যে React, Next.js, এবং Vite-এর মতো বড় বা প্রভাবশালী প্যাকেজগুলো অন্তর্ভুক্ত থাকে, যে কোডবেসগুলো প্রকৃত ডেভেলপাররা প্রতিদিন ইন্সটল করেন। এগুলো কোনো একটি নির্দিষ্ট টুলকে খুশি করার জন্য তৈরি করা কৃত্রিম মাইক্রো-প্রজেক্ট নয়।

এই রিলিজ-ট্রিগার্ড পদ্ধতিটি গুরুত্বপূর্ণ কারণ এটি পরিমাপকে সরাসরি পরিবর্তনের সাথে যুক্ত করে। যদি বেঞ্চমার্কটি কেবল একটি নৈশকালীন শিডিউলে চলত, তবে এটি হয়তো দিনের মাঝামাঝি কোনো হটফিক্স মিস করতে পারত বা ঘণ্টার পর ঘণ্টা একটি রিগ্রেশন (পিছিয়ে পড়া) এড়িয়ে যেত। নতুন ভার্সনগুলোর ওপর বিশেষভাবে চলার মাধ্যমে, canary প্রতিবার একটি সরাসরি প্রশ্ন করে: এই রিলিজটি কি পরিস্থিতি আরও উন্নত করেছে নাকি আরও খারাপ করেছে?

চারটি পরিস্থিতি যা ভিন্ন ভিন্ন দিক পরীক্ষা করে

টেস্ট ম্যাট্রিক্সটি চারটি স্বতন্ত্র সেটআপের ওপর ভিত্তি করে তৈরি করা হয়েছে যা আপনার পরিচিত কাজের পদ্ধতির (workflows) সাথে সরাসরি মিলে যায়।

  • Cold cache, no lockfile: এটি একটি নতুন ল্যাপটপে একটি ফ্রেশ ক্লোন, অথবা node_modules মুছে ফেলার পর প্রথম ইন্সটলেশন। এখানে কিছুই ক্যাশ করা নেই। কিছুই পিন করা নেই। প্যাকেজ ম্যানেজারকে সবকিছু একদম শুরু থেকে রেজলভ, ফেচ এবং রাইট করতে হয়।
  • Warm cache, with lockfile: এটি কন্টিনিউয়াস ইন্টিগ্রেশনের জন্য একটি আদর্শ পথ যখন সবকিছু ঠিকঠাক চলে। লোকালি লকফাইলটি বিদ্যমান থাকে এবং ক্যাশে আগের রান থেকে প্রাপ্ত টারবল (tarballs) সংরক্ষিত থাকে। টুলটির দ্রুত কাজ করা উচিত কারণ বেশিরভাগ সিদ্ধান্ত ইতিমধ্যেই নেওয়া হয়ে গেছে।
  • Cold cache, with lockfile: এখানে লকফাইলটি উপস্থিত আছে, কিন্তু ক্যাশ মুছে ফেলা হয়েছে। ম্যানেজার ডিপেন্ডেন্সি রেজোলিউশন এড়িয়ে যেতে পারে, তবুও তাকে নেটওয়ার্কের মাধ্যমে প্রতিটি বাইট ডাউনলোড করতে হয়। এটি নেটওয়ার্ক স্পিডকে রেজোলিউশন স্পিড থেকে আলাদা করে পরীক্ষা করে।
  • Warm cache, no lockfile: ক্যাশটি উষ্ণ (hot), কিন্তু লকফাইলটি নেই। ফাইলগুলো এক্সট্র্যাক্ট করা শুরু করার আগে প্যাকেজ ম্যানেজারকে ডিপেন্ডেন্সি ট্রি পুনরায় রেজলভ করতে হয়। এটি আদর্শ নেটওয়ার্ক পরিস্থিতিতে সলভার এবং মেটাডেটা পার্সারের দক্ষতা পরীক্ষা করে।

প্রতিটি পরিস্থিতি পাঁচবার চালানো হয় এবং canary তার মিডিয়ান (median) ফলাফলটি সংরক্ষণ করে। এই একটি সিদ্ধান্ত অনেক অপ্রাসঙ্গিকতা (noise) দূর করে দেয়। একটি সাময়িক নেটওয়ার্ক সমস্যা বা রেজিস্ট্রি ল্যাটেন্সির সামান্য বৃদ্ধি পুরো বিষয়টিকে প্রভাবিত করতে পারে না। আউটলায়ার বা ব্যতিক্রমী মানগুলোকে উপেক্ষা করা হয়; সাধারণ অভিজ্ঞতাটি রেকর্ড করা হয়।

স্মোক টেস্ট খালি টাইমারের চেয়ে কার্যকর

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

উদাহরণস্বরূপ, এটি একটি Express অ্যাপ্লিকেশন চালু করে এবং সার্ভারটি প্রত্যাশিত পোর্টে লিসেনিং শুরু করছে কি না তা নিশ্চিত করে। যদি কোডটি না চলে, তবে বেঞ্চমার্কটি সরাসরি ব্যর্থ হয়। smoke test এই সুইটটিকে একটি দৌড় প্রতিযোগিতা থেকে একটি অডিটে রূপান্তরিত করে। এটি এমন একটি প্রশ্নের উত্তর দেয় যা কেবল গতি দিতে পারে না: ইনস্টলেশনটি কি আসলে কাজ করছে?

একটি ফিচার হিসেবে আমূল সততা

canary-এর লেখক এই প্রক্রিয়ার মধ্যে তিনটি নিয়ম অন্তর্ভুক্ত করেছেন যেগুলোকে বেশিরভাগ বেঞ্চমার্ক লেখক ঐচ্ছিক হিসেবে বিবেচনা করেন।

একই খেলার মাঠ (Same playing field)। বিভিন্ন টুলের আচরণকে স্বাভাবিক করতে ফ্ল্যাগ (Flags) ব্যবহার করা হয়। যদি কোনো প্যাকেজ ম্যানেজার ডিফল্ট সেটিংয়ের আড়ালে পারফরম্যান্সের কোনো ত্রুটি লুকিয়ে রাখে, তবে এই বেঞ্চমার্কটি সেই ত্রুটিটি প্রকাশ করে দেয়, পরিবর্তে টুলের ভুলভাবে ভালো দেখানোর সুযোগ দেয় না।

প্রকৃত কোল্ড স্টার্ট (Genuine cold starts)। শুধুমাত্র প্রথমবার নয়, প্রতিটি পুনরাবৃত্তির আগে npm cache এবং pnpm store মুছে ফেলা হয়। এখানে "প্রতিটি" (every) শব্দটি অত্যন্ত গুরুত্বপূর্ণ ভূমিকা পালন করছে। অনেক বেঞ্চমার্ক একবার ক্যাশ পরিষ্কার করে, তারপর পরপর পাঁচটি ইনস্টলেশন চালায়। দ্বিতীয় থেকে পঞ্চম রানগুলো প্রকৃতপক্ষে কোল্ড স্টার্ট নয়, এবং সেই অনুযায়ী সংখ্যাগুলো বাড়িয়ে দেখায়। canary প্রতিবার শূন্য থেকে শুরু করে।

প্রকাশ্য ব্যর্থতার অবস্থা (Public failure states)। যখন কোনো নতুন রিলিজ কোনো কিছু ভেঙে ফেলে, তখন রিপোজিটরি একটি লাল ব্যর্থতার অবস্থায় (red failure state) থাকে। সমাধান না আসা পর্যন্ত এটি ফ্রন্ট পেজে কুৎসিত এবং অমীমাংসিত অবস্থায় পড়ে থাকে। ড্যাশবোর্ডকে সবুজ দেখানোর জন্য কোনো গোপনীয়ভাবে তথ্য চেপে রাখার ব্যবস্থা নেই। এই নীতিটি স্বচ্ছতা নিশ্চিত করে। টুলগুলো মূল্যায়নকারী একজন ব্যবহারকারী কেবল কোনটি দ্রুততম তা দেখতে পান না, বরং সময়ের সাথে কোনটি নির্ভরযোগ্য ছিল তাও দেখতে পান।

পরিদর্শনী ক্ষমতা আপসহীন

যে বেঞ্চমার্ক আপনি পুনরায় তৈরি (reproduce) করতে পারবেন না, তা কেবল একটি প্রচারণার স্লোগান মাত্র। canary একটি একক bash script-এর মাধ্যমে এই সমস্যার সমাধান করে, যা যে কাউকে লোকালি এই সুইটের যেকোনো অংশ চালানোর সুযোগ দেয়। আপনাকে কোনো ক্লাউড প্রোভাইডারের নেটওয়ার্কিং বা কোনো মেইনটেইনারের হাতে তৈরি করা এনভায়রনমেন্টের ওপর নির্ভর করতে হবে না। যদি আপনার সন্দেহ হয় যে সংখ্যাগুলো সঠিক নয়, তবে আপনি নিজেই তা তৈরি করতে পারেন।

সেই স্বচ্ছতা প্রজেক্টটিকে মেইনটেইনারদের জন্যও উপযোগী করে তোলে। যখন কোনো রিগ্রেশন (regression) ঘটে, একজন ডাউনস্ট্রিম ডেভেলপার স্ক্রিপ্টটি নিতে পারেন, টুলের রিলিজগুলো bisect করতে পারেন এবং আপস্ট্রিম টিমকে একটি