সম্পর্কে:ট্রেসিং পতাকা সহ আপনার WebGL গেমের প্রোফাইলিং

লিলি থম্পসন
Lilli Thompson

আপনি এটি পরিমাপ করতে না পারলে, আপনি এটি উন্নত করতে পারবেন না।

লর্ড কেলভিন

আপনার HTML5 গেমগুলি দ্রুত চালানোর জন্য, আপনাকে প্রথমে পারফরম্যান্সের বাধাগুলি চিহ্নিত করতে হবে, তবে এটি কঠিন হতে পারে। ফ্রেম প্রতি সেকেন্ড (FPS) ডেটা মূল্যায়ন একটি শুরু, কিন্তু সম্পূর্ণ ছবি দেখতে, আপনাকে Chrome কার্যকলাপের সূক্ষ্মতা বুঝতে হবে।

about:tracing টুলটি এমন অন্তর্দৃষ্টি প্রদান করে যা আপনাকে কার্যক্ষমতার উন্নতির লক্ষ্যে তাড়াহুড়োর কাজগুলি এড়াতে সাহায্য করে, কিন্তু যা মূলত সু-উদ্দেশ্যপূর্ণ অনুমান করা। আপনি অনেক সময় এবং শক্তি সঞ্চয় করবেন, প্রতিটি ফ্রেমের সাথে Chrome কি করছে তার একটি পরিষ্কার ছবি পাবেন এবং আপনার গেমটি অপ্টিমাইজ করতে এই তথ্যটি ব্যবহার করবেন৷

হ্যালো about:tracing

ক্রোমের about:tracing টুল আপনাকে ক্রোমের সমস্ত ক্রিয়াকলাপের একটি উইন্ডো দেয় যা সময়ের সাথে এত বেশি গ্র্যানুলারিটি সহ যে আপনি প্রথমে এটিকে অপ্রতিরোধ্য মনে করতে পারেন। ক্রোমের অনেকগুলি ফাংশন বাক্সের বাইরে ট্রেস করার জন্য যন্ত্রযুক্ত, তাই কোনও ম্যানুয়াল ইন্সট্রুমেন্টেশন না করে আপনি এখনও আপনার কর্মক্ষমতা ট্র্যাক করতে about:tracing ব্যবহার করতে পারেন৷ (আপনার JS ম্যানুয়ালি ইন্সট্রুমেন্টিং সম্পর্কে পরবর্তী বিভাগ দেখুন)

ট্রেসিং ভিউ দেখতে Chrome-এর অম্নিবক্সে (অ্যাড্রেস বার) "about:tracing" টাইপ করুন।

Chrome omnibox
Chrome-এর অম্নিবক্সে "about:tracing" টাইপ করুন

ট্রেসিং টুল থেকে, আপনি রেকর্ডিং শুরু করতে পারেন, কয়েক সেকেন্ডের জন্য আপনার গেম চালাতে পারেন এবং তারপর ট্রেস ডেটা দেখতে পারেন। এটি ডেটা দেখতে কেমন হতে পারে তার একটি উদাহরণ:

সহজ ট্রেসিং ফলাফল
সহজ ট্রেসিং ফলাফল

হ্যাঁ, যে সব ঠিক বিভ্রান্তিকর. আসুন এটি কীভাবে পড়তে হয় সে সম্পর্কে কথা বলি।

প্রতিটি সারি প্রোফাইল করা একটি প্রক্রিয়ার প্রতিনিধিত্ব করে, বাম-ডান অক্ষ সময় নির্দেশ করে, এবং প্রতিটি রঙিন বাক্স একটি ইন্সট্রুমেন্টেড ফাংশন কল। বিভিন্ন ধরনের সম্পদের জন্য সারি আছে। গেম প্রোফাইলিংয়ের জন্য সবচেয়ে আকর্ষণীয় যেগুলি হল CrGpuMain, যা দেখায় গ্রাফিক্স প্রসেসিং ইউনিট (GPU) কী করছে এবং CrRendererMain৷ প্রতিটি ট্রেসে ট্রেস পিরিয়ডের সময় প্রতিটি খোলা ট্যাবের জন্য CrRendererMain লাইন থাকে (এর মধ্যে about:tracing ট্যাব নিজেই)।

ট্রেস ডেটা পড়ার সময় আপনার প্রথম কাজ হল কোন CrRendererMain সারিটি আপনার গেমের সাথে মিলে যায় তা নির্ধারণ করা।

সহজ ট্রেসিং ফলাফল হাইলাইট
সহজ ট্রেসিং ফলাফল হাইলাইট

এই উদাহরণে দুটি প্রার্থী হল: 2216 এবং 6516। দুর্ভাগ্যবশত বর্তমানে আপনার আবেদন বাছাই করার কোনো পালিশ উপায় নেই যে লাইনটি অনেক সময় পর্যায়ক্রমিক আপডেট করছে (অথবা আপনি যদি ম্যানুয়ালি আপনার কোডের সাথে ইন্সট্রুমেন্ট করে থাকেন) ট্রেস পয়েন্ট, আপনার ট্রেস ডেটা রয়েছে এমন লাইনের সন্ধান করতে)। এই উদাহরণে, দেখে মনে হচ্ছে 6516 আপডেটের ফ্রিকোয়েন্সি থেকে একটি প্রধান লুপ চালাচ্ছে। আপনি যদি ট্রেস শুরু করার আগে অন্য সব ট্যাব বন্ধ করে দেন, সঠিক CrRendererMain খুঁজে বের করা সহজ হবে। কিন্তু আপনার গেম ব্যতীত অন্যান্য প্রক্রিয়াগুলির জন্য এখনও CrRendererMain সারি থাকতে পারে।

আপনার ফ্রেম খোঁজা

একবার আপনি আপনার গেমের ট্রেসিং টুলে সঠিক সারিটি খুঁজে পেলে, পরবর্তী ধাপ হল মূল লুপটি খুঁজে বের করা। মূল লুপটি ট্রেসিং ডেটাতে পুনরাবৃত্তি করা প্যাটার্নের মতো দেখায়। আপনি W, A, S, D কীগুলি ব্যবহার করে ট্রেসিং ডেটা নেভিগেট করতে পারেন: A এবং D বাম বা ডানে (সময়ে সামনে পিছনে) এবং ডাটা জুম ইন এবং আউট করতে W এবং S। আপনি আশা করবেন যে আপনার প্রধান লুপটি এমন একটি প্যাটার্ন হবে যা প্রতি 16 মিলিসেকেন্ডে পুনরাবৃত্তি হয় যদি আপনার গেমটি 60Hz এ চলছে।

তিনটি এক্সিকিউশন ফ্রেমের মতো দেখায়
তিনটি এক্সিকিউশন ফ্রেমের মতো দেখায়

একবার আপনি আপনার গেমের হার্টবিট সনাক্ত করার পরে, আপনি প্রতিটি ফ্রেমে আপনার কোড ঠিক কী করছে তা খুঁজে বের করতে পারেন। যতক্ষণ না আপনি ফাংশন বক্সগুলিতে পাঠ্য পড়তে না পারেন ততক্ষণ জুম ইন করতে W, A, S, D ব্যবহার করুন।

একটি মৃত্যুদন্ডের ফ্রেমে গভীর
একটি মৃত্যুদন্ডের ফ্রেমে গভীর

বাক্সের এই সংগ্রহটি বিভিন্ন ফাংশন কল দেখায়, প্রতিটি কল একটি রঙিন বাক্স দ্বারা প্রতিনিধিত্ব করে। প্রতিটি ফাংশনকে এটির উপরের বক্স দ্বারা কল করা হয়েছিল, তাই এই ক্ষেত্রে, আপনি দেখতে পারেন যে MessageLoop::RunTask যাকে RenderWidget::OnSwapBuffersComplete বলা হয়, যাকে বলা হয় RenderWidget::DoDeferredUpdate, ইত্যাদি। এই ডেটা পড়া, আপনি কি বলা হয় এবং প্রতিটি মৃত্যুদন্ড কত সময় নেয় তার একটি সম্পূর্ণ ভিউ পেতে পারেন।

কিন্তু এখানে এটা একটু আঠালো পায় যেখানে. about:tracing দ্বারা প্রকাশিত তথ্য হল Chrome সোর্স কোড থেকে আসা কাঁচা ফাংশন কল। প্রতিটি ফাংশন নাম থেকে কী করছে সে সম্পর্কে আপনি শিক্ষিত অনুমান করতে পারেন, তবে তথ্যটি ঠিক ব্যবহারকারী বান্ধব নয়। আপনার ফ্রেমের সামগ্রিক প্রবাহ দেখতে এটি দরকারী, তবে আসলে কী ঘটছে তা বোঝার জন্য আপনার আরও কিছুটা মানব পাঠযোগ্য কিছু দরকার।

ট্রেস ট্যাগ যোগ করা হচ্ছে

সৌভাগ্যবশত ট্রেস ডেটা তৈরি করতে আপনার কোডে ম্যানুয়াল ইন্সট্রুমেন্টেশন যোগ করার একটি বন্ধুত্বপূর্ণ উপায় রয়েছে: console.time এবং console.timeEnd

console.time("update");
update
();
console
.timeEnd("update");
console
.time("render");
update
();
console
.timeEnd("render");

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

ট্যাগ ম্যানুয়ালি যোগ করা হয়েছে
ট্যাগ ম্যানুয়ালি যোগ করা হয়েছে

এটি ব্যবহার করে, আপনি আপনার কোডে হটস্পট ট্র্যাক করতে মানুষের পাঠযোগ্য ট্রেসিং ডেটা তৈরি করতে পারেন।

জিপিইউ নাকি সিপিইউ?

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

প্রথমে, CrGPUMain নামের ট্রেসিং ভিউতে লাইনটি খুঁজুন, যা নির্দেশ করে যে GPU একটি নির্দিষ্ট সময়ে ব্যস্ত কিনা।

GPU এবং CPU ট্রেস

আপনি দেখতে পাচ্ছেন যে আপনার গেমের প্রতিটি ফ্রেম CrRendererMain এর পাশাপাশি GPU-তে CPU কাজ করে। উপরের ট্রেসটি একটি খুব সাধারণ ব্যবহারের ক্ষেত্রে দেখায় যেখানে প্রতিটি 16ms ফ্রেমের বেশিরভাগ জন্য CPU এবং GPU উভয়ই নিষ্ক্রিয় থাকে।

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

console.time("update");
doExtraWork
();
update
(Math.min(50, now - time));
console
.timeEnd("update");

console
.time("render");
render
();
console
.timeEnd("render");

এখন আপনি একটি ট্রেস দেখতে পাবেন যা এইরকম দেখাচ্ছে:

GPU এবং CPU ট্রেস

এই ট্রেস আমাদের কি বলে? আমরা দেখতে পাচ্ছি যে চিত্রিত ফ্রেমটি প্রায় 2270ms থেকে 2320ms পর্যন্ত যায়, যার অর্থ প্রতিটি ফ্রেম প্রায় 50ms (20Hz এর একটি ফ্রেম রেট) নিচ্ছে। আপনি আপডেট বক্সের পাশে রেন্ডার ফাংশনের প্রতিনিধিত্বকারী রঙিন বাক্সের স্লিভার দেখতে পারেন, তবে ফ্রেমটি সম্পূর্ণরূপে আপডেটের দ্বারা প্রভাবিত।

CPU-তে যা চলছে তার বিপরীতে, আপনি দেখতে পাচ্ছেন যে GPU এখনও প্রায় প্রতিটি ফ্রেমের জন্য নিষ্ক্রিয় অবস্থায় বসে আছে। এই কোডটি অপ্টিমাইজ করতে, আপনি শেডার কোডে করা যেতে পারে এমন ক্রিয়াকলাপগুলি সন্ধান করতে পারেন এবং সংস্থানগুলির সর্বোত্তম ব্যবহার করার জন্য সেগুলিকে GPU-তে স্থানান্তর করতে পারেন৷

যখন শেডার কোড নিজেই ধীর হয় এবং জিপিইউ অতিরিক্ত কাজ করে তখন কী হবে? যদি আমরা সিপিইউ থেকে অপ্রয়োজনীয় কাজ সরিয়ে ফেলি এবং তার পরিবর্তে ফ্র্যাগমেন্ট শেডার কোডে কিছু কাজ যোগ করি। এখানে একটি অপ্রয়োজনীয় ব্যয়বহুল ফ্র্যাগমেন্ট শেডার রয়েছে:

#ifdef GL_ES
precision highp
float;
#endif
void main(void) {
 
for(int i=0; i<9999; i++) {
    gl_FragColor
= vec4(1.0, 0, 0, 1.0);
 
}
}

যে shader ব্যবহার করে কোড একটি ট্রেস মত চেহারা কি?

ধীর GPU কোড ব্যবহার করার সময় GPU এবং CPU ট্রেস
ধীর GPU কোড ব্যবহার করার সময় GPU এবং CPU ট্রেস

আবার, একটি ফ্রেমের সময়কাল নোট করুন। এখানে পুনরাবৃত্তি প্যাটার্ন প্রায় 2750ms থেকে 2950ms পর্যন্ত যায়, 200ms এর সময়কাল (প্রায় 5Hz এর ফ্রেম রেট)। CrRendererMain লাইনটি প্রায় সম্পূর্ণ খালি অর্থাৎ CPU বেশিরভাগ সময় নিষ্ক্রিয় থাকে, যখন GPU ওভারলোড হয়। এটি একটি নিশ্চিত চিহ্ন যে আপনার শেডারগুলি খুব ভারী।

কম ফ্রেমরেটের কারণে ঠিক কী কারণে আপনার কাছে দৃশ্যমানতা না থাকলে, আপনি 5 Hz আপডেটটি পর্যবেক্ষণ করতে পারেন এবং গেম কোডে যেতে এবং গেমের যুক্তি অপ্টিমাইজ বা অপসারণের চেষ্টা শুরু করতে প্রলুব্ধ হতে পারেন। এই ক্ষেত্রে, এটি একেবারেই ভাল হবে না, কারণ গেম লুপে যুক্তি এমন নয় যা সময়কে খাচ্ছে। প্রকৃতপক্ষে, এই ট্রেসটি যা নির্দেশ করে তা হল যে প্রতিটি ফ্রেমে আরও বেশি CPU কাজ করা মূলত "ফ্রি" হবে যে CPU অলসভাবে ঝুলছে, তাই এটিকে আরও কাজ দিলে ফ্রেমটি কতক্ষণ লাগবে তা প্রভাবিত করবে না।

বাস্তব উদাহরণ

এখন আসুন একটি বাস্তব গেম থেকে ট্রেসিং ডেটা কেমন দেখায় তা দেখুন। ওপেন ওয়েব টেকনোলজির সাহায্যে তৈরি গেমগুলির একটি দুর্দান্ত জিনিস হল যে আপনি আপনার পছন্দের পণ্যগুলিতে কী ঘটছে তা দেখতে পারেন৷ আপনি যদি প্রোফাইলিং টুলগুলি পরীক্ষা করতে চান তবে আপনি Chrome ওয়েব স্টোর থেকে আপনার প্রিয় WebGL শিরোনামটি বেছে নিতে পারেন এবং এটি about:tracing সাথে প্রোফাইল করতে পারেন। এটি চমৎকার WebGL গেম স্কিড রেসার থেকে নেওয়া একটি উদাহরণ ট্রেস।

একটি বাস্তব খেলা ট্রেসিং
একটি বাস্তব খেলা ট্রেসিং

দেখে মনে হচ্ছে প্রতিটি ফ্রেমে প্রায় 20ms লাগে, যার মানে ফ্রেম রেট প্রায় 50 FPS। আপনি দেখতে পাচ্ছেন যে কাজটি CPU এবং GPU এর মধ্যে ভারসাম্যপূর্ণ, কিন্তু GPU হল সেই সম্পদ যার চাহিদা সবচেয়ে বেশি। ওয়েবজিএল গেমগুলির বাস্তব উদাহরণগুলি প্রোফাইলে কেমন লাগে তা আপনি দেখতে চাইলে WebGL-এর সাথে তৈরি কিছু Chrome ওয়েব স্টোর শিরোনাম সহ খেলার চেষ্টা করুন:

উপসংহার

আপনি যদি আপনার গেমটি 60Hz এ চালাতে চান, তাহলে প্রতিটি ফ্রেমের জন্য আপনার সমস্ত ক্রিয়াকলাপ 16ms CPU এবং 16ms GPU সময়ের মধ্যে ফিট করতে হবে৷ আপনার কাছে দুটি সংস্থান রয়েছে যা সমান্তরালভাবে ব্যবহার করা যেতে পারে এবং আপনি কর্মক্ষমতা সর্বাধিক করতে তাদের মধ্যে কাজ পরিবর্তন করতে পারেন। আপনার কোড আসলে কী করছে তার অন্তর্দৃষ্টি পাওয়ার জন্য Chrome-এর about:tracing ভিউ হল একটি অমূল্য হাতিয়ার এবং সঠিক সমস্যাগুলি মোকাবেলা করে আপনার বিকাশের সময়কে সর্বাধিক করতে সাহায্য করবে৷

এরপর কি?

GPU ছাড়াও, আপনি Chrome রানটাইমের অন্যান্য অংশগুলিও ট্রেস করতে পারেন৷ ক্রোম ক্যানারি, ক্রোমের প্রাথমিক পর্যায়ের সংস্করণ, IO, IndexedDB এবং অন্যান্য বেশ কয়েকটি ক্রিয়াকলাপ ট্রেস করার জন্য ব্যবহৃত হয়। ট্রেসিং ইভেন্টগুলির বর্তমান অবস্থা সম্পর্কে গভীরভাবে বোঝার জন্য আপনার এই ক্রোমিয়াম নিবন্ধটি পড়া উচিত৷

আপনি যদি একজন ওয়েব গেম ডেভেলপার হন, তাহলে নিচের ভিডিওটি দেখে নিন। এটি ক্রোম গেমগুলির জন্য পারফরম্যান্স অপ্টিমাইজেশন সম্পর্কে GDC 2012-এ Google-এর গেম ডেভেলপার অ্যাডভোকেট দলের একটি উপস্থাপনা: