اصطلاحات حافظه

مگین کرنی
Meggin Kearney

این بخش اصطلاحات رایج مورد استفاده در تجزیه و تحلیل حافظه را توصیف می کند و برای انواع ابزارهای پروفایل حافظه برای زبان های مختلف قابل استفاده است.

اصطلاحات و مفاهیم شرح داده شده در اینجا به نمایه Heap Chrome DevTools اشاره دارد. اگر تا به حال با جاوا، دات نت، یا سایر نمایه سازهای حافظه کار کرده اید، ممکن است این یک تجدید کننده باشد.

اندازه اشیا

حافظه را به عنوان یک نمودار با انواع اولیه (مانند اعداد و رشته ها) و اشیا (آرایه های انجمنی) در نظر بگیرید. ممکن است به صورت بصری به صورت نموداری با تعدادی نقطه به هم پیوسته به صورت زیر نمایش داده شود:

نمایش تصویری حافظه

یک شی می تواند به دو صورت حافظه را نگه دارد:

  • مستقیماً توسط خود شی.
  • به طور ضمنی با نگه داشتن ارجاع به اشیاء دیگر، و در نتیجه جلوگیری از دفع خودکار آن اشیاء توسط یک زباله جمع کن (به اختصار GC ).

هنگام کار با Heap Profiler در DevTools (ابزاری برای بررسی مسائل مربوط به حافظه که در قسمت "Profiles" یافت می شود)، احتمالاً متوجه خواهید شد که به چند ستون مختلف اطلاعات نگاه می کنید. دو مورد برجسته عبارتند از: Shallow Size و Retained Size ، اما اینها چه چیزی را نشان می دهند؟

اندازه کم عمق و حفظ شده

اندازه کم عمق

این اندازه حافظه ای است که توسط خود شی نگهداری می شود.

اشیاء معمولی جاوا اسکریپت مقداری حافظه برای توضیحات و ذخیره مقادیر فوری دارند. معمولاً فقط آرایه ها و رشته ها می توانند اندازه کم عمق قابل توجهی داشته باشند. با این حال، رشته‌ها و آرایه‌های خارجی اغلب ذخیره‌سازی اصلی خود را در حافظه رندر دارند و تنها یک شیء بسته‌بندی کوچک در پشته جاوا اسکریپت را نشان می‌دهند.

حافظه رندر تمام حافظه فرآیندی است که در آن صفحه بازرسی شده رندر می شود: حافظه بومی + حافظه پشته JS صفحه + حافظه پشته JS همه کارگران اختصاصی که توسط صفحه شروع شده اند. با این وجود، حتی یک شی کوچک می تواند مقدار زیادی از حافظه را به طور غیرمستقیم نگه دارد، با جلوگیری از دفع اشیاء دیگر توسط فرآیند جمع آوری زباله خودکار.

اندازه حفظ شده

این اندازه حافظه ای است که پس از حذف خود شیء به همراه اشیاء وابسته به آن که از ریشه های GC غیرقابل دسترس شده اند، آزاد می شود.

ریشه‌های GC از دسته‌هایی تشکیل شده‌اند که هنگام ارجاع از کد بومی به یک شی جاوا اسکریپت خارج از V8 ایجاد می‌شوند (چه محلی یا جهانی). همه این دسته‌ها را می‌توان در یک عکس فوری در زیر GC roots > Handle scope و GC roots > Global handles پیدا کرد. توصیف دسته ها در این مستندات بدون غوطه ور شدن در جزئیات اجرای مرورگر ممکن است گیج کننده باشد. هم ریشه های GC و هم دسته ها چیزی نیستند که نیازی به نگرانی داشته باشید.

تعداد زیادی روت GC داخلی وجود دارد که بیشتر آنها برای کاربران جالب نیستند. از دیدگاه برنامه های کاربردی، انواع ریشه های زیر وجود دارد:

  • شی جهانی پنجره (در هر iframe). یک فیلد فاصله در عکس‌های فوری پشته وجود دارد که تعداد ارجاعات ویژگی در کوتاه‌ترین مسیر نگهدارنده از پنجره است.
  • درخت DOM سند متشکل از تمام گره های DOM بومی که با عبور از سند قابل دسترسی هستند. ممکن است همه آنها دارای بسته بندی JS نباشند، اما اگر آنها wrapper ها را داشته باشند، تا زمانی که سند زنده است، زنده خواهند بود.
  • گاهی اوقات ممکن است اشیا توسط زمینه اشکال زدا و کنسول DevTools حفظ شوند (مثلاً پس از ارزیابی کنسول). عکس‌های فوری پشته‌ای با کنسول واضح و بدون نقاط شکست فعال در اشکال‌زدا ایجاد کنید.

نمودار حافظه با یک ریشه شروع می شود که ممکن است شی window مرورگر یا شی Global یک ماژول Node.js باشد. شما کنترل نمی کنید که چگونه این شی ریشه GC'd شود.

شی ریشه قابل کنترل نیست

هر چیزی که از ریشه قابل دسترسی نباشد GC می گیرد.

درخت نگهدارنده اشیاء

پشته شبکه ای از اشیاء به هم پیوسته است. در دنیای ریاضی به این ساختار گراف یا نمودار حافظه می گویند. یک گراف از گره هایی که به وسیله یال هایی به هم متصل شده اند ساخته می شود که هر دو دارای برچسب هستند.

  • گره ها ( یا اشیا ) با استفاده از نام تابع سازنده که برای ساخت آنها استفاده شده است، برچسب گذاری می شوند.
  • لبه ها با استفاده از نام ویژگی ها برچسب گذاری می شوند.

نحوه ضبط نمایه با استفاده از Heap Profiler را بیاموزید. برخی از چیزهای چشم نوازی که می توانیم در ضبط Heap Profiler در زیر مشاهده کنیم عبارتند از فاصله: فاصله از ریشه GC. اگر تقریباً تمام اجسام از یک نوع در یک فاصله قرار دارند و تعداد کمی از آنها در فاصله بیشتری قرار دارند، این چیزی است که ارزش بررسی دارد.

فاصله از ریشه

سلطه گران

اشیاء Dominator از یک ساختار درختی تشکیل شده اند زیرا هر شی دقیقاً یک Dominator دارد. سلطه گر یک شی ممکن است فاقد ارجاع مستقیم به شیئی باشد که بر آن تسلط دارد. یعنی درخت غالب یک درخت پوشا از نمودار نیست.

در نمودار زیر:

  • گره 1 بر گره 2 مسلط است
  • گره 2 بر گره های 3، 4 و 6 تسلط دارد
  • گره 3 بر گره 5 مسلط است
  • گره 5 بر گره 8 مسلط است
  • گره 6 بر گره 7 مسلط است

ساختار درختی غالب

در مثال زیر، گره #3 غالب #10 است، اما #7 نیز در هر مسیر ساده از GC تا #10 وجود دارد. بنابراین، اگر B در هر مسیر ساده از ریشه تا شی A وجود داشته باشد، یک شی B غالب بر یک شی A است.

تصویر متحرک سلطه گر

مشخصات V8

هنگام نمایه‌سازی حافظه، درک اینکه چرا عکس‌های فوری پشته به شکل خاصی به نظر می‌رسند، مفید است. این بخش برخی از موضوعات مرتبط با حافظه را که به طور خاص مربوط به ماشین مجازی جاوا اسکریپت V8 (V8 VM یا VM) هستند، توضیح می دهد.

نمایش شی جاوا اسکریپت

سه نوع اولیه وجود دارد:

  • اعداد (به عنوان مثال، 3.14159..)
  • بولی ها (درست یا نادرست)
  • رشته ها (به عنوان مثال، "ورنر هایزنبرگ")

آنها نمی توانند به مقادیر دیگر ارجاع دهند و همیشه برگ یا گره پایانی هستند.

اعداد را می توان به صورت زیر ذخیره کرد:

  • یک مقادیر صحیح 31 بیتی به نام اعداد صحیح کوچک ( SMIs ) یا
  • اجسام پشته ای که به آنها اعداد پشته گفته می شود. اعداد Heap برای ذخیره مقادیری استفاده می‌شوند که در فرم SMI قرار نمی‌گیرند، مانند دو برابر ، یا زمانی که یک مقدار باید کادر بندی شود، مانند تنظیم ویژگی‌ها روی آن.

رشته ها را می توان در یکی از موارد زیر ذخیره کرد:

  • پشته VM ، یا
  • خارجی در حافظه رندر . یک شی wrapper ایجاد می شود و برای دسترسی به حافظه خارجی استفاده می شود، جایی که، به عنوان مثال، منابع اسکریپت و سایر محتوای دریافتی از وب ذخیره می شود، به جای کپی شدن در پشته VM.

حافظه برای اشیاء جاوا اسکریپت جدید از یک پشته اختصاصی جاوا اسکریپت (یا پشته VM ) اختصاص داده می شود. این اشیاء توسط جمع کننده زباله V8 مدیریت می شوند و بنابراین تا زمانی که حداقل یک مرجع قوی به آنها وجود داشته باشد، زنده می مانند.

اشیاء بومی هر چیز دیگری هستند که در پشته جاوا اسکریپت نیستند. شیء بومی، بر خلاف شی heap، در طول عمر خود توسط جمع‌آورنده زباله V8 مدیریت نمی‌شود، و فقط می‌توان از جاوا اسکریپت با استفاده از شی بسته بندی جاوا اسکریپت به آن دسترسی داشت.

رشته Cons جسمی است که از جفت رشته‌هایی تشکیل شده است که ذخیره شده و سپس به هم متصل شده‌اند و نتیجه الحاق است. پیوستن محتویات رشته منفی فقط در صورت لزوم انجام می شود. یک مثال می تواند زمانی باشد که یک رشته فرعی از یک رشته متصل شده باید ساخته شود.

به عنوان مثال، اگر a و b را به هم متصل کنید، یک رشته (a, b) دریافت می کنید که نشان دهنده نتیجه الحاق است. اگر بعداً d را با آن نتیجه الحاق کنید، یک رشته منفی دیگر ((a, b, d) دریافت خواهید کرد.

آرایه ها - آرایه یک شی با کلیدهای عددی است. آنها به طور گسترده در V8 VM برای ذخیره مقادیر زیادی داده استفاده می شوند. مجموعه‌ای از جفت‌های کلید-مقدار مورد استفاده مانند دیکشنری‌ها توسط آرایه‌ها پشتیبان‌گیری می‌شوند.

یک شی جاوا اسکریپت معمولی می تواند یکی از دو نوع آرایه مورد استفاده برای ذخیره سازی باشد:

  • خواص نامگذاری شده و
  • عناصر عددی

در مواردی که تعداد بسیار کمی از ویژگی ها وجود دارد، می توان آنها را به صورت داخلی در خود شی جاوا اسکریپت ذخیره کرد.

نقشه -شیئی که نوع شی و چیدمان آن را توصیف می کند. به عنوان مثال، نقشه ها برای توصیف سلسله مراتب اشیاء ضمنی برای دسترسی سریع به ویژگی استفاده می شوند.

گروه های شی

هر گروه اشیاء بومی از اشیایی تشکیل شده است که ارجاعات متقابلی به یکدیگر دارند. به عنوان مثال، یک زیردرخت DOM را در نظر بگیرید که در آن هر گره پیوندی به والد خود دارد و به فرزند بعدی و خواهر یا برادر بعدی پیوند دارد، بنابراین یک نمودار متصل تشکیل می‌شود. توجه داشته باشید که اشیاء بومی در پشته جاوا اسکریپت نشان داده نمی شوند - به همین دلیل اندازه آنها صفر است. در عوض، اشیاء wrapper ایجاد می شوند.

هر شیء wrapper یک ارجاع به شیء بومی مربوطه دارد تا دستورات را به آن هدایت کند. به نوبه خود، یک گروه شیء اشیاء بسته بندی را نگه می دارد. با این حال، این یک چرخه غیرقابل جمع‌آوری ایجاد نمی‌کند، زیرا GC به اندازه کافی هوشمند است تا گروه‌های شی را آزاد کند که پوشش‌های آنها دیگر ارجاع داده نمی‌شود. اما فراموش کردن آزاد کردن یک لفاف، کل گروه و لفاف های مرتبط را نگه می دارد.