জাভাস্ক্রিপ্ট কর্মক্ষমতা রহস্য সমাধান করতে ফরেনসিক এবং গোয়েন্দা কাজ ব্যবহার করুন

ভূমিকা

সাম্প্রতিক বছরগুলিতে, ওয়েব অ্যাপ্লিকেশনগুলি যথেষ্ট গতিতে বেড়েছে। অনেক অ্যাপ্লিকেশান এখন যথেষ্ট দ্রুত চলে যে আমি কিছু ডেভেলপারকে উচ্চস্বরে বলতে শুনেছি "ওয়েব কি যথেষ্ট দ্রুত?" কিছু অ্যাপ্লিকেশনের জন্য এটি হতে পারে, কিন্তু, উচ্চ কার্যকারিতা অ্যাপ্লিকেশনগুলিতে কাজ করা বিকাশকারীদের জন্য, আমরা জানি এটি যথেষ্ট দ্রুত নয়। জাভাস্ক্রিপ্ট ভার্চুয়াল মেশিন প্রযুক্তিতে আশ্চর্যজনক অগ্রগতি সত্ত্বেও, একটি সাম্প্রতিক গবেষণায় দেখা গেছে যে Google অ্যাপ্লিকেশনগুলি তাদের সময়ের 50% থেকে 70% V8 এর মধ্যে ব্যয় করে। আপনার অ্যাপ্লিকেশানের একটি সীমিত পরিমাণ সময় আছে, একটি সিস্টেমের শেভিং সাইকেল বন্ধ করার অর্থ হল অন্য সিস্টেম আরও অনেক কিছু করতে পারে৷ মনে রাখবেন, 60fps-এ চলমান অ্যাপ্লিকেশনগুলির প্রতি ফ্রেমে শুধুমাত্র 16ms আছে অন্যথায় - জ্যাঙ্ক । জাভাস্ক্রিপ্ট এবং প্রোফাইল জাভাস্ক্রিপ্ট অ্যাপ্লিকেশন অপ্টিমাইজ করার বিষয়ে জানতে পড়ুন, ভি 8 টিমের পারফরম্যান্স গোয়েন্দাদের একটি অস্পষ্ট পারফরম্যান্স সমস্যা ট্র্যাক করার গল্প থেকে একটি অস্পষ্ট পারফরম্যান্স সমস্যা খুঁজে বের করার জন্য ওজে

Google I/O 2013 সেশন

আমি এই উপাদানটি Google I/O 2013 এ উপস্থাপন করেছি৷ নীচের ভিডিওটি দেখুন:

কর্মক্ষমতা কেন গুরুত্বপূর্ণ?

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

কর্মক্ষমতা সমস্যা সমাধান

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

V8 CSI: Oz

আশ্চর্যজনক উইজার্ডস বিল্ডিং ফাইন্ড ইওর ওয়ে টু ওজ V8 টিমের সাথে একটি পারফরম্যান্স সমস্যার সাথে যোগাযোগ করেছে যা তারা নিজেরাই সমাধান করতে পারেনি। মাঝে মাঝে ওজ জমে যায়, যার ফলে জ্যাংক হয়। Oz ডেভেলপাররা Chrome DevTools-টাইমলাইন প্যানেল ব্যবহার করে কিছু প্রাথমিক তদন্ত করেছে। মেমরি ব্যবহারের দিকে তাকিয়ে তারা ভয়ঙ্কর করাত দাঁতের গ্রাফের মুখোমুখি হয়েছিল। প্রতি সেকেন্ডে একবার আবর্জনা সংগ্রাহক 10MB আবর্জনা সংগ্রহ করছিলেন এবং আবর্জনা সংগ্রহের বিরতি জ্যাঙ্কের সাথে সামঞ্জস্যপূর্ণ ছিল। Chrome Devtools-এ টাইমলাইন থেকে নিম্নলিখিত স্ক্রিনশটের অনুরূপ:

Devtools টাইমলাইন

ভি 8 গোয়েন্দা, জ্যাকব এবং ইয়াং মামলাটি গ্রহণ করেছিলেন। V8 টিম এবং Oz দলের জ্যাকব এবং ইয়াং এর মধ্যে যা ঘটেছিল তা অনেক আগে থেকেই ছিল। আমি এই কথোপকথনটি গুরুত্বপূর্ণ ইভেন্টগুলিতে পাতিয়েছি যা এই সমস্যাটিকে ট্র্যাক করতে সাহায্য করেছে৷

প্রমান

প্রথম ধাপ হল প্রাথমিক প্রমাণ সংগ্রহ এবং অধ্যয়ন করা।

আমরা কি ধরনের অ্যাপ্লিকেশন দেখছি?

Oz ডেমো একটি ইন্টারেক্টিভ 3D অ্যাপ্লিকেশন। এই কারণে, এটি আবর্জনা সংগ্রহের কারণে সৃষ্ট বিরতির জন্য খুব সংবেদনশীল। মনে রাখবেন, 60fps-এ চলমান একটি ইন্টারেক্টিভ অ্যাপ্লিকেশনের সমস্ত JavaScript কাজ করার জন্য 16ms আছে এবং গ্রাফিক্স কলগুলি প্রক্রিয়া করতে এবং স্ক্রীন আঁকতে Chrome-এর জন্য সেই সময়ের কিছু সময় ছেড়ে দিতে হবে৷

Oz দ্বৈত মানের উপর প্রচুর গাণিতিক গণনা করে এবং WebAudio এবং WebGL-এ ঘন ঘন কল করে।

আমরা কি ধরনের কর্মক্ষমতা সমস্যা দেখছি?

আমরা পজস ওরফে ফ্রেম ড্রপস ওরফে জ্যাঙ্ক দেখছি। এই বিরতিগুলি আবর্জনা সংগ্রহের সাথে সম্পর্কযুক্ত।

বিকাশকারীরা কি সর্বোত্তম অনুশীলনগুলি অনুসরণ করছেন?

হ্যাঁ, Oz বিকাশকারীরা JavaScript VM কর্মক্ষমতা এবং অপ্টিমাইজেশান কৌশলগুলিতে পারদর্শী। এটি লক্ষণীয় যে Oz বিকাশকারীরা তাদের উত্স ভাষা হিসাবে CoffeeScript ব্যবহার করছিল এবং CoffeeScript কম্পাইলারের মাধ্যমে জাভাস্ক্রিপ্ট কোড তৈরি করছিল। Oz ডেভেলপারদের লেখা কোড এবং V8 ব্যবহার করা কোডের মধ্যে সংযোগ বিচ্ছিন্ন হওয়ার কারণে এটি তদন্তকে আরও জটিল করে তুলেছে। Chrome DevTools এখন সোর্স ম্যাপ সমর্থন করে যা এটিকে আরও সহজ করে তুলত।

আবর্জনা সংগ্রহকারী কেন চালায়?

জাভাস্ক্রিপ্টের মেমরি VM দ্বারা বিকাশকারীর জন্য স্বয়ংক্রিয়ভাবে পরিচালিত হয়। V8 একটি সাধারণ আবর্জনা সংগ্রহের ব্যবস্থা ব্যবহার করে যেখানে মেমরি দুটি (বা তার বেশি) প্রজন্মে বিভক্ত। তরুণ প্রজন্মের কাছে এমন বস্তু রয়েছে যা সম্প্রতি বরাদ্দ করা হয়েছে। যদি একটি বস্তু দীর্ঘকাল বেঁচে থাকে তবে তা পুরানো প্রজন্মে স্থানান্তরিত হয়।

পুরানো প্রজন্মের তুলনায় তরুণ প্রজন্ম অনেক বেশি ফ্রিকোয়েন্সিতে সংগ্রহ করা হয়। এটি ডিজাইন অনুসারে, কারণ তরুণ প্রজন্মের সংগ্রহ অনেক সস্তা। প্রায়শই মনে করা নিরাপদ যে ঘন ঘন জিসি বিরতি তরুণ প্রজন্মের সংগ্রহের কারণে হয়।

V8-এ তরুণ মেমরি স্পেস দুটি সমান আকারের মেমরির সংলগ্ন ব্লকে বিভক্ত। মেমরির এই দুটি ব্লকের মধ্যে শুধুমাত্র একটি যেকোন সময়ে ব্যবহার করা হয় এবং একে বলা হয় মহাকাশে। টু স্পেসে মেমরি অবশিষ্ট থাকলেও একটি নতুন বস্তু বরাদ্দ করা সস্তা। নতুন অবজেক্টের জন্য প্রয়োজনীয় বাইটের সংখ্যার মধ্যে একটি কার্সারকে স্থানান্তর করা হয়। এটি চলতে থাকে যতক্ষণ না পর্যন্ত স্থানটি নিঃশেষ হয়ে যায়। এই মুহুর্তে প্রোগ্রামটি বন্ধ হয়ে যায় এবং সংগ্রহ শুরু হয়।

V8 তরুণ স্মৃতি

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

স্বজ্ঞাতভাবে আপনার বোঝা উচিত যে প্রতিবারই একটি বস্তুকে হয় নিহিতভাবে বা স্পষ্টভাবে বরাদ্দ করা হয় (নতুন, [], বা {}কে কলের মাধ্যমে) আপনার অ্যাপ্লিকেশনটি আবর্জনা সংগ্রহের এবং ভয়ঙ্কর অ্যাপ্লিকেশন বিরতির কাছাকাছি এবং কাছাকাছি চলে যাচ্ছে।

এই অ্যাপ্লিকেশনের জন্য কি 10MB/সেকেন্ড আবর্জনা প্রত্যাশিত?

সংক্ষেপে, না। ডেভেলপার 10MB/সেকেন্ড আবর্জনা আশা করার জন্য কিছু করছে না।

সন্দেহভাজন

তদন্তের পরবর্তী পর্যায়ে সম্ভাব্য সন্দেহভাজনদের নির্ধারণ করা এবং তারপরে তাদের নামিয়ে দেওয়া।

সন্দেহভাজন # 1

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

সন্দেহভাজন নম্বর 2

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

সন্দেহভাজন #3

অপ্টিমাইজড কোডে পাটিগণিত। অঅপ্টিমাইজড কোডে সমস্ত গণনার ফলাফল প্রকৃত বস্তু বরাদ্দ করা হচ্ছে। উদাহরণস্বরূপ, এই স্নিপেট:

var a = p * d;
var b = c + 3;
var c = 3.3 * dt;
point.x = a * b * c;

5টি HeapNumber অবজেক্টের ফলাফল তৈরি করা হচ্ছে। প্রথম তিনটি ভেরিয়েবলের জন্য, a, b, এবং c। 4র্থটি বেনামী মানের (a*b) জন্য এবং 5মটি #4*c থেকে; 5ম শেষ পর্যন্ত পয়েন্ট.x এ বরাদ্দ করা হয়েছে।

Oz ফ্রেম প্রতি এই অপারেশন হাজার হাজার করে. যদি এই কম্পিউটেশনগুলির মধ্যে কোনও ফাংশন ঘটে যা কখনই অপ্টিমাইজ করা হয় না, সেগুলি আবর্জনার কারণ হতে পারে। কারণ অপ্টিমাইজ করা কম্পিউটেশন অস্থায়ী ফলাফলের জন্যও মেমরি বরাদ্দ করে।

সন্দেহভাজন # 4

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

sprite.position.x += 0.5 * (dt);

অপ্টিমাইজ করা কোডে, প্রতিবার x একটি নতুন গণনা করা মান, একটি আপাতদৃষ্টিতে নিরীহ বিবৃতি বরাদ্দ করা হয়, একটি নতুন HeapNumber অবজেক্ট নিহিতভাবে বরাদ্দ করা হয়, যা আমাদের আবর্জনা সংগ্রহের বিরতির কাছাকাছি নিয়ে আসে।

মনে রাখবেন যে একটি টাইপ করা অ্যারে ব্যবহার করে (অথবা একটি নিয়মিত অ্যারে যা শুধুমাত্র দ্বিগুণ ধারণ করে) আপনি এই নির্দিষ্ট সমস্যাটিকে সম্পূর্ণরূপে এড়াতে পারেন কারণ ডাবল নির্ভুল সংখ্যার জন্য স্টোরেজ শুধুমাত্র একবার বরাদ্দ করা হয় এবং বারবার মান পরিবর্তন করার জন্য নতুন স্টোরেজ বরাদ্দ করার প্রয়োজন হয় না। .

সন্দেহভাজন #4 একটি সম্ভাবনা।

ফরেনসিক

এই মুহুর্তে গোয়েন্দাদের কাছে দুটি সম্ভাব্য সন্দেহভাজন রয়েছে: বস্তুর বৈশিষ্ট্য হিসাবে হিপ সংখ্যা সংরক্ষণ করা এবং অঅপ্টিমাইজড ফাংশনগুলির মধ্যে ঘটছে গাণিতিক গণনা। ল্যাবে যাওয়ার এবং কোন সন্দেহভাজন দোষী তা নিশ্চিতভাবে নির্ধারণ করার সময় ছিল। দ্রষ্টব্য: এই বিভাগে আমি প্রকৃত Oz সোর্স কোডে পাওয়া সমস্যার একটি পুনরুৎপাদন ব্যবহার করব। এই পুনরুৎপাদন হল মূল কোডের চেয়ে ছোট মাত্রার আদেশ, তাই যুক্তি করা সহজ।

পরীক্ষা #1

সন্দেহভাজন #3 পরীক্ষা করা হচ্ছে (অঅপ্টিমাইজড ফাংশনের ভিতরে গাণিতিক গণনা)। V8 জাভাস্ক্রিপ্ট ইঞ্জিনে একটি লগিং সিস্টেম বিল্টইন রয়েছে যা হুডের নীচে কী ঘটছে সে সম্পর্কে দুর্দান্ত অন্তর্দৃষ্টি প্রদান করতে পারে।

ক্রোম মোটেও চলছে না দিয়ে শুরু করে, পতাকা সহ ক্রোম চালু করা:

--no-sandbox --js-flags="--prof --noprof-lazy --log-timer-events"

এবং তারপর সম্পূর্ণরূপে ক্রোম ছাড়ার ফলে বর্তমান ডিরেক্টরিতে একটি v8.log ফাইল আসবে৷

v8.log-এর বিষয়বস্তু ব্যাখ্যা করার জন্য, আপনাকে অবশ্যই v8-এর একই সংস্করণ ডাউনলোড করতে হবে যা আপনার Chrome ব্যবহার করছে (সম্পর্কে: সংস্করণ পরীক্ষা করুন), এবং এটি তৈরি করুন

সফলভাবে v8 তৈরি করার পরে, আপনি টিক প্রসেসর ব্যবহার করে লগ প্রক্রিয়া করতে পারেন:

$ tools/linux-tick-processor /path/to/v8.log

(আপনার প্ল্যাটফর্মের উপর নির্ভর করে লিনাক্সের জন্য ম্যাক বা উইন্ডোজ বিকল্প করুন।) (এই টুলটি অবশ্যই v8-এর শীর্ষ স্তরের সোর্স ডিরেক্টরি থেকে চালানো উচিত।)

টিক প্রসেসর জাভাস্ক্রিপ্ট ফাংশনগুলির একটি পাঠ্য ভিত্তিক সারণী প্রদর্শন করে যাতে সর্বাধিক টিক ছিল:

[JavaScript]:
ticks  total  nonlib   name
167   61.2%   61.2%  LazyCompile: *opt demo.js:12
 40   14.7%   14.7%  LazyCompile: unopt demo.js:20
 15    5.5%    5.5%  Stub: KeyedLoadElementStub
 13    4.8%    4.8%  Stub: BinaryOpStub_MUL_Alloc_Number+Smi
  6    2.2%    2.2%  Stub: BinaryOpStub_ADD_OverwriteRight_Number+Number
  4    1.5%    1.5%  Stub: KeyedStoreElementStub
  4    1.5%    1.5%  KeyedLoadIC:  {12}
  2    0.7%    0.7%  KeyedStoreIC:  {13}
  1    0.4%    0.4%  LazyCompile: ~main demo.js:30

আপনি দেখতে পারেন demo.js এর তিনটি ফাংশন ছিল: অপ্ট, আনঅপ্ট এবং প্রধান। অপ্টিমাইজ করা ফাংশনগুলির নামের পাশে একটি তারকাচিহ্ন (*) থাকে। লক্ষ্য করুন যে ফাংশন opt অপ্টিমাইজ করা হয়েছে এবং unopt অপ্টিমাইজ করা হয়েছে।

V8 গোয়েন্দার টুল ব্যাগের আরেকটি গুরুত্বপূর্ণ টুল হল প্লট-টাইমার-ইভেন্ট। এটি এভাবে কার্যকর করা যেতে পারে:

$ tools/plot-timer-event /path/to/v8.log

চালানোর পর, timer-events.png নামে একটি পিএনজি ফাইল বর্তমান ডিরেক্টরিতে থাকে। এটি খুললে আপনার এমন কিছু দেখতে হবে যা এইরকম দেখাচ্ছে:

টাইমার ইভেন্ট

নীচে বরাবর গ্রাফ বাদে, ডেটা সারিগুলিতে প্রদর্শিত হয়। X অক্ষ হল সময় (ms)। বাম দিকে প্রতিটি সারির জন্য লেবেল রয়েছে:

টাইমার ইভেন্ট Y অক্ষ

V8.Execute সারিতে প্রতিটি প্রোফাইল টিক যেখানে V8 জাভাস্ক্রিপ্ট কোড নির্বাহ করছিল সেখানে কালো উল্লম্ব রেখা আঁকা আছে। V8.GCScavenger-এর প্রতিটি প্রোফাইল টিক যেখানে V8 একটি নতুন প্রজন্মের সংগ্রহ সম্পাদন করছিল সেখানে একটি নীল উল্লম্ব রেখা আঁকা হয়েছে। একইভাবে বাকি V8 রাজ্যের জন্য।

সবচেয়ে গুরুত্বপূর্ণ সারিগুলির মধ্যে একটি হল "কোড ধরনের কার্যকর করা হচ্ছে"। যখনই অপ্টিমাইজ করা কোডটি কার্যকর করা হবে তখন এটি সবুজ হবে এবং যখনই অপ্টিমাইজ করা কোডটি কার্যকর করা হচ্ছে তখন লাল এবং নীল রঙের মিশ্রণ হবে৷ নিম্নলিখিত স্ক্রিনশটটি অপ্টিমাইজ করা থেকে অপ্টিমাইজ করা এবং তারপরে অপ্টিমাইজ করা কোডে ট্রানজিশন দেখায়:

কোড ধরনের নির্বাহ করা হচ্ছে

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

আপনি যদি এই দৈর্ঘ্যে চলে যান তবে এটি লক্ষণীয় যে আপনি আপনার অ্যাপ্লিকেশনটিকে রিফ্যাক্টর করে আরও দ্রুত কাজ করতে পারেন যাতে এটি v8 ডিবাগ শেলে চলতে পারে: d8। d8 ব্যবহার করলে আপনি টিক-প্রসেসর এবং প্লট-টাইমার-ইভেন্ট সরঞ্জামগুলির সাথে দ্রুত পুনরাবৃত্তির সময় পাবেন। D8 ব্যবহার করার আরেকটি পার্শ্বপ্রতিক্রিয়া হল প্রকৃত সমস্যাকে বিচ্ছিন্ন করা সহজ হয়ে যায়, ডেটাতে উপস্থিত শব্দের পরিমাণ কমিয়ে দেয়।

Oz সোর্স কোড থেকে টাইমার ইভেন্ট প্লট দেখে, অপ্টিমাইজ করা থেকে আনঅপ্টিমাইজ করা কোডে একটি ট্রানজিশন দেখায় এবং, অপ্টিমাইজ করা কোড চালানোর সময় অনেক নতুন প্রজন্মের সংগ্রহ ট্রিগার করা হয়েছিল, নিম্নলিখিত স্ক্রিনশটের মতো (নোট সময় মাঝখানে সরানো হয়েছে):

টাইমার ঘটনা প্লট

আপনি যদি ঘনিষ্ঠভাবে লক্ষ্য করেন তবে আপনি দেখতে পাবেন যে V8 কখন জাভাস্ক্রিপ্ট কোড চালাচ্ছে তা নির্দেশ করে সেই কালো রেখাগুলি নতুন প্রজন্মের সংগ্রহের (নীল লাইন) হিসাবে একই প্রোফাইল টিক বারে অনুপস্থিত। এটি স্পষ্টভাবে দেখায় যে যখন আবর্জনা সংগ্রহ করা হচ্ছে, তখন স্ক্রিপ্টটি থামানো হয়েছে।

Oz সোর্স কোড থেকে টিক প্রসেসরের আউটপুট দেখে, শীর্ষ ফাংশন (updateSprites) অপ্টিমাইজ করা হয়নি। অন্য কথায়, যে ফাংশনে প্রোগ্রামটি সবচেয়ে বেশি সময় ব্যয় করেছিল সেটিও অপ্টিমাইজ করা হয়েছিল। এটি দৃঢ়ভাবে নির্দেশ করে যে সন্দেহভাজন #3 অপরাধী। UpdateSprites-এর উৎসে লুপ রয়েছে যা দেখতে এইরকম:

function updateSprites(dt) {
    for (var sprite in sprites) {
        sprite.position.x += 0.5 * dt;
        // 20 more lines of arithmetic computation.
    }
}

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

পরীক্ষা #2

এই পতাকা দিয়ে Chrome চালানো হচ্ছে:

--js-flags="--trace-deopt --trace-opt-verbose"

অপ্টিমাইজেশান এবং ডিঅপ্টিমাইজেশন ডেটার একটি ভার্বোস লগ প্রদর্শন করে৷ আপডেট স্প্রাইটের জন্য ডেটা অনুসন্ধান করে আমরা পাই:

[আপডেটস্প্রাইটের জন্য অপ্টিমাইজেশান অক্ষম, কারণ: ForInStatement দ্রুত কেস নয়]

ঠিক যেমন গোয়েন্দারা অনুমান করেছিলেন, ফর-আই-ইন লুপ কনস্ট্রাক্ট ছিল কারণ।

মামলা বন্ধ

আপডেট স্প্রাইট অপ্টিমাইজ না হওয়ার কারণ আবিষ্কার করার পরে, সমাধানটি সহজ ছিল, কেবল গণনাটিকে তার নিজস্ব ফাংশনে সরান, এটি হল:

function updateSprite(sprite, dt) {
    sprite.position.x += 0.5 * dt;
    // 20 more lines of arithmetic computation.
}

function updateSprites(dt) {
    for (var sprite in sprites) {
        updateSprite(sprite, dt);
    }
}

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

উপসংহার

Oz বিকাশকারীরা সেখানে থামেনি। V8 গোয়েন্দাদের দ্বারা তাদের সাথে ভাগ করা সরঞ্জাম এবং কৌশলগুলির সাথে সজ্জিত, তারা আরও কয়েকটি ফাংশন খুঁজে পেতে সক্ষম হয়েছিল যেগুলি ডিঅপ্টিমাইজেশন হেলে আটকে ছিল এবং কম্পিউটেশন কোডটিকে পাতার ফাংশনে ফ্যাক্টর করে যা অপ্টিমাইজ করা হয়েছিল, যার ফলে আরও ভাল পারফরম্যান্স হয়েছিল।

সেখানে যান এবং কিছু কর্মক্ষমতা অপরাধের সমাধান শুরু করুন!