পারফ-সেপশনের মাধ্যমে একটি 400% দ্রুত পারফরম্যান্স প্যানেল

আন্দ্রেস অলিভারেস
Andrés Olivares
ন্যান্সি লি
Nancy Li

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

পারফরম্যান্স প্যানেল ব্যবহার করলেও নিম্নলিখিত উদাহরণটি আপনাকে নিয়ে যায়।

আমাদের প্রোফাইলিং দৃশ্যকল্প সেট আপ এবং পুনরায় তৈরি করা

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

আপনি হয়তো জানেন, DevTools নিজেই একটি ওয়েব অ্যাপ্লিকেশন। যেমন, এটি পারফরম্যান্স প্যানেল ব্যবহার করে প্রোফাইল করা যেতে পারে। এই প্যানেলটি নিজেই প্রোফাইল করতে, আপনি DevTools খুলতে পারেন এবং তারপরে এটির সাথে সংযুক্ত আরেকটি DevTools উদাহরণ খুলতে পারেন। Google-এ, এই সেটআপটি DevTools-on-DevTools নামে পরিচিত।

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

DevTools ইন্সট্যান্সের একটি স্ক্রিনশট যা DevTools-এরই উপাদানগুলি পরিদর্শন করে৷
DevTools-on-DevTools: DevTools দিয়ে DevTools পরিদর্শন করা।

দ্বিতীয় DevTools ইন্সট্যান্সে, পারফরম্যান্স প্যানেল—যাকে এখান থেকে পারফ প্যানেল বলা হবে—প্রথম DevTools ইন্সট্যান্সটি দৃশ্যকল্পটি পুনরায় তৈরি করার জন্য পর্যবেক্ষণ করে, যা একটি প্রোফাইল লোড করে।

দ্বিতীয় DevTools উদাহরণে একটি লাইভ রেকর্ডিং শুরু হয়, যখন প্রথম উদাহরণে, ডিস্কের একটি ফাইল থেকে একটি প্রোফাইল লোড হয়৷ বৃহৎ ইনপুট প্রক্রিয়াকরণের সঠিকভাবে প্রোফাইল কার্যক্ষমতার জন্য একটি বড় ফাইল লোড করা হয়। যখন উভয় দৃষ্টান্ত লোড করা শেষ হয়, তখন পারফরম্যান্স প্রোফাইলিং ডেটা—সাধারণত একটি ট্রেস বলা হয়—একটি প্রোফাইল লোড করার পারফ প্যানেলের দ্বিতীয় DevTools উদাহরণে দেখা যায়।

প্রাথমিক অবস্থা: উন্নতির সুযোগ চিহ্নিত করা

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

DevTools-এ পারফরম্যান্স প্যানেলের একটি স্ক্রিনশট যা অন্য DevTools উদাহরণের পারফরম্যান্স প্যানেলে একটি পারফরম্যান্স ট্রেস লোড করা পরিদর্শন করে। প্রোফাইলটি লোড হতে প্রায় 10 সেকেন্ড সময় নেয়। এই সময়টি বেশিরভাগ কার্যকলাপের পাঁচটি প্রধান গ্রুপে বিভক্ত।

প্রথম কার্যকলাপ গ্রুপ: অপ্রয়োজনীয় কাজ

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

দ্বিতীয় কার্যকলাপ গ্রুপ

দ্বিতীয় কার্যকলাপ গ্রুপে, সমাধানটি প্রথমটির মতো সহজ ছিল না। buildProfileCalls প্রায় 0.5 সেকেন্ড সময় নেয়, এবং সেই কাজটি এমন কিছু ছিল না যা এড়ানো যায়।

DevTools-এ পারফরম্যান্স প্যানেলের একটি স্ক্রিনশট যা অন্য পারফরম্যান্স প্যানেলের উদাহরণ পরিদর্শন করছে। buildProfileCalls ফাংশনের সাথে যুক্ত একটি টাস্ক প্রায় 0.5 সেকেন্ড সময় নেয়।

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

পারফরম্যান্স প্যানেলের মেমরি খরচ মূল্যায়ন করে DevTools-এ মেমরি প্রোফাইলারের একটি স্ক্রিনশট। পরিদর্শক পরামর্শ দেন যে buildProfileCalls ফাংশন একটি মেমরি ফাঁসের জন্য দায়ী।

এই সন্দেহের উপর ফলো আপ করার জন্য, আমরা তদন্ত করার জন্য মেমরি প্যানেল (DevTools-এ অন্য একটি প্যানেল, perf প্যানেলের মেমরি ড্রয়ার থেকে আলাদা) ব্যবহার করেছি। মেমরি প্যানেলের মধ্যে, "অ্যালোকেশন স্যাম্পলিং" প্রোফাইলিং টাইপ নির্বাচন করা হয়েছিল, যা সিপিইউ প্রোফাইল লোড করার পারফ প্যানেলের জন্য হিপ স্ন্যাপশট রেকর্ড করে।

মেমরি প্রোফাইলারের প্রাথমিক অবস্থার একটি স্ক্রিনশট। 'অ্যালোকেশন স্যাম্পলিং' বিকল্পটি একটি লাল বাক্স দিয়ে হাইলাইট করা হয়েছে এবং এটি নির্দেশ করে যে এই বিকল্পটি জাভাস্ক্রিপ্ট মেমরি প্রোফাইলিংয়ের জন্য সেরা।

নিম্নলিখিত স্ক্রিনশটটি সংগৃহীত হিপ স্ন্যাপশট দেখায়।

মেমরি প্রোফাইলারের একটি স্ক্রিনশট, একটি মেমরি-নিবিড় সেট-ভিত্তিক অপারেশন নির্বাচন করা হয়েছে৷

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

সেটগুলি অনন্য আইটেমগুলি সঞ্চয় করার জন্য উপযোগী এবং ক্রিয়াকলাপগুলি প্রদান করে যা তাদের সামগ্রীর স্বতন্ত্রতা ব্যবহার করে, যেমন ডেটাসেটগুলি কেটে নেওয়া এবং আরও দক্ষ লুকআপ প্রদান করে৷ যাইহোক, এই বৈশিষ্ট্যগুলি প্রয়োজনীয় ছিল না যেহেতু সংরক্ষিত ডেটা উৎস থেকে অনন্য হওয়ার গ্যারান্টি ছিল। যেমন, সেট প্রথম স্থানে প্রয়োজনীয় ছিল না. মেমরি বরাদ্দ উন্নত করতে, সম্পত্তির ধরন একটি Set থেকে একটি প্লেইন অ্যারেতে পরিবর্তন করা হয়েছিল। এই পরিবর্তনটি প্রয়োগ করার পরে, আরেকটি হিপ স্ন্যাপশট নেওয়া হয়েছিল, এবং মেমরি বরাদ্দ হ্রাস লক্ষ্য করা হয়েছিল। এই পরিবর্তনের সাথে যথেষ্ট গতির উন্নতি না হওয়া সত্ত্বেও, সেকেন্ডারি সুবিধা হল যে অ্যাপ্লিকেশনটি কম ঘন ঘন ক্র্যাশ হয়েছিল।

মেমরি প্রোফাইলারের একটি স্ক্রিনশট। পূর্বে মেমরি-ইনটেনসিভ সেট-ভিত্তিক অপারেশন একটি প্লেইন অ্যারে ব্যবহার করার জন্য পরিবর্তন করা হয়েছিল, যা মেমরি খরচ উল্লেখযোগ্যভাবে হ্রাস করেছে।

থার্ড অ্যাক্টিভিটি গ্রুপ: ওয়েইং ডাটা স্ট্রাকচার ট্রেড-অফ

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

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

/**
 * Adds an event to the flame chart data at a defined vertical level.
 */
function appendEventAtLevel (event, level) {
  // ...

  const index = data.length;
  data.push(event);
  this.indexForEventMap.set(event, index);

  // ...
}

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

আগে:

appendEventAtLevel ফাংশনে অপ্টিমাইজেশন করার আগে পারফরম্যান্স প্যানেলের একটি স্ক্রিনশট। ফাংশন চালানোর জন্য মোট সময় ছিল 1,372.51 মিলিসেকেন্ড।

পরে:

appendEventAtLevel ফাংশনে অপ্টিমাইজেশন করার পর পারফরম্যান্স প্যানেলের একটি স্ক্রিনশট। ফাংশন চালানোর জন্য মোট সময় ছিল 207.2 মিলিসেকেন্ড।

চতুর্থ কার্যকলাপ গ্রুপ: নকল কাজ প্রতিরোধ করতে অ-সমালোচনামূলক কাজ এবং ক্যাশে ডেটা স্থগিত করা

এই উইন্ডোতে জুম ইন করলে দেখা যাবে যে ফাংশন কলের দুটি প্রায় অভিন্ন ব্লক রয়েছে। বলা ফাংশনগুলির নাম দেখে, আপনি অনুমান করতে পারেন যে এই ব্লকগুলিতে এমন কোড রয়েছে যা গাছ তৈরি করছে (উদাহরণস্বরূপ, refreshTree বা buildChildren এর মতো নাম সহ)। আসলে, সম্পর্কিত কোডটি প্যানেলের নীচের ড্রয়ারে ট্রি ভিউ তৈরি করে। মজার বিষয় হল এই গাছের দৃশ্যগুলি লোড করার পরে দেখানো হয় না৷ পরিবর্তে, গাছ দেখানোর জন্য ব্যবহারকারীকে একটি ট্রি ভিউ নির্বাচন করতে হবে (ড্রয়ারে "নিচের-আপ", "কল ট্রি" এবং "ইভেন্ট লগ" ট্যাব)। তদ্ব্যতীত, আপনি স্ক্রিনশট থেকে বলতে পারেন, গাছ তৈরির প্রক্রিয়াটি দুবার সম্পাদিত হয়েছিল।

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

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

  1. একটি অ-সমালোচনামূলক কাজ লোড সময়ের কর্মক্ষমতা বাধাগ্রস্ত ছিল. ব্যবহারকারীদের সবসময় এর আউটপুট প্রয়োজন হয় না। যেমন, টাস্কটি প্রোফাইল লোড করার জন্য গুরুত্বপূর্ণ নয়।
  2. এই কাজগুলির ফলাফল ক্যাশে করা হয়নি। সেজন্য ডাটা পরিবর্তন না হওয়া সত্ত্বেও দুইবার গাছ গণনা করা হয়েছে।

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

পঞ্চম অ্যাক্টিভিটি গ্রুপ: সম্ভব হলে জটিল কল হায়ারার্কি এড়িয়ে চলুন

এই গোষ্ঠীটিকে ঘনিষ্ঠভাবে দেখলে, এটি স্পষ্ট যে একটি নির্দিষ্ট কল চেইন বারবার আহ্বান করা হচ্ছে। একই প্যাটার্ন শিখা চার্টে বিভিন্ন জায়গায় 6 বার উপস্থিত হয়েছিল এবং এই উইন্ডোটির মোট সময়কাল ছিল প্রায় 2.4 সেকেন্ড!

পারফরম্যান্স প্যানেলের একটি স্ক্রিনশট একই ট্রেস মিনিম্যাপ তৈরি করার জন্য ছয়টি পৃথক ফাংশন কল দেখাচ্ছে, যার প্রতিটিতে গভীর কল স্ট্যাক রয়েছে।

সম্পর্কিত কোডটিকে একাধিকবার বলা হচ্ছে সেই অংশ যা "মিনিম্যাপ" (প্যানেলের শীর্ষে টাইমলাইন কার্যকলাপের ওভারভিউ) রেন্ডার করার জন্য ডেটা প্রক্রিয়া করে। এটা কেন একাধিকবার ঘটছিল তা স্পষ্ট ছিল না, তবে এটি অবশ্যই 6 বার ঘটতে হবে না! প্রকৃতপক্ষে, অন্য কোনো প্রোফাইল লোড না হলে কোডের আউটপুট বর্তমান থাকা উচিত। তত্ত্বগতভাবে, কোড শুধুমাত্র একবার চালানো উচিত।

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

পারফরম্যান্স প্যানেলের একটি স্ক্রিনশট যেটি একই ট্রেস মিনিম্যাপ তৈরি করার জন্য ছয়টি পৃথক ফাংশন কল দেখায় যা শুধুমাত্র দুইবার কমে গেছে।

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

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

উপসংহার

এই সমস্ত সংশোধনগুলি প্রয়োগ করার পরে (এবং এখানে এবং সেখানে আরও কয়েকটি ছোট), প্রোফাইল লোডিং টাইমলাইনের পরিবর্তনটি নিম্নরূপ দেখায়:

আগে:

পারফরম্যান্স প্যানেলের একটি স্ক্রিনশট অপ্টিমাইজেশনের আগে ট্রেস লোডিং দেখাচ্ছে৷ প্রক্রিয়াটি প্রায় দশ সেকেন্ড সময় নেয়।

পরে:

পারফরম্যান্স প্যানেলের একটি স্ক্রিনশট অপ্টিমাইজেশনের পরে ট্রেস লোডিং দেখাচ্ছে৷ প্রক্রিয়াটি এখন প্রায় দুই সেকেন্ড সময় নেয়।

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

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

Takeaways

আপনার অ্যাপ্লিকেশনের পারফরম্যান্স অপ্টিমাইজেশনের ক্ষেত্রে এই ফলাফলগুলি থেকে কিছু শিক্ষা নেওয়ার আছে:

1. রানটাইম কর্মক্ষমতা নিদর্শন সনাক্ত করতে প্রোফাইলিং সরঞ্জাম ব্যবহার করুন

আপনার অ্যাপ্লিকেশানটি চলমান অবস্থায় কী ঘটছে তা বোঝার জন্য প্রোফাইলিং সরঞ্জামগুলি অবিশ্বাস্যভাবে উপযোগী, বিশেষ করে কর্মক্ষমতা উন্নত করার সুযোগগুলি সনাক্ত করতে। Chrome DevTools-এর পারফরম্যান্স প্যানেল ওয়েব অ্যাপ্লিকেশনগুলির জন্য একটি দুর্দান্ত বিকল্প কারণ এটি ব্রাউজারে নেটিভ ওয়েব প্রোফাইলিং টুল, এবং এটি সাম্প্রতিক ওয়েব প্ল্যাটফর্ম বৈশিষ্ট্যগুলির সাথে আপ-টু-ডেট থাকার জন্য সক্রিয়ভাবে বজায় রাখা হয়েছে। এছাড়াও, এটি এখন উল্লেখযোগ্যভাবে দ্রুত! 😉

নমুনাগুলি ব্যবহার করুন যা প্রতিনিধি কাজের লোড হিসাবে ব্যবহার করা যেতে পারে এবং দেখুন আপনি কী পেতে পারেন!

2. জটিল কল শ্রেণীবিন্যাস এড়িয়ে চলুন

যখন সম্ভব, আপনার কল গ্রাফকে খুব জটিল করা এড়িয়ে চলুন। জটিল কল হায়ারার্কিগুলির সাথে, কর্মক্ষমতা রিগ্রেশনের সাথে পরিচিত করা সহজ এবং কেন আপনার কোডটি যেভাবে চলছে তা বোঝা কঠিন, এটিকে উন্নতি করা কঠিন করে তোলে।

3. অপ্রয়োজনীয় কাজ চিহ্নিত করুন

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

4. সঠিকভাবে ডেটা স্ট্রাকচার ব্যবহার করুন

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

5. জটিল বা পুনরাবৃত্তিমূলক অপারেশনের জন্য ডুপ্লিকেট কাজ এড়াতে ক্যাশে ফলাফল

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

6. অ-সমালোচনামূলক কাজ স্থগিত করুন

যদি একটি টাস্কের আউটপুট অবিলম্বে প্রয়োজন না হয় এবং টাস্ক এক্সিকিউশনটি জটিল পথকে প্রসারিত করে, তবে এটির আউটপুট আসলে প্রয়োজন হলে অলসভাবে কল করে এটি পিছিয়ে দেওয়ার কথা বিবেচনা করুন।

7. বড় ইনপুটগুলিতে দক্ষ অ্যালগরিদম ব্যবহার করুন

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

8. বোনাস: আপনার পাইপলাইন বেঞ্চমার্ক

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

,

আন্দ্রেস অলিভারেস
Andrés Olivares
ন্যান্সি লি
Nancy Li

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

পারফরম্যান্স প্যানেল ব্যবহার করলেও নিম্নলিখিত উদাহরণটি আপনাকে নিয়ে যায়।

আমাদের প্রোফাইলিং দৃশ্যকল্প সেট আপ এবং পুনরায় তৈরি করা

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

আপনি হয়তো জানেন, DevTools নিজেই একটি ওয়েব অ্যাপ্লিকেশন। যেমন, এটি পারফরম্যান্স প্যানেল ব্যবহার করে প্রোফাইল করা যেতে পারে। এই প্যানেলটি নিজেই প্রোফাইল করতে, আপনি DevTools খুলতে পারেন এবং তারপরে এটির সাথে সংযুক্ত আরেকটি DevTools উদাহরণ খুলতে পারেন। Google-এ, এই সেটআপটি DevTools-on-DevTools নামে পরিচিত।

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

DevTools ইন্সট্যান্সের একটি স্ক্রিনশট যা DevTools-এরই উপাদানগুলি পরিদর্শন করে৷
DevTools-on-DevTools: DevTools দিয়ে DevTools পরিদর্শন করা।

দ্বিতীয় DevTools ইন্সট্যান্সে, পারফরম্যান্স প্যানেল—যাকে এখান থেকে পারফ প্যানেল বলা হবে—প্রথম DevTools ইন্সট্যান্সটি দৃশ্যকল্পটি পুনরায় তৈরি করার জন্য পর্যবেক্ষণ করে, যা একটি প্রোফাইল লোড করে।

দ্বিতীয় DevTools উদাহরণে একটি লাইভ রেকর্ডিং শুরু হয়, যখন প্রথম উদাহরণে, ডিস্কের একটি ফাইল থেকে একটি প্রোফাইল লোড হয়৷ বৃহৎ ইনপুট প্রক্রিয়াকরণের সঠিকভাবে প্রোফাইল কার্যক্ষমতার জন্য একটি বড় ফাইল লোড করা হয়। যখন উভয় দৃষ্টান্ত লোড করা শেষ হয়, তখন পারফরম্যান্স প্রোফাইলিং ডেটা—সাধারণত একটি ট্রেস বলা হয়—একটি প্রোফাইল লোড করার পারফ প্যানেলের দ্বিতীয় DevTools উদাহরণে দেখা যায়।

প্রাথমিক অবস্থা: উন্নতির সুযোগ চিহ্নিত করা

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

DevTools-এ পারফরম্যান্স প্যানেলের একটি স্ক্রিনশট যা অন্য DevTools উদাহরণের পারফরম্যান্স প্যানেলে একটি পারফরম্যান্স ট্রেস লোড করা পরিদর্শন করে। প্রোফাইলটি লোড হতে প্রায় 10 সেকেন্ড সময় নেয়। এই সময়টি বেশিরভাগ কার্যকলাপের পাঁচটি প্রধান গ্রুপে বিভক্ত।

প্রথম কার্যকলাপ গ্রুপ: অপ্রয়োজনীয় কাজ

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

দ্বিতীয় কার্যকলাপ গ্রুপ

দ্বিতীয় কার্যকলাপ গ্রুপে, সমাধানটি প্রথমটির মতো সহজ ছিল না। buildProfileCalls প্রায় 0.5 সেকেন্ড সময় নেয়, এবং সেই কাজটি এমন কিছু ছিল না যা এড়ানো যায়।

DevTools-এ পারফরম্যান্স প্যানেলের একটি স্ক্রিনশট যা অন্য পারফরম্যান্স প্যানেলের উদাহরণ পরিদর্শন করছে। buildProfileCalls ফাংশনের সাথে যুক্ত একটি টাস্ক প্রায় 0.5 সেকেন্ড সময় নেয়।

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

পারফরম্যান্স প্যানেলের মেমরি খরচ মূল্যায়ন করে DevTools-এ মেমরি প্রোফাইলারের একটি স্ক্রিনশট। পরিদর্শক পরামর্শ দেন যে buildProfileCalls ফাংশন একটি মেমরি ফাঁসের জন্য দায়ী।

এই সন্দেহের উপর ফলো আপ করার জন্য, আমরা তদন্ত করার জন্য মেমরি প্যানেল (DevTools-এ অন্য একটি প্যানেল, perf প্যানেলের মেমরি ড্রয়ার থেকে আলাদা) ব্যবহার করেছি। মেমরি প্যানেলের মধ্যে, "অ্যালোকেশন স্যাম্পলিং" প্রোফাইলিং টাইপ নির্বাচন করা হয়েছিল, যা সিপিইউ প্রোফাইল লোড করার পারফ প্যানেলের জন্য হিপ স্ন্যাপশট রেকর্ড করে।

মেমরি প্রোফাইলারের প্রাথমিক অবস্থার একটি স্ক্রিনশট। 'অ্যালোকেশন স্যাম্পলিং' বিকল্পটি একটি লাল বাক্স দিয়ে হাইলাইট করা হয়েছে এবং এটি নির্দেশ করে যে এই বিকল্পটি জাভাস্ক্রিপ্ট মেমরি প্রোফাইলিংয়ের জন্য সেরা।

নিম্নলিখিত স্ক্রিনশটটি সংগৃহীত হিপ স্ন্যাপশট দেখায়।

মেমরি প্রোফাইলারের একটি স্ক্রিনশট, একটি মেমরি-নিবিড় সেট-ভিত্তিক অপারেশন নির্বাচন করা হয়েছে৷

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

সেটগুলি অনন্য আইটেমগুলি সঞ্চয় করার জন্য উপযোগী এবং ক্রিয়াকলাপগুলি প্রদান করে যা তাদের সামগ্রীর স্বতন্ত্রতা ব্যবহার করে, যেমন ডেটাসেটগুলি কেটে নেওয়া এবং আরও দক্ষ লুকআপ প্রদান করে৷ যাইহোক, এই বৈশিষ্ট্যগুলি প্রয়োজনীয় ছিল না যেহেতু সংরক্ষিত ডেটা উৎস থেকে অনন্য হওয়ার গ্যারান্টি ছিল। যেমন, সেট প্রথম স্থানে প্রয়োজনীয় ছিল না. মেমরি বরাদ্দ উন্নত করতে, সম্পত্তির ধরন একটি Set থেকে একটি প্লেইন অ্যারেতে পরিবর্তন করা হয়েছিল। এই পরিবর্তনটি প্রয়োগ করার পরে, আরেকটি হিপ স্ন্যাপশট নেওয়া হয়েছিল, এবং মেমরি বরাদ্দ হ্রাস লক্ষ্য করা হয়েছিল। এই পরিবর্তনের সাথে যথেষ্ট গতির উন্নতি না হওয়া সত্ত্বেও, সেকেন্ডারি সুবিধা হল যে অ্যাপ্লিকেশনটি কম ঘন ঘন ক্র্যাশ হয়েছিল।

মেমরি প্রোফাইলারের একটি স্ক্রিনশট। পূর্বে মেমরি-ইনটেনসিভ সেট-ভিত্তিক অপারেশন একটি প্লেইন অ্যারে ব্যবহার করার জন্য পরিবর্তন করা হয়েছিল, যা মেমরি খরচ উল্লেখযোগ্যভাবে হ্রাস করেছে।

থার্ড অ্যাক্টিভিটি গ্রুপ: ওয়েইং ডাটা স্ট্রাকচার ট্রেড-অফ

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

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

/**
 * Adds an event to the flame chart data at a defined vertical level.
 */
function appendEventAtLevel (event, level) {
  // ...

  const index = data.length;
  data.push(event);
  this.indexForEventMap.set(event, index);

  // ...
}

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

আগে:

appendEventAtLevel ফাংশনে অপ্টিমাইজেশন করার আগে পারফরম্যান্স প্যানেলের একটি স্ক্রিনশট। ফাংশন চালানোর জন্য মোট সময় ছিল 1,372.51 মিলিসেকেন্ড।

পরে:

appendEventAtLevel ফাংশনে অপ্টিমাইজেশন করার পর পারফরম্যান্স প্যানেলের একটি স্ক্রিনশট। ফাংশন চালানোর জন্য মোট সময় ছিল 207.2 মিলিসেকেন্ড।

চতুর্থ কার্যকলাপ গ্রুপ: নকল কাজ প্রতিরোধ করতে অ-সমালোচনামূলক কাজ এবং ক্যাশে ডেটা স্থগিত করা

এই উইন্ডোতে জুম ইন করলে দেখা যাবে যে ফাংশন কলের দুটি প্রায় অভিন্ন ব্লক রয়েছে। বলা ফাংশনগুলির নাম দেখে, আপনি অনুমান করতে পারেন যে এই ব্লকগুলিতে এমন কোড রয়েছে যা গাছ তৈরি করছে (উদাহরণস্বরূপ, refreshTree বা buildChildren এর মতো নাম সহ)। আসলে, সম্পর্কিত কোডটি প্যানেলের নীচের ড্রয়ারে ট্রি ভিউ তৈরি করে। মজার বিষয় হল এই গাছের দৃশ্যগুলি লোড করার পরে দেখানো হয় না৷ পরিবর্তে, গাছ দেখানোর জন্য ব্যবহারকারীকে একটি ট্রি ভিউ নির্বাচন করতে হবে (ড্রয়ারে "নিচের-আপ", "কল ট্রি" এবং "ইভেন্ট লগ" ট্যাব)। তদ্ব্যতীত, আপনি স্ক্রিনশট থেকে বলতে পারেন, গাছ তৈরির প্রক্রিয়াটি দুবার সম্পাদিত হয়েছিল।

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

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

  1. একটি অ-সমালোচনামূলক কাজ লোড সময়ের কর্মক্ষমতা বাধাগ্রস্ত ছিল. ব্যবহারকারীদের সবসময় এর আউটপুট প্রয়োজন হয় না। যেমন, টাস্কটি প্রোফাইল লোড করার জন্য গুরুত্বপূর্ণ নয়।
  2. এই কাজগুলির ফলাফল ক্যাশে করা হয়নি। সেজন্য ডাটা পরিবর্তন না হওয়া সত্ত্বেও দুইবার গাছ গণনা করা হয়েছে।

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

পঞ্চম অ্যাক্টিভিটি গ্রুপ: সম্ভব হলে জটিল কল হায়ারার্কি এড়িয়ে চলুন

এই গোষ্ঠীটিকে ঘনিষ্ঠভাবে দেখলে, এটি স্পষ্ট যে একটি নির্দিষ্ট কল চেইন বারবার আহ্বান করা হচ্ছে। একই প্যাটার্ন শিখা চার্টে বিভিন্ন জায়গায় 6 বার উপস্থিত হয়েছিল এবং এই উইন্ডোটির মোট সময়কাল ছিল প্রায় 2.4 সেকেন্ড!

পারফরম্যান্স প্যানেলের একটি স্ক্রিনশট একই ট্রেস মিনিম্যাপ তৈরি করার জন্য ছয়টি পৃথক ফাংশন কল দেখাচ্ছে, যার প্রতিটিতে গভীর কল স্ট্যাক রয়েছে।

সম্পর্কিত কোডটিকে একাধিকবার বলা হচ্ছে সেই অংশ যা "মিনিম্যাপ" (প্যানেলের শীর্ষে টাইমলাইন কার্যকলাপের ওভারভিউ) রেন্ডার করার জন্য ডেটা প্রক্রিয়া করে। এটা কেন একাধিকবার ঘটছিল তা স্পষ্ট ছিল না, তবে এটি অবশ্যই 6 বার ঘটতে হবে না! প্রকৃতপক্ষে, অন্য কোনো প্রোফাইল লোড না হলে কোডের আউটপুট বর্তমান থাকা উচিত। তত্ত্বগতভাবে, কোড শুধুমাত্র একবার চালানো উচিত।

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

পারফরম্যান্স প্যানেলের একটি স্ক্রিনশট যেটি একই ট্রেস মিনিম্যাপ তৈরি করার জন্য ছয়টি পৃথক ফাংশন কল দেখায় যা শুধুমাত্র দুইবার কমে গেছে।

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

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

উপসংহার

এই সমস্ত সংশোধনগুলি প্রয়োগ করার পরে (এবং এখানে এবং সেখানে আরও কয়েকটি ছোট), প্রোফাইল লোডিং টাইমলাইনের পরিবর্তনটি নিম্নরূপ দেখায়:

আগে:

পারফরম্যান্স প্যানেলের একটি স্ক্রিনশট অপ্টিমাইজেশনের আগে ট্রেস লোডিং দেখাচ্ছে৷ প্রক্রিয়াটি প্রায় দশ সেকেন্ড সময় নেয়।

পরে:

পারফরম্যান্স প্যানেলের একটি স্ক্রিনশট অপ্টিমাইজেশনের পরে ট্রেস লোডিং দেখাচ্ছে৷ প্রক্রিয়াটি এখন প্রায় দুই সেকেন্ড সময় নেয়।

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

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

Takeaways

আপনার অ্যাপ্লিকেশনের পারফরম্যান্স অপ্টিমাইজেশনের ক্ষেত্রে এই ফলাফলগুলি থেকে কিছু শিক্ষা নেওয়ার আছে:

1. রানটাইম কর্মক্ষমতা নিদর্শন সনাক্ত করতে প্রোফাইলিং সরঞ্জাম ব্যবহার করুন

আপনার অ্যাপ্লিকেশানটি চলমান অবস্থায় কী ঘটছে তা বোঝার জন্য প্রোফাইলিং সরঞ্জামগুলি অবিশ্বাস্যভাবে উপযোগী, বিশেষ করে কর্মক্ষমতা উন্নত করার সুযোগগুলি সনাক্ত করতে। ক্রোম ডিভটুলসের পারফরম্যান্স প্যানেলটি ওয়েব অ্যাপ্লিকেশনগুলির জন্য দুর্দান্ত বিকল্প হিসাবে এটি ব্রাউজারের নেটিভ ওয়েব প্রোফাইলিং সরঞ্জাম, এবং এটি সর্বশেষতম ওয়েব প্ল্যাটফর্ম বৈশিষ্ট্যগুলির সাথে আপ-টু-ডেট হিসাবে সক্রিয়ভাবে বজায় রাখা হয়েছে। এছাড়াও, এটি এখন উল্লেখযোগ্যভাবে দ্রুত! 😉

প্রতিনিধি কাজের চাপ হিসাবে ব্যবহার করা যেতে পারে এমন নমুনাগুলি ব্যবহার করুন এবং আপনি কী খুঁজে পেতে পারেন তা দেখুন!

2। জটিল কল শ্রেণিবিন্যাস এড়িয়ে চলুন

যখন সম্ভব হয়, আপনার কল গ্রাফটি খুব জটিল করে তুলুন। জটিল কল হায়ারার্কিজ সহ, পারফরম্যান্স রিগ্রেশনগুলি প্রবর্তন করা সহজ এবং আপনার কোডটি কেন এটি চলছে তা বোঝা শক্ত করে, এটি অবতরণ করা কঠিন করে তোলে।

3। অপ্রয়োজনীয় কাজ চিহ্নিত করুন

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

4. সঠিকভাবে ডেটা স্ট্রাকচার ব্যবহার করুন

পারফরম্যান্সটি অনুকূল করতে ডেটা স্ট্রাকচার ব্যবহার করুন, তবে কোনটি ব্যবহার করবেন তা সিদ্ধান্ত নেওয়ার সময় প্রতিটি ধরণের ডেটা স্ট্রাকচার নিয়ে আসা ব্যয় এবং ট্রেড-অফগুলিও বুঝতে পারে। এটি কেবল ডেটা কাঠামোর স্পেস জটিলতা নয়, প্রযোজ্য ক্রিয়াকলাপগুলির সময় জটিলতাও।

5। জটিল বা পুনরাবৃত্ত ক্রিয়াকলাপের জন্য সদৃশ কাজ এড়াতে ক্যাশে ফলাফল

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

6 .. অ-সমালোচনামূলক কাজ স্থগিত করুন

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

7 .. বড় ইনপুটগুলিতে দক্ষ অ্যালগরিদম ব্যবহার করুন

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

8 .. বোনাস: আপনার পাইপলাইনগুলি বেঞ্চমার্ক করুন

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

,

আন্ড্রেস অলিভারেস
Andrés Olivares
ন্যান্সি লি
Nancy Li

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

পারফরম্যান্স প্যানেলটি ব্যবহার করে নিম্নলিখিত উদাহরণটি আপনাকে হাঁটছে।

আমাদের প্রোফাইলিং দৃশ্যটি সেট আপ এবং পুনরুদ্ধার করা

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

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

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

ডিভটুলস নিজেই উপাদানগুলি পরিদর্শন করে একটি ডিভটুলের উদাহরণগুলির একটি স্ক্রিনশট।
ডেভটুলস-অন-ডেভটুলস: ডেভটুলগুলি সহ ডিভটুলগুলি পরিদর্শন করা।

দ্বিতীয় ডিভটুলস উদাহরণে, পারফরম্যান্স প্যানেল - যাকে এখান থেকে সুগন্ধি প্যানেল বলা হবে - দৃশ্যটি পুনরায় তৈরি করার জন্য প্রথম ডিভটুলস উদাহরণটি পর্যবেক্ষণ করে, যা একটি প্রোফাইল লোড করে।

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

প্রাথমিক অবস্থা: উন্নতির জন্য সুযোগগুলি সনাক্তকরণ

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

ডিভটুলসের পারফরম্যান্স প্যানেলের একটি স্ক্রিনশট অন্য একটি ডিভটুলস উদাহরণের পারফরম্যান্স প্যানেলে পারফরম্যান্স ট্রেসের লোডিং পরিদর্শন করে। প্রোফাইলটি লোড হতে প্রায় 10 সেকেন্ড সময় নেয়। এই সময়টি বেশিরভাগ ক্রিয়াকলাপের পাঁচটি প্রধান গোষ্ঠীতে বিভক্ত।

প্রথম ক্রিয়াকলাপ গ্রুপ: অপ্রয়োজনীয় কাজ

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

দ্বিতীয় ক্রিয়াকলাপ গ্রুপ

দ্বিতীয় ক্রিয়াকলাপ গোষ্ঠীতে, সমাধানটি প্রথমটির মতো সহজ ছিল না। buildProfileCalls প্রায় 0.5 সেকেন্ড সময় নিয়েছিল এবং সেই কাজটি এমন কিছু ছিল না যা এড়ানো যায়।

ডিভটুলসের পারফরম্যান্স প্যানেলের একটি স্ক্রিনশট অন্য পারফরম্যান্স প্যানেল উদাহরণ পরিদর্শন করে। বিল্ডপ্রোফিলক্যালস ফাংশনের সাথে যুক্ত একটি কাজ প্রায় 0.5 সেকেন্ড সময় নেয়।

কৌতূহলের বাইরে, আমরা সুগন্ধি প্যানেলে মেমরি বিকল্পটি আরও তদন্ত করতে সক্ষম করেছি এবং দেখেছি যে buildProfileCalls ক্রিয়াকলাপটিও প্রচুর স্মৃতি ব্যবহার করছে। এখানে, আপনি দেখতে পাচ্ছেন যে ব্লু লাইন গ্রাফটি কীভাবে হঠাৎ সময় buildProfileCalls চালানো হয় তার চারপাশে লাফিয়ে যায়, যা একটি সম্ভাব্য মেমরি ফুটো প্রস্তাব দেয়।

পারফরম্যান্স প্যানেলের মেমরি খরচ মূল্যায়ন করে ডিভটুলগুলিতে মেমরি প্রোফাইলারের একটি স্ক্রিনশট। পরিদর্শক পরামর্শ দেন যে বিল্ডপ্রোফিলক্যালস ফাংশনটি মেমরি ফাঁসের জন্য দায়ী।

এই সন্দেহটি অনুসরণ করার জন্য, আমরা তদন্তের জন্য মেমরি প্যানেল (ডিভটুলের অন্য প্যানেল, পারফেস প্যানেলের মেমরি ড্রয়ারের চেয়ে আলাদা) ব্যবহার করেছি। মেমরি প্যানেলের মধ্যে, "বরাদ্দ স্যাম্পলিং" প্রোফাইলিং প্রকারটি নির্বাচন করা হয়েছিল, যা সিপিইউ প্রোফাইলটি লোড করে পারফেস প্যানেলের জন্য হিপ স্ন্যাপশটটি রেকর্ড করেছিল।

মেমরি প্রোফাইলারের প্রাথমিক অবস্থার একটি স্ক্রিনশট। 'বরাদ্দ স্যাম্পলিং' বিকল্পটি একটি লাল বাক্সের সাথে হাইলাইট করা হয়েছে এবং এটি নির্দেশ করে যে এই বিকল্পটি জাভাস্ক্রিপ্ট মেমরি প্রোফাইলিংয়ের জন্য সেরা।

নিম্নলিখিত স্ক্রিনশটটি সংগ্রহ করা হিপ স্ন্যাপশটটি দেখায়।

মেমরি প্রোফাইলারের একটি স্ক্রিনশট, একটি মেমরি-নিবিড় সেট-ভিত্তিক অপারেশন নির্বাচিত।

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

সেটগুলি অনন্য আইটেমগুলি সংরক্ষণ করার জন্য দরকারী এবং এমন ক্রিয়াকলাপ সরবরাহ করে যা তাদের সামগ্রীর স্বতন্ত্রতা ব্যবহার করে, যেমন ডেটাসেটগুলি ডেডুপ্লিকেট করা এবং আরও দক্ষ অনুসন্ধান সরবরাহ করে। যাইহোক, সঞ্চিত ডেটা উত্স থেকে অনন্য হওয়ার গ্যারান্টিযুক্ত হওয়ায় এই বৈশিষ্ট্যগুলি প্রয়োজনীয় ছিল না। যেমন, সেটগুলি প্রথম স্থানে প্রয়োজনীয় ছিল না। মেমরি বরাদ্দ উন্নত করতে, সম্পত্তির ধরণটি একটি Set থেকে একটি সরল অ্যারেতে পরিবর্তন করা হয়েছিল। এই পরিবর্তনটি প্রয়োগ করার পরে, আরেকটি হিপ স্ন্যাপশট নেওয়া হয়েছিল এবং মেমরি বরাদ্দ হ্রাস লক্ষ্য করা গেছে। এই পরিবর্তনের সাথে যথেষ্ট গতির উন্নতি অর্জন না করা সত্ত্বেও, গৌণ সুবিধাটি হ'ল অ্যাপ্লিকেশনটি কম ঘন ঘন বিধ্বস্ত হয়েছিল।

মেমরি প্রোফাইলারের একটি স্ক্রিনশট। পূর্বে মেমরি-নিবিড় সেট-ভিত্তিক অপারেশনটি একটি সরল অ্যারে ব্যবহার করার জন্য পরিবর্তন করা হয়েছিল, যা মেমরির ব্যয়কে উল্লেখযোগ্যভাবে হ্রাস করেছে।

তৃতীয় ক্রিয়াকলাপ গোষ্ঠী: ওজনযুক্ত ডেটা স্ট্রাকচার ট্রেড অফগুলি

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

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

/**
 * Adds an event to the flame chart data at a defined vertical level.
 */
function appendEventAtLevel (event, level) {
  // ...

  const index = data.length;
  data.push(event);
  this.indexForEventMap.set(event, index);

  // ...
}

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

আগে:

অ্যাপেনডেভেন্ট্যাটলভেল ফাংশনে অপ্টিমাইজেশন করার আগে পারফরম্যান্স প্যানেলের একটি স্ক্রিনশট। ফাংশনটি চালানোর মোট সময়টি ছিল 1,372.51 মিলিসেকেন্ড।

পরে:

অপ্টিমাইজেশনের পরে পারফরম্যান্স প্যানেলের একটি স্ক্রিনশট অ্যাপেনডেভেন্ট্যাটলভেল ফাংশনে তৈরি করা হয়েছিল। ফাংশনটি চালানোর মোট সময়টি ছিল 207.2 মিলিসেকেন্ড।

চতুর্থ ক্রিয়াকলাপ গোষ্ঠী: সদৃশ কাজ রোধ করতে অ-সমালোচনামূলক কাজ এবং ক্যাশে ডেটা স্থগিত করা

এই উইন্ডোতে জুম করা, এটি দেখা যায় যে ফাংশন কলগুলির প্রায় দুটি অভিন্ন ব্লক রয়েছে। নামক ফাংশনগুলির নামটি দেখে আপনি অনুমান করতে পারেন যে এই ব্লকগুলিতে এমন কোড রয়েছে যা গাছ তৈরি করছে (উদাহরণস্বরূপ, refreshTree বা buildChildren মতো নাম সহ)। প্রকৃতপক্ষে, সম্পর্কিত কোডটি হ'ল প্যানেলের নীচের ড্রয়ারে গাছের দৃশ্য তৈরি করে। মজার বিষয় হ'ল এই গাছের দৃশ্যগুলি লোড করার পরে ঠিক দেখানো হয়নি। পরিবর্তে, গাছগুলি দেখানোর জন্য ব্যবহারকারীর একটি গাছের দৃশ্য ("নীচে-আপ", "কল ট্রি" এবং ড্রয়ারে "ইভেন্ট লগ" ট্যাবগুলি) নির্বাচন করতে হবে। তদ্ব্যতীত, আপনি যেমন স্ক্রিনশট থেকে বলতে পারেন, গাছ বিল্ডিং প্রক্রিয়াটি দু'বার কার্যকর করা হয়েছিল।

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

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

  1. একটি অ-সমালোচনামূলক কাজ লোড সময়ের পারফরম্যান্সকে বাধা দিচ্ছিল। ব্যবহারকারীদের সর্বদা এর আউটপুট প্রয়োজন হয় না। যেমনটি, টাস্কটি প্রোফাইল লোডিংয়ের জন্য গুরুত্বপূর্ণ নয়।
  2. এই কাজের ফলাফল ক্যাশে করা হয়নি। এজন্য ডেটা পরিবর্তন না হওয়া সত্ত্বেও গাছগুলি দু'বার গণনা করা হয়েছিল।

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

পঞ্চম ক্রিয়াকলাপ গোষ্ঠী: সম্ভব হলে জটিল কল শ্রেণিবদ্ধতা এড়িয়ে চলুন

এই গোষ্ঠীর দিকে ঘনিষ্ঠভাবে তাকিয়ে, এটি স্পষ্ট ছিল যে একটি নির্দিষ্ট কল চেইন বারবার আহ্বান করা হচ্ছে। একই প্যাটার্নটি শিখা চার্টে বিভিন্ন জায়গায় 6 বার উপস্থিত হয়েছিল এবং এই উইন্ডোটির মোট সময়কাল প্রায় 2.4 সেকেন্ড ছিল!

পারফরম্যান্স প্যানেলের একটি স্ক্রিনশট একই ট্রেস মিনিম্যাপ উত্পন্ন করার জন্য ছয়টি পৃথক ফাংশন কল দেখায়, যার প্রত্যেকটিরই গভীর কল স্ট্যাক রয়েছে।

একাধিকবার বলা হচ্ছে সম্পর্কিত কোডটি এমন একটি অংশ যা "মিনিম্যাপ" (প্যানেলের শীর্ষে টাইমলাইন ক্রিয়াকলাপের ওভারভিউ) তে ডেটা সরবরাহ করার জন্য ডেটা প্রক্রিয়া করে। এটি কেন একাধিকবার ঘটছে তা পরিষ্কার ছিল না, তবে এটি অবশ্যই 6 বার ঘটতে হবে না! প্রকৃতপক্ষে, অন্য কোনও প্রোফাইল লোড না করা হলে কোডের আউটপুট বর্তমান থাকা উচিত। তত্ত্ব অনুসারে, কোডটি কেবল একবার চালানো উচিত।

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

একই ট্রেস মিনিম্যাপ উত্পন্ন করার জন্য ছয়টি পৃথক ফাংশন কল করে পারফরম্যান্স প্যানেলের একটি স্ক্রিনশট কেবল দু'বার কমে যায়।

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

যেহেতু এই মিনিম্যাপগুলি উভয় চিত্রই একটি ক্যানভাসে আঁকা, তাই এটি drawImage ক্যানভাস ইউটিলিটি ব্যবহার করার বিষয় ছিল এবং পরবর্তীকালে কিছু অতিরিক্ত সময় সাশ্রয় করার জন্য কোডটি কেবল একবার চালানো ছিল। এই প্রচেষ্টার ফলস্বরূপ, গোষ্ঠীর সময়কাল ২.৪ সেকেন্ড থেকে কমিয়ে ১৪০ মিলিসেকেন্ডে কমিয়ে আনা হয়েছিল।

উপসংহার

এই সমস্ত সংশোধনগুলি প্রয়োগ করার পরে (এবং এখানে এবং সেখানে আরও কয়েকটি ছোট ছোট ছোট) প্রয়োগ করার পরে, প্রোফাইল লোডিং টাইমলাইনের পরিবর্তনটি নিম্নরূপ দেখায়:

আগে:

অপ্টিমাইজেশনের আগে ট্রেস লোডিং দেখায় পারফরম্যান্স প্যানেলের একটি স্ক্রিনশট। প্রক্রিয়াটি প্রায় দশ সেকেন্ড সময় নিয়েছিল।

পরে:

অপ্টিমাইজেশনের পরে ট্রেস লোডিং দেখায় পারফরম্যান্স প্যানেলের একটি স্ক্রিনশট। প্রক্রিয়াটি এখন প্রায় দুই সেকেন্ড সময় নেয়।

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

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

Takeaways

আপনার অ্যাপ্লিকেশনটির পারফরম্যান্স অপ্টিমাইজেশনের ক্ষেত্রে এই ফলাফলগুলি থেকে দূরে সরিয়ে নেওয়ার কিছু পাঠ রয়েছে:

1। রানটাইম পারফরম্যান্স নিদর্শনগুলি সনাক্ত করতে প্রোফাইলিং সরঞ্জামগুলি ব্যবহার করুন

আপনার অ্যাপ্লিকেশন চলাকালীন কী ঘটছে তা বোঝার জন্য প্রোফাইলিং সরঞ্জামগুলি অবিশ্বাস্যভাবে কার্যকর, বিশেষত পারফরম্যান্স উন্নত করার সুযোগগুলি সনাক্ত করতে। ক্রোম ডিভটুলসের পারফরম্যান্স প্যানেলটি ওয়েব অ্যাপ্লিকেশনগুলির জন্য দুর্দান্ত বিকল্প হিসাবে এটি ব্রাউজারের নেটিভ ওয়েব প্রোফাইলিং সরঞ্জাম, এবং এটি সর্বশেষতম ওয়েব প্ল্যাটফর্ম বৈশিষ্ট্যগুলির সাথে আপ-টু-ডেট হিসাবে সক্রিয়ভাবে বজায় রাখা হয়েছে। এছাড়াও, এটি এখন উল্লেখযোগ্যভাবে দ্রুত! 😉

প্রতিনিধি কাজের চাপ হিসাবে ব্যবহার করা যেতে পারে এমন নমুনাগুলি ব্যবহার করুন এবং আপনি কী খুঁজে পেতে পারেন তা দেখুন!

2। জটিল কল শ্রেণিবিন্যাস এড়িয়ে চলুন

যখন সম্ভব হয়, আপনার কল গ্রাফটি খুব জটিল করে তুলুন। জটিল কল হায়ারার্কিজ সহ, পারফরম্যান্স রিগ্রেশনগুলি প্রবর্তন করা সহজ এবং আপনার কোডটি কেন এটি চলছে তা বোঝা শক্ত করে, এটি অবতরণ করা কঠিন করে তোলে।

3। অপ্রয়োজনীয় কাজ চিহ্নিত করুন

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

4. সঠিকভাবে ডেটা স্ট্রাকচার ব্যবহার করুন

পারফরম্যান্সটি অনুকূল করতে ডেটা স্ট্রাকচার ব্যবহার করুন, তবে কোনটি ব্যবহার করবেন তা সিদ্ধান্ত নেওয়ার সময় প্রতিটি ধরণের ডেটা স্ট্রাকচার নিয়ে আসা ব্যয় এবং ট্রেড-অফগুলিও বুঝতে পারে। এটি কেবল ডেটা কাঠামোর স্পেস জটিলতা নয়, প্রযোজ্য ক্রিয়াকলাপগুলির সময় জটিলতাও।

5। জটিল বা পুনরাবৃত্ত ক্রিয়াকলাপের জন্য সদৃশ কাজ এড়াতে ক্যাশে ফলাফল

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

6 .. অ-সমালোচনামূলক কাজ স্থগিত করুন

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

7 .. বড় ইনপুটগুলিতে দক্ষ অ্যালগরিদম ব্যবহার করুন

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

8 .. বোনাস: আপনার পাইপলাইনগুলি বেঞ্চমার্ক করুন

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

,

আন্ড্রেস অলিভারেস
Andrés Olivares
ন্যান্সি লি
Nancy Li

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

পারফরম্যান্স প্যানেলটি ব্যবহার করে নিম্নলিখিত উদাহরণটি আপনাকে হাঁটছে।

আমাদের প্রোফাইলিং দৃশ্যটি সেট আপ এবং পুনরুদ্ধার করা

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

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

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

ডিভটুলস নিজেই উপাদানগুলি পরিদর্শন করে একটি ডিভটুলের উদাহরণগুলির একটি স্ক্রিনশট।
ডেভটুলস-অন-ডেভটুলস: ডেভটুলগুলি সহ ডিভটুলগুলি পরিদর্শন করা।

দ্বিতীয় ডিভটুলস উদাহরণে, পারফরম্যান্স প্যানেল - যাকে এখান থেকে সুগন্ধি প্যানেল বলা হবে - দৃশ্যটি পুনরায় তৈরি করার জন্য প্রথম ডিভটুলস উদাহরণটি পর্যবেক্ষণ করে, যা একটি প্রোফাইল লোড করে।

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

প্রাথমিক অবস্থা: উন্নতির জন্য সুযোগগুলি সনাক্তকরণ

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

ডিভটুলসের পারফরম্যান্স প্যানেলের একটি স্ক্রিনশট অন্য একটি ডিভটুলস উদাহরণের পারফরম্যান্স প্যানেলে পারফরম্যান্স ট্রেসের লোডিং পরিদর্শন করে। প্রোফাইলটি লোড হতে প্রায় 10 সেকেন্ড সময় নেয়। এই সময়টি বেশিরভাগ ক্রিয়াকলাপের পাঁচটি প্রধান গোষ্ঠীতে বিভক্ত।

প্রথম ক্রিয়াকলাপ গ্রুপ: অপ্রয়োজনীয় কাজ

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

দ্বিতীয় ক্রিয়াকলাপ গ্রুপ

দ্বিতীয় ক্রিয়াকলাপ গোষ্ঠীতে, সমাধানটি প্রথমটির মতো সহজ ছিল না। buildProfileCalls প্রায় 0.5 সেকেন্ড সময় নিয়েছিল এবং সেই কাজটি এমন কিছু ছিল না যা এড়ানো যায়।

ডিভটুলসের পারফরম্যান্স প্যানেলের একটি স্ক্রিনশট অন্য পারফরম্যান্স প্যানেল উদাহরণ পরিদর্শন করে। বিল্ডপ্রোফিলক্যালস ফাংশনের সাথে যুক্ত একটি কাজ প্রায় 0.5 সেকেন্ড সময় নেয়।

কৌতূহলের বাইরে, আমরা সুগন্ধি প্যানেলে মেমরি বিকল্পটি আরও তদন্ত করতে সক্ষম করেছি এবং দেখেছি যে buildProfileCalls ক্রিয়াকলাপটিও প্রচুর স্মৃতি ব্যবহার করছে। এখানে, আপনি দেখতে পাচ্ছেন যে ব্লু লাইন গ্রাফটি কীভাবে হঠাৎ সময় buildProfileCalls চালানো হয় তার চারপাশে লাফিয়ে যায়, যা একটি সম্ভাব্য মেমরি ফুটো প্রস্তাব দেয়।

পারফরম্যান্স প্যানেলের মেমরি খরচ মূল্যায়ন করে ডিভটুলগুলিতে মেমরি প্রোফাইলারের একটি স্ক্রিনশট। পরিদর্শক পরামর্শ দেন যে বিল্ডপ্রোফিলক্যালস ফাংশনটি মেমরি ফাঁসের জন্য দায়ী।

এই সন্দেহটি অনুসরণ করার জন্য, আমরা তদন্তের জন্য মেমরি প্যানেল (ডিভটুলের অন্য প্যানেল, পারফেস প্যানেলের মেমরি ড্রয়ারের চেয়ে আলাদা) ব্যবহার করেছি। মেমরি প্যানেলের মধ্যে, "বরাদ্দ স্যাম্পলিং" প্রোফাইলিং প্রকারটি নির্বাচন করা হয়েছিল, যা সিপিইউ প্রোফাইলটি লোড করে পারফেস প্যানেলের জন্য হিপ স্ন্যাপশটটি রেকর্ড করেছিল।

মেমরি প্রোফাইলারের প্রাথমিক অবস্থার একটি স্ক্রিনশট। 'বরাদ্দ স্যাম্পলিং' বিকল্পটি একটি লাল বাক্সের সাথে হাইলাইট করা হয়েছে এবং এটি নির্দেশ করে যে এই বিকল্পটি জাভাস্ক্রিপ্ট মেমরি প্রোফাইলিংয়ের জন্য সেরা।

নিম্নলিখিত স্ক্রিনশটটি সংগ্রহ করা হিপ স্ন্যাপশটটি দেখায়।

মেমরি প্রোফাইলারের একটি স্ক্রিনশট, একটি মেমরি-নিবিড় সেট-ভিত্তিক অপারেশন নির্বাচিত।

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

সেটগুলি অনন্য আইটেমগুলি সংরক্ষণ করার জন্য দরকারী এবং এমন ক্রিয়াকলাপ সরবরাহ করে যা তাদের সামগ্রীর স্বতন্ত্রতা ব্যবহার করে, যেমন ডেটাসেটগুলি ডেডুপ্লিকেট করা এবং আরও দক্ষ অনুসন্ধান সরবরাহ করে। যাইহোক, সঞ্চিত ডেটা উত্স থেকে অনন্য হওয়ার গ্যারান্টিযুক্ত হওয়ায় এই বৈশিষ্ট্যগুলি প্রয়োজনীয় ছিল না। যেমন, সেটগুলি প্রথম স্থানে প্রয়োজনীয় ছিল না। মেমরি বরাদ্দ উন্নত করতে, সম্পত্তির ধরণটি একটি Set থেকে একটি সরল অ্যারেতে পরিবর্তন করা হয়েছিল। এই পরিবর্তনটি প্রয়োগ করার পরে, আরেকটি হিপ স্ন্যাপশট নেওয়া হয়েছিল এবং মেমরি বরাদ্দ হ্রাস লক্ষ্য করা গেছে। এই পরিবর্তনের সাথে যথেষ্ট গতির উন্নতি অর্জন না করা সত্ত্বেও, গৌণ সুবিধাটি হ'ল অ্যাপ্লিকেশনটি কম ঘন ঘন বিধ্বস্ত হয়েছিল।

মেমরি প্রোফাইলারের একটি স্ক্রিনশট। পূর্বে মেমরি-নিবিড় সেট-ভিত্তিক অপারেশনটি একটি সরল অ্যারে ব্যবহার করার জন্য পরিবর্তন করা হয়েছিল, যা মেমরির ব্যয়কে উল্লেখযোগ্যভাবে হ্রাস করেছে।

তৃতীয় ক্রিয়াকলাপ গোষ্ঠী: ওজনযুক্ত ডেটা স্ট্রাকচার ট্রেড অফগুলি

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

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

/**
 * Adds an event to the flame chart data at a defined vertical level.
 */
function appendEventAtLevel (event, level) {
  // ...

  const index = data.length;
  data.push(event);
  this.indexForEventMap.set(event, index);

  // ...
}

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

আগে:

অ্যাপেনডেভেন্ট্যাটলভেল ফাংশনে অপ্টিমাইজেশন করার আগে পারফরম্যান্স প্যানেলের একটি স্ক্রিনশট। ফাংশনটি চালানোর মোট সময়টি ছিল 1,372.51 মিলিসেকেন্ড।

পরে:

অপ্টিমাইজেশনের পরে পারফরম্যান্স প্যানেলের একটি স্ক্রিনশট অ্যাপেনডেভেন্ট্যাটলভেল ফাংশনে তৈরি করা হয়েছিল। ফাংশনটি চালানোর মোট সময়টি ছিল 207.2 মিলিসেকেন্ড।

চতুর্থ ক্রিয়াকলাপ গোষ্ঠী: সদৃশ কাজ রোধ করতে অ-সমালোচনামূলক কাজ এবং ক্যাশে ডেটা স্থগিত করা

এই উইন্ডোতে জুম করা, এটি দেখা যায় যে ফাংশন কলগুলির প্রায় দুটি অভিন্ন ব্লক রয়েছে। নামক ফাংশনগুলির নামটি দেখে আপনি অনুমান করতে পারেন যে এই ব্লকগুলিতে এমন কোড রয়েছে যা গাছ তৈরি করছে (উদাহরণস্বরূপ, refreshTree বা buildChildren মতো নাম সহ)। প্রকৃতপক্ষে, সম্পর্কিত কোডটি হ'ল প্যানেলের নীচের ড্রয়ারে গাছের দৃশ্য তৈরি করে। মজার বিষয় হ'ল এই গাছের দৃশ্যগুলি লোড করার পরে ঠিক দেখানো হয়নি। পরিবর্তে, গাছগুলি দেখানোর জন্য ব্যবহারকারীর একটি গাছের দৃশ্য ("নীচে-আপ", "কল ট্রি" এবং ড্রয়ারে "ইভেন্ট লগ" ট্যাবগুলি) নির্বাচন করতে হবে। তদ্ব্যতীত, আপনি যেমন স্ক্রিনশট থেকে বলতে পারেন, গাছ বিল্ডিং প্রক্রিয়াটি দু'বার কার্যকর করা হয়েছিল।

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

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

  1. একটি অ-সমালোচনামূলক কাজ লোড সময়ের পারফরম্যান্সকে বাধা দিচ্ছিল। ব্যবহারকারীদের সর্বদা এর আউটপুট প্রয়োজন হয় না। যেমনটি, টাস্কটি প্রোফাইল লোডিংয়ের জন্য গুরুত্বপূর্ণ নয়।
  2. এই কাজের ফলাফল ক্যাশে করা হয়নি। এজন্য ডেটা পরিবর্তন না হওয়া সত্ত্বেও গাছগুলি দু'বার গণনা করা হয়েছিল।

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

পঞ্চম ক্রিয়াকলাপ গোষ্ঠী: সম্ভব হলে জটিল কল শ্রেণিবদ্ধতা এড়িয়ে চলুন

এই গোষ্ঠীর দিকে ঘনিষ্ঠভাবে তাকিয়ে, এটি স্পষ্ট ছিল যে একটি নির্দিষ্ট কল চেইন বারবার আহ্বান করা হচ্ছে। একই প্যাটার্নটি শিখা চার্টে বিভিন্ন জায়গায় 6 বার উপস্থিত হয়েছিল এবং এই উইন্ডোটির মোট সময়কাল প্রায় 2.4 সেকেন্ড ছিল!

পারফরম্যান্স প্যানেলের একটি স্ক্রিনশট একই ট্রেস মিনিম্যাপ উত্পন্ন করার জন্য ছয়টি পৃথক ফাংশন কল দেখায়, যার প্রত্যেকটিরই গভীর কল স্ট্যাক রয়েছে।

একাধিকবার বলা হচ্ছে সম্পর্কিত কোডটি এমন একটি অংশ যা "মিনিম্যাপ" (প্যানেলের শীর্ষে টাইমলাইন ক্রিয়াকলাপের ওভারভিউ) তে ডেটা সরবরাহ করার জন্য ডেটা প্রক্রিয়া করে। এটি কেন একাধিকবার ঘটছে তা পরিষ্কার ছিল না, তবে এটি অবশ্যই 6 বার ঘটতে হবে না! প্রকৃতপক্ষে, অন্য কোনও প্রোফাইল লোড না করা হলে কোডের আউটপুট বর্তমান থাকা উচিত। তত্ত্ব অনুসারে, কোডটি কেবল একবার চালানো উচিত।

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

একই ট্রেস মিনিম্যাপ উত্পন্ন করার জন্য ছয়টি পৃথক ফাংশন কল করে পারফরম্যান্স প্যানেলের একটি স্ক্রিনশট কেবল দু'বার কমে যায়।

নোট করুন যে মিনিম্যাপ রেন্ডারিং এক্সিকিউশনটি একবার নয়, দু'বার ঘটে। This is because there are two minimaps being drawn for every profile: one for the overview on top of the panel, and another for the drop-down menu that selects the currently visible profile from the history (every item in this menu contains an overview of the profile it selects). Nonetheless, these two have the exact same content, so one should be able to reused for the other.

Since these minimaps are both images drawn on a canvas, it was a matter of using the drawImage canvas utility , and subsequently running the code only once to save some extra time. As a result of this effort, the group's duration was reduced from 2.4 seconds to 140 milliseconds.

উপসংহার

After having applied all these fixes (and a couple of other smaller ones here and there), the change of the profile loading timeline looked as follows:

আগে:

A screenshot of the performance panel showing trace loading before optimizations. The process took approximately ten seconds.

পরে:

A screenshot of the performance panel showing trace loading after optimizations. The process now takes approximately two seconds.

The load time after the improvements was 2 seconds, meaning that an improvement of about 80% was achieved with relatively low effort, since most of what was done consisted of quick fixes. Of course, properly identifying what to do initially was key, and the perf panel was the right tool for this.

It's also important to highlight that these numbers are particular to a profile being used as a subject of study. The profile was interesting to us because it was particularly large. Nonetheless, since the processing pipeline is the same for every profile, the significant improvement achieved applies to every profile loaded in the perf panel.

Takeaways

There are some lessons to take away from these results in terms of performance optimization of your application:

1. Make use of profiling tools to identify runtime performance patterns

Profiling tools are incredibly useful to understand what's happening in your application while it's running, especially to identify opportunities to improve performance. The Performance panel in Chrome DevTools is a great option for web applications since it's the native web profiling tool in the browser, and it's actively maintained to be up-to-date with the latest web platform features. Also, it's now significantly faster! 😉

Use samples that can be used as representative workloads and see what you can find!

2. Avoid complex call hierarchies

When possible, avoid making your call graph too complicated. With complex call hierarchies, it's easy to introduce performance regressions and hard to understand why your code is running the way it is, making it hard to land improvements.

3. Identify unnecessary work

It's common for aging codebases to contain code that's no longer needed. In our case, legacy and unnecessary code was taking a significant portion of the total loading time. Removing it was the lowest-hanging fruit.

4. সঠিকভাবে ডেটা স্ট্রাকচার ব্যবহার করুন

Use data structures to optimize performance, but also understand the costs and trade-offs each type of data structure brings when deciding which ones to use. This isn't only the space complexity of the data structure itself, but also time complexity of the applicable operations.

5. Cache results to avoid duplicate work for complex or repetitive operations

If the operation is costly to execute, it makes sense to store its results for the next time it's needed. It also makes sense to do this if the operation is done many times—even if each individual time isn't particularly costly.

6. Defer non-critical work

If the output of a task isn't needed immediately and the task execution is extending the critical path, consider deferring it by lazily calling it when its output is actually needed.

7. Use efficient algorithms on large inputs

For large inputs, optimal time complexity algorithms become crucial. We didn't look into this category in this example, but their importance can hardly be overstated.

8. Bonus: benchmark your pipelines

To make sure your evolving code remains fast, it's wise to monitor the behavior and compare it against standards. This way, you proactively identify regressions and improve the overall reliability, setting you up for long-term success.