হিপ স্ন্যাপশট রেকর্ড করুন

মেগিন কার্নি
Meggin Kearney
সোফিয়া ��মেলিয়ানোভা
Sofia Emelianova

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

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

একটি স্ন্যাপশট নিন

একটি গাদা স্ন্যাপশট নিতে:

  1. আপনি প্রোফাইল করতে চান এমন একটি পৃষ্ঠায়, DevTools খুলুন এবং মেমরি প্যানেলে নেভিগেট করুন।
  2. Heap স্ন্যাপশট প্রোফাইলিং টাইপ নির্বাচন করুন, তারপর একটি JavaScript VM ইন্সট্যান্স নির্বাচন করুন এবং স্ন্যাপশট নিন ক্লিক করুন।

একটি নির্বাচিত প্রোফাইলিং টাইপ এবং JavaScript VM উদাহরণ।

যখন মেমরি প্যানেল স্ন্যাপশট লোড করে এবং পার্স করে, তখন এটি HEAP SNAPSHOTS বিভাগে স্ন্যাপশট শিরোনামের নীচে পৌঁছানোযোগ্য জাভাস্ক্রিপ্ট অবজেক্টের মোট আকার দেখায়।

পৌঁছানো যায় এমন বস্তুর মোট আকার।

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

বিক্ষিপ্ত আইটেম বস্তুর একটি গাদা স্ন্যাপশট।

সাফ স্ন্যাপশট

সমস্ত স্ন্যাপশট মুছে ফেলতে, সমস্ত প্রোফাইল সাফ ক্লিক করুন:

সমস্ত প্রোফাইল সাফ করুন।

স্ন্যাপশট দেখুন

বিভিন্ন উদ্দেশ্যে বিভিন্ন দৃষ্টিকোণ থেকে স্ন্যাপশটগুলি পরিদর্শন করতে, শীর্ষে ড্রপ-ডাউন মেনু থেকে একটি দৃশ্য নির্বাচন করুন:

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

উপরের ড্রপ-ডাউন মেনু থেকে নির্বাচিত সারাংশ ভিউ।

সারাংশ ভিউ

প্রাথমিকভাবে, একটি হিপ স্ন্যাপশট সারাংশ ভিউতে খোলে যা কলামে কনস্ট্রাক্টরদের তালিকা করে। আপনি কনস্ট্রাক্টরকে প্রসারিত করতে পারেন তারা যে বস্তুগুলিকে তাৎক্ষণিকভাবে দেখে তা দেখতে।

একটি প্রসারিত কনস্ট্রাক্টর সহ সারাংশ দৃশ্য।

অপ্রাসঙ্গিক কনস্ট্রাক্টর ফিল্টার করার জন্য, সারাংশ ভিউয়ের শীর্ষে ক্লাস ফিল্টারে আপনি পরিদর্শন করতে চান এমন একটি নাম টাইপ করুন।

কন্সট্রাক্টরের নামের পাশের সংখ্যাগুলি কনস্ট্রাক্টরের সাথে তৈরি করা বস্তুর মোট সংখ্যা নির্দেশ করে। সারাংশ ভিউ নিম্নলিখিত কলামগুলিও দেখায়:

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

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

কনস্ট্রাক্টর ফিল্টার

সারাংশ ভিউ আপনাকে অদক্ষ মেমরি ব্যবহারের সাধারণ ক্ষেত্রের উপর ভিত্তি করে কনস্ট্রাক্টর ফিল্টার করতে দেয়।

এই ফিল্টারগুলি ব্যবহার করতে, অ্যাকশন বারে ডানদিকের ড্রপ-ডাউন মেনু থেকে নিম্নলিখিত বিকল্পগুলির মধ্যে একটি নির্বাচন করুন:

  • সমস্ত বস্তু : বর্তমান স্ন্যাপশট দ্বারা বন্দী সমস্ত বস্তু। ডিফল্টরূপে সেট করুন।
  • স্ন্যাপশট 1 এর আগে বরাদ্দকৃত অবজেক্ট : প্রথম স্ন্যাপশট নেওয়ার আগে যে অবজেক্ট তৈরি করা হয়েছিল এবং মেমরিতে থেকে গিয়েছিল।
  • স্ন্যাপশট 1 এবং স্ন্যাপশট 2 এর মধ্যে বরাদ্দ করা বস্তু : সাম্প্রতিক স্ন্যাপশট এবং পূর্ববর্তী স্ন্যাপশটের মধ্যে বস্তুর পার্থক্য দেখুন। প্রতিটি নতুন স্ন্যাপশট ড্রপ-ডাউন তালিকায় এই ফিল্টারের একটি বৃদ্ধি যোগ করে।
  • সদৃশ স্ট্রিং : স্ট্রিং মান যা মেমরিতে একাধিকবার সংরক্ষণ করা হয়েছে।
  • বিচ্ছিন্ন নোড দ্বারা রক্ষিত বস্তু : যে বস্তুগুলিকে জীবিত রাখা হয় কারণ একটি বিচ্ছিন্ন DOM নোড তাদের উল্লেখ করে।
  • DevTools কনসোল দ্বারা রক্ষিত অবজেক্ট : মেমরিতে রাখা বস্তুগুলি কারণ সেগুলি DevTools কনসোলের মাধ্যমে মূল্যায়ন করা হয়েছিল বা তাদের সাথে ইন্টারঅ্যাক্ট করা হয়েছিল৷

সারাংশে বিশেষ এন্ট্রি

কনস্ট্রাক্টরদের দ্বারা গোষ্ঠীবদ্ধ করার পাশাপাশি, সারাংশ ভিউ অবজেক্টগুলিকেও গোষ্ঠীভুক্ত করে:

  • বিল্ট-ইন ফাংশন যেমন Array বা Object
  • HTML উপাদানগুলি তাদের ট্যাগ দ্বারা গোষ্ঠীবদ্ধ, উদাহরণস্বরূপ, <div> , <a> , <img> এবং অন্যান্য।
  • আপনি আপনার কোডে সংজ্ঞায়িত ফাংশন.
  • বিশেষ বিভাগ যা নির্মাণকারীদের উপর ভিত্তি করে নয়।

কনস্ট্রাক্টর এন্ট্রি।

(array)

এই বিভাগে বিভিন্ন অভ্যন্তরীণ অ্যারে-সদৃশ অবজেক্ট রয়েছে যা জাভাস্ক্রিপ্টে দৃশ্যমান বস্তুর সাথে সরাসরি মিলিত নয়।

উদাহরণ স্বরূপ, জাভাস্ক্রিপ্ট Array অবজেক্টের বিষয়বস্তু একটি গৌণ অভ্যন্তরীণ বস্তু নামক (object elements)[] এ সংরক্ষিত হয়, যাতে সহজে আকার পরিবর্তন করা যায়। একইভাবে, জাভাস্ক্রিপ্ট অবজেক্টের নামযুক্ত বৈশিষ্ট্যগুলি প্রায়ই (object properties)[] নামে গৌণ অভ্যন্তরীণ অবজেক্টে সংরক্ষণ করা হয় যেগুলি (array) বিভাগে তালিকাভুক্ত করা হয়।

(compiled code)

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

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

(concatenated string)

যখন V8 দুটি স্ট্রিংকে সংযুক্ত করে, যেমন জাভাস্ক্রিপ্ট + অপারেটরের সাথে, এটি ফলাফলটিকে অভ্যন্তরীণভাবে একটি "সংযুক্ত স্ট্রিং" হিসাবে উপস্থাপন করতে বেছে নিতে পারে যা রোপ ডেটা স্ট্রাকচার নামেও পরিচিত।

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

InternalNode

এই বিভাগটি V8 এর বাইরে বরাদ্দকৃত বস্তুর প্রতিনিধিত্ব করে, যেমন Blink দ্বারা সংজ্ঞায়িত C++ অবজেক্ট।

C++ ক্লাসের নাম দেখতে, পরীক্ষার জন্য Chrome ব্যবহার করুন এবং নিম্নলিখিতগুলি করুন:

  1. DevTools খুলুন এবং চালু করুন Settings > Experiments > হিপ স্ন্যাপশটে ইন্টারনাল এক্সপোজ করার বিকল্প দেখান
  2. মেমরি প্যানেল খুলুন, Heap snapshot নির্বাচন করুন এবং এক্সপোজ ইন্টারনাল চালু করুন (অতিরিক্ত বাস্তবায়ন-নির্দিষ্ট বিবরণ সহ)
  3. InternalNode অনেক মেমরি ধরে রাখার কারণে সমস্যাটি পুনরুত্পাদন করুন।
  4. একটি গাদা স্ন্যাপশট নিন. এই স্ন্যাপশটে, অবজেক্টের InternalNode পরিবর্তে C++ ক্লাসের নাম রয়েছে।
(object shape)

V8-এর ফাস্ট প্রোপার্টিজ -এ যেমন বর্ণনা করা হয়েছে, V8 লুকানো শ্রেণীগুলি (বা আকারগুলি ) ট্র্যাক করে যাতে একই ক্রমে একই বৈশিষ্ট্য সহ একাধিক বস্তুকে দক্ষতার সাথে উপস্থাপন করা যায়। এই বিভাগে সেই লুকানো ক্লাসগুলি রয়েছে, যাকে বলা হয় system / Map (জাভাস্ক্রিপ্ট Map সাথে সম্পর্কিত নয়), এবং সম্পর্কিত ডেটা।

(sliced string)

যখন V8-এর একটি সাবস্ট্রিং নেওয়ার প্রয়োজন হয়, যেমন জাভাস্ক্রিপ্ট কোড যখন String.prototype.substring() কল করে, V8 মূল স্ট্রিং থেকে সমস্ত প্রাসঙ্গিক অক্ষর অনুলিপি করার পরিবর্তে একটি কাটা স্ট্রিং অবজেক্ট বরাদ্দ করতে পারে। এই নতুন অবজেক্টটিতে মূল স্ট্রিংটির একটি পয়েন্টার রয়েছে এবং মূল স্ট্রিং থেকে কোন অক্ষর ব্যবহার করতে হবে তা বর্ণনা করে।

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

system / Context

টাইপ system / Context অ��্যন্তরীণ অ�����েক্ট��� ক্লোজার থেকে স্থানীয় ভেরিয়েবল থাকে—একটি জাভাস্ক্রিপ্ট স্কোপ যা একটি নেস্টেড ফাংশন অ্যাক্সেস করতে পারে।

প্রতিটি ফাংশন Context একটি অভ্যন্তরীণ পয়েন্টার থাকে যা এটি কার্যকর করে, যাতে এটি সেই ভেরিয়েবলগুলি অ্যাক্সেস করতে পারে। যদিও Context অবজেক্টগুলি জাভাস্ক্রিপ্ট থেকে সরাসরি দেখা যায় না, তবে তাদের উপর আপনার সরাসরি নিয়ন্ত্রণ আছে।

(system)

এই বিভাগে বিভিন্ন অভ্যন্তরীণ বস্তু রয়েছে যেগুলিকে (এখনও) আরও অর্থপূর্ণ উপায়ে শ্রেণীবদ্ধ করা হয়নি।

তুলনা ভিউ

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

একটি নির্দিষ্ট অপারেশন লিক তৈরি করে না তা যাচাই করতে:

  1. অপারেশন করার আগে একটি হিপ স্ন্যাপশট নিন।
  2. একটি অপারেশন সঞ্চালন. অর্থাৎ, কোনো পৃষ্ঠার সাথে এমনভাবে ইন্টারঅ্যাক্ট করুন যা আপনার মনে হয় লিক হতে পারে।
  3. একটি বিপরীত অপারেশন সঞ্চালন. অর্থাৎ, বিপরীত মিথস্ক্রিয়া করুন এবং এটি কয়েকবার পুনরাবৃত্তি করুন।
  4. একটি সেকেন্ড হিপ স্ন্যাপশট নিন এবং স্ন্যাপশট 1 এর সাথে তুলনা করে এর ভিউকে তুলনা করুন।

তুলনা ভিউ দুটি স্ন্যাপশটের মধ্যে পার্থক্য দেখায়। মোট এন্ট্রি প্রসারিত করার সময়, যোগ করা এবং মুছে ফেলা বস্তুর উদাহরণগুলি দেখানো হয়:

স্ন্যাপশট 1 এর সাথে তুলনা করা।

কন্টেনমেন্ট ভিউ

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

ভিউ বিভিন্ন এন্ট্রি পয়েন্ট প্রদান করে:

  • DOMWindow অবজেক্ট । জাভাস্ক্রিপ্ট কোডের জন্য গ্লোবাল অবজেক্ট।
  • জিসি শিকড় । VM এর আবর্জনা সংগ্রহকারী দ্বারা ব্যবহৃত GC শিকড়। GC রুটে অন্তর্নির্মিত বস্তুর মানচিত্র, প্রতীক টেবিল, VM থ্রেড স্ট্যাক, সংকলন ক্যাশে, হ্যান্ডেল স্কোপ এবং গ্লোবাল হ্যান্ডেল থাকতে পারে।
  • দেশীয় বস্তু । ব্রাউজার অবজেক্টগুলি জাভাস্ক্রিপ্ট ভার্চুয়াল মেশিনের ভিতরে অটোমেশনের অনুমতি দিতে "পুশ" করে, উদাহরণস্বরূপ, DOM নোড এবং CSS নিয়ম।

কন্টেনমেন্ট ভিউ।

রিটেনার্স বিভাগ

মেমরি প্যানেলের নীচে রিটেনার্স বিভাগটি এমন বস্তু দেখায় যা দৃশ্যে নির্বাচিত বস্তুর দিকে নির্দেশ করে। মেমরি প্যানেল রিটেনার্স বিভাগ আপডেট করে যখন আপনি পরিসংখ্যান ব্যতীত যেকোন ভিউতে একটি ভিন্ন বস্তু নির্বাচন করেন।

রিটেনার্স বিভাগ।

এই উদাহরণে, নির্বাচিত স্ট্রিংটি একটি Item উদাহরণের x ব��শিষ্ট্য দ্বারা ধরে রাখা হয়।

ধারকদের উপেক্ষা করুন

আপনি অন্য যে কোনো বস্তু থেকে নির্বাচিত একটি বজায় রাখা খুঁজে বের করতে retainers লুকাতে পারেন. এই বিকল্পের সাহায্যে, আপনাকে প্রথমে কোড থেকে এই ধারকটিকে সরাতে হবে না এবং তারপরে হিপ স্ন্যাপশটটি পুনরায় নিতে হবে।

ড্রপ-ডাউন মেনুতে 'এই ধারককে উপেক্ষা করুন' বিকল্পটি।

একটি ধারক লুকানোর জন্য, ডান-ক্লিক করুন এবং এই ধারককে উপেক্ষা করুন নির্বাচন করুন। উপেক্ষা করা ধারকদের দূরত্ব কলামে ignored হিসাবে চিহ্নিত করা হয়েছে। সমস্ত ধারকদের উপেক্ষা করা বন্ধ করতে, শীর্ষে অ্যাকশন বারে উপেক্ষা করা রিটেনারদের পুনরুদ্ধার করুন ক্লিক করুন।

একটি নির্দিষ্ট বস্তু খুঁজুন

সংগৃহীত হিপে একটি বস্তু খুঁজে পেতে আপনি Ctrl + F ব্যবহার করে অনুসন্ধান করতে পারেন এবং অবজেক্ট আইডি লিখতে পারেন।

ক্লোজারগুলিকে আলাদা করার জন্য ফাংশনের নাম দিন

এটি ফাংশনগুলির নাম দিতে অনেক সাহায্য করে যাতে আপনি স্ন্যাপশটে বন্ধের মধ্যে পার্থক্য করতে পারেন।

উদাহরণস্বরূপ, নিম্নলিখিত কোড নামযুক্ত ফাংশন ব্যবহার করে না:

function createLargeClosure() {
  var largeStr = new Array(1000000).join('x');

  var lC = function() { // this is NOT a named function
    return largeStr;
  };

  return lC;
}

যদিও এই উদাহরণটি করে:

function createLargeClosure() {
  var largeStr = new Array(1000000).join('x');

  var lC = function lC() { // this IS a named function
    return largeStr;
  };

  return lC;
}

একটি বন্ধ ফাংশন নামকরণ.

DOM ফাঁস উন্মোচন করুন

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

DOM লিক আপনার ধারণার চেয়ে বড় হতে পারে। নিম্নলিখিত উদাহরণ বিবেচনা করুন. #tree আবর্জনা কখন সংগ্রহ করা হয়?

  var select = document.querySelector;
  var treeRef = select("#tree");
  var leafRef = select("#leaf");
  var body = select("body");

  body.removeChild(treeRef);

  //#tree can't be GC yet due to treeRef
  treeRef = null;

  //#tree can't be GC yet due to indirect
  //reference from leafRef

  leafRef = null;
  //#NOW #tree can be garbage collected

#leaf তার পিতামাতার ( parentNode ) একটি রেফারেন্স বজায় রাখে এবং পুনরাবৃত্তিমূলকভাবে #tree পর্যন্ত, তাই শুধুমাত্র যখন leafRef বাতিল করা হয় তখনই #tree এর নীচে পুরো গাছটি GC-এর প্রার্থী হয়।

DOM সাবট্রিস