একজন ডেভেলপার লক্ষ্য করেছেন যে Playwright বা Puppeteer-এর মাধ্যমে Chrome DevTools debugger সংযুক্ত করলে fetch-ভিত্তিক আপলোড ২০ গুণেরও বেশি ধীর হয়ে যায়, যা সাধারণ পারফরম্যান্স বেঞ্চমার্কগুলোকে বিভ্রান্তিকর তথ্যে পরিণত করে।

তদন্তের সূত্রপাত ঘட்டிய সেই ধাঁধাটি

Coffer হলো একটি ব্রাউজার-ভিত্তিক ফাইল স্টোর যা সার্ভারে পাঠানোর আগে ডেটা এনক্রিপ্ট করে এবং এটি নিয়মিতভাবে লোকাল নেটওয়ার্কের মাধ্যমে গিগাবিট-ক্লাসের আপলোড সম্পন্ন করে। যখন টিম আপলোড স্পিড পরিমাপ করছিল, তারা একটি পার্থক্য দেখতে পায়: ডাউনলোডগুলো লিঙ্কটি পূর্ণ ব্যবহার (saturate) করছিল, কিন্তু আপলোডগুলো উপলব্ধ ব্যান্ডউইথের মাত্র এক-অষ্টমাংশ গতিতে চলছিল। এই অমিলটি কোড পরিবর্তনের তিনটি ধাপের জন্ম দেয় যা কোনো উল্লেখযোগ্য পরিবর্তন আনতে ব্যর্থ হয়েছিল, যতক্ষণ না চতুর্থ একটি "ফিক্স" বিশাল উন্নতি দেখাল—কিন্তু ডিবাগার সরিয়ে নেওয়ার সাথে সাথেই সেই উন্নতি উধাও হয়ে গেল।

টিম প্রথমে যা চেষ্টা করেছিল

ইঞ্জিনিয়াররা সাধারণ সন্দেহভাজন বিষয়গুলো পরীক্ষা করে দেখেছিলেন:

  • Chunk size – ব্লক সাইজ ১৬ MiB থেকে বাড়িয়ে ৩২ MiB করলেও থ্রুপুট (throughput) অপরিবর্তিত ছিল।
  • Pipelining – বর্তমান আপলোডের সাথে পরবর্তী ব্লকের এনক্রিপশন ওভারল্যাপ করার ফলে মাত্র ১৩% উন্নতি দেখা গিয়েছিল, যা পরিমাপের ত্রুটির (measurement noise) চেয়ে আলাদা কিছু মনে হয়নি।
  • Concurrency – সমান্তরালভাবে (parallel) বেশ কয়েকটি আপলোড চালালে মোট গতি একই রকম ছিল, যা একটি গ্লোবাল সিলিং (global ceiling) নির্দেশ করছিল।

এই কোনো পরিবর্তনই ৮ গুণ ধীরগতির কারণ ব্যাখ্যা করতে পারেনি।

একটি আশ্চর্যজনক সরাসরি তুলনা

সমস্যাটি শনাক্ত করতে টিম ক্লায়েন্ট ইমপ্লিমেন্টেশন পরিবর্তন করে। একই নেটওয়ার্কে .NET HttpClient ব্যবহার করে তারা 700 Mbps রেকর্ড করেছিল; কিন্তু Chromium-এর fetch() API থেকে একই রিকোয়েস্ট পাঠালে তা 140 Mbps-এ আটকে যাচ্ছিল। এই বিশাল পার্থক্য ব্রাউজারের নেটওয়ার্ক স্ট্যাককেই দোষী সাব্যস্ত করছিল—যতক্ষণ না পরবর্তী পরীক্ষা অন্য কিছু প্রমাণ করল।

ডিবাগারের লুকানো খরচ

Playwright এবং Puppeteer, Chrome DevTools Protocol (CDP)-এর মাধ্যমে Chrome-কে পরিচালনা করে। এই প্রোটোকলটি ব্রাউজার প্রসেসের সাথে একটি ডিবাগার সংযুক্ত করে, যা নেটওয়ার্ক ইভেন্ট, DOM স্ন্যাপশট এবং কনসোল লগ প্রকাশ করে। টিম একটি সুনির্দিষ্ট পরীক্ষা চালিয়েছিল: একটি fetch() কল যা একটি Uint8Array পেলোড পাঠাচ্ছিল, একবার CDP ডিবাগার সংযুক্ত অবস্থায় এবং একবার ছাড়া।

  • Debugger attached: 113 Mbps

ডিবাগারের উপস্থিতির কারণে আপলোড স্পিড ২০ গুণেরও বেশি কমে গিয়েছিল। একটি সাধারণ Edge উইন্ডোতে ম্যানুয়াল টেস্টে—যেখানে কোনো ডিবাগার সংযুক্ত ছিল না—600+ Mbps গতি পাওয়া গিয়েছিল, যা নিশ্চিত করে যে কোনো বাধা না থাকলে ব্রাউজার নিজেই এই ট্রাফিক সামলাতে পারে।

একটি সামান্য কিন্তু প্রকৃত উন্নতি

যদিও ধীরগতির মূল কারণ ছিল ডিবাগার, তবুও টিম একটি প্রকৃত অপ্টিমাইজেশন খুঁজে পেয়েছিল: রিকোয়েস্ট বডি Uint8Array থেকে Blob-এ পরিবর্তন করলে Chromium-এর গতি প্রায় ৩০% বৃদ্ধি পায়। এটি একটি কার্যকর পরিবর্তন, তবে শুরুতে আশা করা সেই "অলৌকিক" উন্নতির ধারেকাছেও নয়।

কেন এটি ইঞ্জিনিয়ারদের জন্য গুরুত্বপূর্ণ

  • যন্ত্রপাতি মিথ্যা বলতে পারে। যে পারফরম্যান্স টুলগুলো ব্রাউজার অটোমেট করে, সেগুলো নিজেই পরিমাপ প্রক্রিয়ার একটি অংশ।
  • অসম্ভব মনে হওয়া বেঞ্চমার্কগুলোর একটি স্যানিটি চেক (sanity check) করা উচিত। যদি সংখ্যাগুলো নেটওয়ার্ক ক্ষমতার তুলনায় অনেক বেশি ভিন্ন হয়, তবে পরিমাপের পরিবেশকেই প্রথম সন্দেহ করা উচিত।
  • একটি শূন্য ফলাফলও মূল্যবান। কোনো পরিবর্তন যে কোনো কাজ করছে না তা নিশ্চিত করা মানে কাল্পনিক বাগ (phantom bugs) তাড়া করার অপচয় রোধ করা।
  • ম্যানুয়াল কন্ট্রোল হলো সস্তা বিমা। একটি সাধারণ ব্রাউজার উইন্ডোতে একই অপারেশন চালিয়ে লুকানো ইন্সট্রুমেন্টেশন ওভারহেড (instrumentation overhead) শনাক্ত করা সম্ভব।

পাল্টা যুক্তি: যখন ডিবাগার অপরিহার্য

ডিবাগার পেজ বিহেভিয়ার, এরর ট্রেস এবং নেটওয়ার্ক টাইমলাইনের এমন দৃশ্যমানতা প্রদান করে যা অন্যথায় পাওয়া অসম্ভব। রিগ্রেশন টেস্টিং, সিকিউরিটি অডিট বা জটিল UI ইন্টারঅ্যাকশনের জন্য CDP ডিবাগার সংযুক্ত করা প্রায়ই অপরিহার্য হয়ে পড়ে। মূল বিষয়টি হলো ফাংশনাল টেস্টিং এবং র (raw) পারফরম্যান্স পরিমাপকে আলাদা রাখা, এবং পারফরম্যান্স পরিমাপের ক্ষেত্রে ডিবাগারটি বন্ধ রাখা।

সারকথা: যে টুলগুলো অটোমেটেড টেস্টিং সম্ভব করে তোলে, সেগুলোই পারফরম্যান্স বিকৃতির সবচেয়ে বড় উৎস হয়ে উঠতে পারে। ব্রাউজার, নেটওয়ার্ক বা কোডকে দোষারোপ করার আগে নিশ্চিত হয়ে নিন যে কোনো ডিবাগার নিঃশব্দে ডেটা স্ট্রিমকে ধীর করে দিচ্ছে না।