WebAssembly দ্রুত ডিবাগিং

Philip Pfaffe
কিম-আন ট্রান
Kim-Anh Tran
Eric Leese
Sam Clegg

Chrome Dev Summit 2020- এ, আমরা প্রথমবারের মতো ওয়েবে WebAssembly অ্যাপ্লিকেশনের জন্য Chrome-এর ডিবাগিং সমর্থন ডেমো করেছি। তারপর থেকে, দলটি বড় এবং এমনকি বিশাল অ্যাপ্লিকেশনগুলির জন্য বিকাশকারীর অভিজ্ঞতা স্কেল তৈরি করতে প্রচুর শক্তি বিনিয়োগ করেছে। এই পোস্টে আমরা আপনাকে দেখাব যে আমরা বিভিন্ন সরঞ্জামগুলিতে যোগ করেছি (বা কাজ করেছি) এবং কীভাবে সেগুলি ব্যবহার করতে হয়!

স্কেলেবল ডিবাগিং

আমাদের 2020 পোস্টে আমরা যেখান থেকে রেখেছিলাম তা শুরু করুন। আমরা তখন যে উদাহরণটি দেখছিলাম তা এখানে:

#include <SDL2/SDL.h>
#include <complex>

int main() {
  // Init SDL.
  int width = 600, height = 600;
  SDL_Init(SDL_INIT_VIDEO);
  SDL_Window* window;
  SDL_Renderer* renderer;
  SDL_CreateWindowAndRenderer(width, height, SDL_WINDOW_OPENGL, &window,
                              &renderer);

  // Generate a palette with random colors.
  enum { MAX_ITER_COUNT = 256 };
  SDL_Color palette[MAX_ITER_COUNT];
  srand(time(0));
  for (int i = 0; i < MAX_ITER_COUNT; ++i) {
    palette[i] = {
        .r = (uint8_t)rand(),
        .g = (uint8_t)rand(),
        .b = (uint8_t)rand(),
        .a = 255,
    };
  }

  // Calculate and draw the Mandelbrot set.
  std::complex<double> center(0.5, 0.5);
  double scale = 4.0;
  for (int y = 0; y < height; y++) {
    for (int x = 0; x < width; x++) {
      std::complex<double> point((double)x / width, (double)y / height);
      std::complex<double> c = (point - center) * scale;
      std::complex<double> z(0, 0);
      int i = 0;
      for (; i < MAX_ITER_COUNT - 1; i++) {
        z = z * z + c;
        if (abs(z) > 2.0)
          break;
      }
      SDL_Color color = palette[i];
      SDL_SetRenderDrawColor(renderer, color.r, color.g, color.b, color.a);
      SDL_RenderDrawPoint(renderer, x, y);
    }
  }

  // Render everything we've drawn to the canvas.
  SDL_RenderPresent(renderer);

  // SDL_Quit();
}

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

শেষ পোস্টে, আমরা আলোচনা করেছি কিভাবে এই উদাহরণটি কম্পাইল এবং ডিবাগ করতে হয়। আসুন এটি আবার করি, তবে আসুন //performance// এও উঁকি দেওয়া যাক :

$ emcc -sUSE_SDL=2 -g -O0 -o mandelbrot.html mandelbrot.cc -sALLOW_MEMORY_GROWTH

এই কমান্ডটি একটি 3MB wasm বাইনারি তৈরি করে। এবং যে বাল্ক, আপনি আশা করতে পারেন, ডিবাগ তথ্য. আপনি llvm-objdump টুল [1] দিয়ে এটি যাচাই করতে পারেন উদাহরণস্বরূপ:

$ llvm-objdump -h mandelbrot.wasm

mandelbrot.wasm:        file format wasm

Sections:
Idx Name          Size     VMA      Type
  0 TYPE          0000026f 00000000
  1 IMPORT        00001f03 00000000
  2 FUNCTION      0000043e 00000000
  3 TABLE         00000007 00000000
  4 MEMORY        00000007 00000000
  5 GLOBAL        00000021 00000000
  6 EXPORT        0000014a 00000000
  7 ELEM          00000457 00000000
  8 CODE          0009308a 00000000 TEXT
  9 DATA          0000e4cc 00000000 DATA
 10 name          00007e58 00000000
 11 .debug_info   000bb1c9 00000000
 12 .debug_loc    0009b407 00000000
 13 .debug_ranges 0000ad90 00000000
 14 .debug_abbrev 000136e8 00000000
 15 .debug_line   000bb3ab 00000000
 16 .debug_str    000209bd 00000000

এই আউটপুটটি আমাদেরকে জেনারেট করা wasm ফাইলে থাকা সমস্ত বিভাগ দেখায়, তাদের বেশিরভাগই স্ট্যান্ডার্ড WebAssembly বিভাগ, কিন্তু এছাড়াও বেশ কয়েকটি কাস্টম বিভাগ রয়েছে যার নাম .debug_ দিয়ে শুরু হয়। যেখানে বাইনারি আমাদের ডিবাগ তথ্য ধারণ করে! যদি আমরা সমস্ত আকার যোগ করি, আমরা দেখতে পাই যে ডিবাগ তথ্য আমাদের 3MB ফাইলের প্রায় 2.3MB তৈরি করে। যদি আমরা emcc কমান্ডের time , আমরা দেখতে পাই যে আমাদের মেশিনে এটি চালানোর জন্য প্রায় 1.5 সেকেন্ড সময় নেয়। এই সংখ্যাগুলি একটি সুন্দর ছোট বেসলাইন তৈরি করে, তবে এগুলি এত ছোট যে সম্ভবত কেউ তাদের সম্পর্কে নজর দেবে না। বাস্তব অ্যাপ্লিকেশনে, যদিও, ডিবাগ বাইনারি সহজেই GBs আকারে পৌঁছাতে পারে এবং তৈরি করতে কয়েক মিনিট সময় নেয়!

বাইনারিন এড়িয়ে যাওয়া

Emscripten এর সাথে একটি wasm অ্যাপ্লিকেশন তৈরি করার সময়, এটির একটি চূড়ান্ত বিল্ড ধাপ হল Binaryen অপ্টিমাইজার চালানো। Binaryen হল একটি কম্পাইলার টুলকিট যা WebAssembly(-like) বাইনারিগুলিকে অপ্টিমাইজ এবং বৈধ করে। বিল্ডের অংশ হিসাবে Binaryen চালানো মোটামুটি ব্যয়বহুল, কিন্তু এটি শুধুমাত্র কিছু নির্দিষ্ট শর্তে প্রয়োজন। ডিবাগ বিল্ডগুলির জন্য, আমরা যদি বাইনারিন পাসের প্রয়োজন এড়াতে পারি তবে আমরা বিল্ড টাইমকে উল্লেখযোগ্যভাবে দ্রুত করতে পারি। 64 বিট পূর্ণসংখ্যা মান সম্বলিত ফাংশন স্বাক্ষর বৈধ করার জন্য সবচেয়ে সাধারণ প্রয়োজনীয় Binaryen পাস। -sWASM_BIGINT ব্যবহার করে WebAssembly BigInt ইন্টিগ্রেশন নির্বাচন করে আমরা এটি এড়াতে পারি।

$ emcc -sUSE_SDL=2 -g -O0 -o mandelbrot.html mandelbrot.cc -sALLOW_MEMORY_GROWTH -sWASM_BIGINT -sERROR_ON_WASM_CHANGES_AFTER_LINK

আমরা ভাল পরিমাপের জন্য -sERROR_ON_WASM_CHANGES_AFTER_LINK পতাকা নিক্ষেপ করেছি৷ এটি সনাক্ত করতে সাহায্য করে কখন বাইনারিন চলছে এবং বাইনারিটি অপ্রত্যাশিতভাবে পুনরায় লেখা হচ্ছে। এইভাবে, আমরা নিশ্চিত করতে পারি যে আমরা দ্রুত পথে রয়েছি।

যদিও আমাদের উদাহরণ মোটামুটি ছোট, আমরা এখনও বাইনারিনকে এড়িয়ে যাওয়ার প্রভাব দেখতে পাচ্ছি! time অনুযায়ী, এই কমান্ডটি 1 সেকেন্ডের নিচে চলে, তাই আগের চেয়ে অর্ধ সেকেন্ড দ্রুত!

উন্নত tweaks

ইনপুট ফাইল স্ক্যানিং এড়িয়ে যাওয়া

সাধারণত একটি Emscripten প্রকল্প লিঙ্ক করার সময়, emcc সমস্ত ইনপুট অবজেক্ট ফাইল এবং লাইব্রেরি স্ক্যান করবে। এটি আপনার প্রোগ্রামে জাভাস্ক্রিপ্ট লাইব্রেরি ফাংশন এবং নেটিভ চিহ্নগুলির মধ্যে সুনির্দিষ্ট নির্ভরতা বাস্তবায়নের জন্য এটি করে। বড় প্রকল্পগুলির জন্য ইনপুট ফাইলগুলির এই অতিরিক্ত স্ক্যানিং ( llvm-nm ব্যবহার করে) লিঙ্কের সময় উল্লেখযোগ্যভাবে যোগ করতে পারে।

পরিবর্তে -sREVERSE_DEPS=all দিয়ে চালানো সম্ভব যা emcc জাভাস্ক্রিপ্ট ফাংশনের সমস্ত সম্ভাব্য নেটিভ নির্ভরতা অন্তর্ভুক্ত করতে বলে। এটির ওভারহেডের একটি ছোট কোড আকার রয়েছে তবে লিঙ্কের সময়কে দ্রুত করতে পারে এবং ডিবাগ বিল্ডগুলির জন্য দরকারী হতে পারে।

আমাদের উদাহরণের মতো ছোট একটি প্রকল্পের জন্য এটি কোনও বাস্তব পার্থক্য করে না তবে আপনার প্রকল্পে যদি আপনার শত শত বা এমনকি হাজার হাজার অবজেক্ট ফাইল থাকে তবে এটি লিঙ্কের সময়কে অর্থপূর্ণভাবে উন্নত করতে পারে।

"নাম" বিভাগটি খুলে ফেলা

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

$ emstrip --no-strip-all --remove-section=name mandelbrot.wasm

এটি DWARF ডিবাগ বিভাগগুলি সংরক্ষণ করার সময় WebAssembly "নাম" বিভাগটি সরিয়ে ফেলবে।

ডিবাগ ফিশন

প্রচুর ডিবাগ ডেটা সহ বাইনারিগুলি কেবল বিল্ড সময়ের উপর চাপ দেয় না তবে ডিবাগিং সময়ের উপরও। ডিবাগারকে ডেটা লোড করতে হবে এবং এটির জন্য একটি সূচক তৈরি করতে হবে, যাতে এটি দ্রুত প্রশ্নের উত্তর দিতে পারে, যেমন "স্থানীয় ভেরিয়েবল x এর ধরন কি?"।

ডিবাগ ফিশন আমাদের একটি বাইনারির ডিবাগ তথ্যকে দুটি ভাগে ভাগ করতে দেয়: একটি, যা বাইনারিতে থাকে এবং একটি, যা একটি পৃথক, তথাকথিত DWARF অবজেক্ট ( .dwo ) ফাইলে থাকে৷ Emscripten-এ -gsplit-dwarf পতাকা পাস করে এটি সক্ষম করা যেতে পারে:

$ emcc -sUSE_SDL=2 -g -gsplit-dwarf -gdwarf-5 -O0 -o mandelbrot.html mandelbrot.cc  -sALLOW_MEMORY_GROWTH -sWASM_BIGINT -sERROR_ON_WASM_CHANGES_AFTER_LINK

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

বিভিন্ন কমান্ড এবং কি ফাইল তৈরি করা হয়

DWARF ডেটা বিভক্ত করার সময়, ডিবাগ ডেটার একটি অংশ বাইনারির সাথে থাকে, যেখানে বড় অংশটি mandelbrot.dwo ফাইলে রাখা হয় (উপরে চিত্রিত)।

mandelbrot জন্য আমাদের কাছে শুধুমাত্র একটি সোর্স ফাইল রয়েছে, তবে সাধারণত প্রকল্পগুলি এর চেয়ে বড় এবং একাধিক ফাইল অন্তর্ভুক্ত করে। ডিবাগ ফিশন তাদের প্রত্যেকের জন্য একটি .dwo ফাইল তৈরি করে। ডিবাগারের বর্তমান বিটা সংস্করণের জন্য (0.1.6.1615) এই বিভক্ত ডিবাগ তথ্য লোড করতে সক্ষম হওয়ার জন্য, আমাদের এগুলিকে একটি তথাকথিত DWARF প্যাকেজে ( .dwp ) বান্ডিল করতে হবে:

$ emdwp -e mandelbrot.wasm -o mandelbrot.dwp

একটি DWARF প্যাকেজে dwo ফাইল বান্ডিল করুন

পৃথক বস্তুর বাইরে DWARF প্যাকেজ তৈরি করার সুবিধা রয়েছে যে আপনাকে শুধুমাত্র একটি অতিরিক্ত ফাইল পরিবেশন করতে হবে! আমরা বর্তমানে ভবিষ্যতের রিলিজে সমস্ত পৃথক বস্তু লোড করার জন্যও কাজ করছি।

DWARF 5 এর সাথে কী আছে?

আপনি হয়তো লক্ষ্য করেছেন, আমরা উপরের emcc কমান্ডে আরেকটি পতাকা ছিঁড়েছি, -gdwarf-5 । DWARF চিহ্নগুলির সংস্করণ 5 সক্ষম করা, যা বর্তমানে ডিফল্ট নয়, আমাদের দ্রুত ডিবাগিং শুরু করতে সাহায্য করার আরেকটি কৌশল। এটির সাহায্যে, কিছু তথ্য মূল বাইনারিতে সংরক্ষণ করা হয় যা ডিফল্ট সংস্করণ 4 বাদ দেওয়া হয়। বিশেষ করে, আমরা মূল বাইনারি থেকে উৎস ফাইলের সম্পূর্ণ সেট নির্ধারণ করতে পারি। এটি ডিবাগারকে সম্পূর্ণ সোর্স ট্রি দেখানো এবং সম্পূর্ণ প্রতীক ডেটা লোড ও পার্স না করে ব্রেকপয়েন্ট সেট করার মতো মৌলিক কাজ করতে দেয়। এটি বিভক্ত চিহ্নগুলির সাথে ডিবাগিংকে অনেক দ্রুত করে তোলে, তাই আমরা সর্বদা -gsplit-dwarf এবং -gdwarf-5 কমান্ড লাইন পতাকাগুলি একসাথে ব্যবহার করি!

DWARF5 ডিবাগ ফরম্যাটের সাথে আমরা আরেকটি দরকারী বৈশিষ্ট্যের অ্যাক্সেসও পাই। এটি ডিবাগ ডেটাতে একটি নাম সূচী প্রবর্তন করে যা -gpubnames পতাকা পাস করার সময় তৈরি করা হবে:

$ emcc -sUSE_SDL=2 -g -gdwarf-5 -gsplit-dwarf -gpubnames -O0 -o mandelbrot.html mandelbrot.cc -sALLOW_MEMORY_GROWTH -sWASM_BIGINT -sERROR_ON_WASM_CHANGES_AFTER_LINK

একটি ডিবাগিং সেশনের সময়, প্রতীক সন্ধান প্রায়শই নামের দ্বারা একটি সত্তা অনুসন্ধান করার মাধ্যমে ঘটে, যেমন, একটি পরিবর্তনশীল বা একটি প্রকারের সন্ধান করার সময়। নাম সূচী সরাসরি সংকলন ইউনিটের দিকে নির্দেশ করে এই অনুসন্ধানটিকে ত্বরান্বিত করে যা সেই নামটিকে সংজ্ঞায়িত করে। একটি নাম সূচী ব্যতীত, সঠিক সংকলন ইউনিট খুঁজে পেতে সমগ্র ডিবাগ ডেটার একটি সম্পূর্ণ অনুসন্ধানের প্রয়োজন হবে যা আমরা যে নামটি খুঁজছি সেটিকে সংজ্ঞায়িত করে৷

কৌতূহলীদের জন্য: ডিবাগ ডেটা দেখছেন

DWARF ডেটাতে উঁকি দেওয়ার জন্য আপনি llvm-dwarfdump ব্যবহার করতে পারেন। আসুন এটি চেষ্টা করে দেখি:

llvm-dwarfdump mandelbrot.wasm

এটি আমাদের "কম্পাইল ইউনিট" (মোটামুটিভাবে বলতে গেলে, সোর্স ফাইল) সম্পর্কে একটি ওভারভিউ দেয় যার জন্য আমাদের কাছে ডিবাগ তথ্য রয়েছে। এই উদাহরণে, আমাদের কাছে শুধুমাত্র mandelbrot.cc এর জন্য ডিবাগ তথ্য আছে। সাধারণ তথ্য আমাদের জানাবে যে আমাদের একটি কঙ্কাল ইউনিট আছে, যার মানে এই যে আমাদের কাছে এই ফাইলটিতে অসম্পূর্ণ ডেটা রয়েছে এবং একটি পৃথক .dwo ফাইল রয়েছে যাতে অবশিষ্ট ডিবাগ তথ্য রয়েছে:

mandelbrot.wasm এবং ডিবাগ তথ্য

আপনি এই ফাইলের মধ্যে অন্যান্য টেবিলগুলিও দেখতে পারেন, যেমন লাইন টেবিলে যা C++ লাইনে wasm বাইটকোডের ম্যাপিং দেখায় ( llvm-dwarfdump -debug-line ব্যবহার করে দেখুন)।

এছাড়াও আমরা আলাদা .dwo ফাইলে থাকা ডিবাগ তথ্য দেখতে পারি:

llvm-dwarfdump mandelbrot.dwo

mandelbrot.wasm এবং ডিবাগ তথ্য

TL;DR: ডিবাগ ফিশন ব্যবহার করার সুবিধা কী?

ডিবাগ তথ্য বিভক্ত করার বিভিন্ন সুবিধা রয়েছে যদি কেউ বড় অ্যাপ্লিকেশনগুলির সাথে কাজ করে থাকে:

  1. দ্রুত লিঙ্কিং: লিঙ্কারকে আর সম্পূর্ণ ডিবাগ তথ্য পার্স করতে হবে না । লিঙ্কারদের সাধারণত বাইনারিতে থাকা সম্পূর্ণ DWARF ডেটা পার্স করতে হয়। ডিবাগ তথ্যের বৃহৎ অংশগুলিকে আলাদা ফাইলে সরিয়ে, লিঙ্কারগুলি ছোট বাইনারিগুলির সাথে কাজ করে, যার ফলে দ্রুত লিঙ্ক করার সময় হয় (বিশেষত বড় অ্যাপ্লিকেশনগুলির জন্য সত্য)।

  2. দ্রুত ডিবাগিং: ডিবাগার কিছু প্রতীক সন্ধানের জন্য .dwo / .dwp ফাইলগুলিতে অতিরিক্ত চিহ্নগুলি পার্স করা এড়িয়ে যেতে পারে । কিছু লুকআপের জন্য (যেমন wasm-to-C++ ফাইলের লাইন ম্যাপিংয়ের অনুরোধ), আমাদের অতিরিক্ত ডিবাগ ডেটা দেখার দরকার নেই। এটি আমাদের সময় বাঁচায়, অতিরিক্ত ডিবাগ ডেটা লোড এবং পার্স করার প্রয়োজন হয় না।

1 : আপনার সিস্টেমে llvm-objdump এর সাম্প্রতিক সংস্করণ না থাকলে এবং আপনি emsdk ব্যবহার করছেন, আপনি এটি emsdk/upstream/bin ডিরেক্টরিতে খুঁজে পেতে পারেন।

প্রিভিউ চ্যানেল ডাউনলোড করুন

আপনার ডিফল্ট ডেভেলপমেন্ট ব্রাউজার হিসেবে Chrome Canary , Dev বা Beta ব্যবহার করার কথা বিবেচনা করুন। এই পূর্বরূপ চ্যানেলগুলি আপনাকে সর্বশেষ DevTools বৈশিষ্ট্যগুলিতে অ্যাক্সেস দেয়, অত্যাধুনিক ওয়েব প্ল্যাটফর্ম API পরীক্ষা করে এবং আপনার ব্যবহারকারীদের আগে আপনার সাইটে সমস্যাগুলি খুঁজে পায়!

Chrome DevTools টিমের সাথে যোগাযোগ করা হচ্ছে

পোস্টের নতুন বৈশিষ্ট্য এবং পরিবর্তনগুলি বা DevTools সম্পর্কিত অন্য কিছু নিয়ে আলোচনা করতে নিম্নলিখিত বিকল্পগুলি ব্যবহার করুন৷

  • crbug.com এর মাধ্যমে আমাদের কাছে একটি পরামর্শ বা প্রতিক্রিয়া জমা দিন।
  • আরও বিকল্প ব্যবহার করে একটি DevTools সমস্যা রিপোর্ট করুনআরও > সাহায্য > DevTools-এ একটি DevTools সমস্যা রিপোর্ট করুন
  • @ ChromeDevTools-এ টুইট করুন।
  • আমাদের DevTools YouTube ভিডিও বা DevTools টিপস YouTube ভিডিওগুলিতে নতুন কী আছে সে সম্পর্কে মন্তব্য করুন৷