Bu bölümde, bellek analizinde kullanılan yaygın terimler açıklanmaktadır ve farklı diller için çeşitli bellek profilleme araçlarında geçerlidir.
Burada açıklanan terimler ve kavramlar Chrome Geliştirici Araçları Yığın Profilleyicisi ile ilgilidir. Java, .NET veya başka bir bellek profilleyiciyle daha önce çalıştıysanız bu makale size yardımcı olabilir.
Nesne boyutları
Belleği, ilkel türler (sayılar ve dizeler gibi) ve nesneler (ilişkisel diziler) içeren bir grafik olarak düşünebilirsiniz. Görsel olarak, aşağıdaki gibi birbirine bağlı bir dizi nokta içeren bir grafik olarak gösterilebilir:
Bir nesne iki şekilde bellek tutabilir:
- Doğrudan nesnenin kendisi tarafından.
- Diğer nesnelere referanslar tutarak ve bu nedenle bu nesnelerin bir çöp toplayıcı (kısaltması GC) tarafından otomatik olarak kaldırılmasını engelleyerek dolaylı olarak.
DevTools'daki Heap Profiler (Hafıza panelinde bulunan hafıza sorunlarını incelemek için kullanılan bir araç) ile çalışırken muhtemelen birkaç farklı bilgi sütununa bakarsınız. Sığ Boyut ve Sabit Boyut öne çıkan iki boyuttur. Peki bu boyutlar neyi temsil eder?
Nesne öz boyutu
Bu, nesnenin kendisi tarafından tutulan bellek boyutudur.
Tipik JavaScript nesneleri, açıklamaları ve anlık değerleri depolamak için ayrılmış bir bellek alanına sahiptir. Genellikle yalnızca diziler ve dizelerin boyutu önemli ölçüde küçük olabilir. Ancak dizelerin ve harici dizilerin ana depolama alanı genellikle oluşturma aracı belleğindedir. Bu nedenle, JavaScript yığınında yalnızca küçük bir sarmalayıcı nesnesi gösterilir.
Oluşturucu belleği, incelenen bir sayfanın oluşturulduğu sürecin tüm belleğidir: yerel bellek + sayfanın JS yığın belleği + sayfa tarafından başlatılan tüm özel çalışanların JS yığın belleği. Bununla birlikte, küçük bir nesne bile diğer nesnelerin otomatik çöp toplama işlemiyle kaldırılmasını engelleyerek dolaylı olarak büyük miktarda bellek tutabilir.
Tutulan boyut
Bu, nesnenin kendisi GC köklerinden erişilemez hale getirilen bağımlı nesneleriyle birlikte silindikten sonra boşaltılan bellek boyutudur.
GC kökleri, yerel koddan V8 dışındaki bir JavaScript nesnesine referans verirken oluşturulan işleyicilerden (yerel veya genel) oluşur. Bu türdeki tüm herkese açık kullanıcı adları, bir yığın anlık görüntüsünde GC kökleri > Herkese açık kullanıcı adı kapsamı ve GC kökleri > Küresel herkese açık kullanıcı adları altında bulunabilir. Tarayıcının uygulama ayrıntılarına girmeden bu dokümanda herkese açık kimlikleri açıklamak kafa karıştırıcı olabilir. Hem GC kökleri hem de tutamaklarla ilgili endişelenmenize gerek yoktur.
Çoğu kullanıcılar için ilgi çekici olmayan çok sayıda dahili GC kökü vardır. Uygulamalar açısından aşağıdaki kök türleri vardır:
- Pencere global nesnesi (her iFrame'de). Yığın anlık görüntülerinde, pencereden en kısa koruma yolunda bulunan mülk referanslarının sayısı olan bir mesafe alanı vardır.
- Belgede gezinerek erişilebilen tüm yerel DOM düğümlerinden oluşan doküman DOM ağacı. Bunların hepsinin JS sarmalayıcısı olmayabilir ancak varsa sarmalayıcılar, doküman mevcut olduğu sürece etkin kalır.
- Bazen nesneler, hata ayıklayıcı bağlamı ve Geliştirici Araçları Konsolu tarafından saklanabilir (ör. konsol değerlendirmesinden sonra). Hata ayıklayıcıda net bir konsol ve etkin kesme noktası olmadan yığın anlık görüntüleri oluşturun.
Bellek grafiği, tarayıcı window
nesnesi veya Node.js modülü Global
nesnesi olabilecek bir kökle başlar. Bu kök nesnenin nasıl GC'ye alınacağını siz kontrol etmezsiniz.
Kökten erişilemeyen öğeler GC'ye gönderilir.
Ağacı saklayan nesneler
Yığın, birbirine bağlı nesnelerden oluşan bir ağdır. Matematik dünyasında bu yapıya grafik veya hafıza grafiği denir. Grafikler, kenarlar aracılığıyla birbirine bağlı düğümlerden oluşur. Her ikisine de etiketler verilir.
- Düğümler (veya nesneler), oluşturulmak için kullanılan yapıcı işlevinin adı kullanılarak etiketlenir.
- Kenarlar, mülklerin adları kullanılarak etiketlenir.
Yığın Profilleyici'yi kullanarak nasıl profil kaydedeceğinizi öğrenin. Aşağıdaki Heap Profiler kaydında görebileceğimiz dikkat çekici şeylerden bazıları mesafedir: GC köküne olan mesafe. Aynı türdeki nesnelerin neredeyse tamamı aynı mesafedeyse ve birkaçı daha uzaktaysa bu durum incelenmeye değerdir.
Dominasyon
Her nesnenin tam olarak bir hakimi olduğu için hakim nesneler bir ağaç yapısından oluşur. Bir öğenin dominator'u, dominada ettiği öğeye doğrudan referanslar içermeyebilir. Yani dominator'un ağacı, grafiğin kapsayıcı ağacı değildir.
Aşağıdaki şemada:
- 1. düğüm 2. düğüme hükmediyor
- 2. düğüm, 3., 4. ve 6. düğümleri yönetir
- 3. düğüm 5. düğüme hakimdir
- 5. düğüm 8. düğüme hakimdir
- 6. düğüm 7. düğüme hakimdir
Aşağıdaki örnekte, #3
düğümü #10
'un hakimidir ancak #7
, GC'den #10
'a giden her basit yolda da bulunur. Bu nedenle, kökten A nesnesine giden her basit yolda B nesnesi varsa B, A nesnesinin hakimidir.
V8 ayrıntıları
Belleği profillerken yığın anlık görüntülerinin neden belirli bir şekilde göründüğünü anlamak yararlıdır. Bu bölümde, bellekle ilgili bazı konular özellikle V8 JavaScript sanal makinesine (V8 sanal makinesi veya sanal makine) karşılık gelecek şekilde açıklanmaktadır.
JavaScript nesnesi gösterimi
Üç temel tür vardır:
- Sayılar (ör. 3,14159..)
- Boole değerleri (doğru veya yanlış)
- Dize (ör. 'Werner Heisenberg')
Diğer değerlere referans veremezler ve her zaman yaprak veya sonlandırma düğümleridir.
Sayılar aşağıdaki biçimlerde depolanabilir:
- Küçük tam sayılar (SMIs) olarak adlandırılan 31 bitlik bir anlık tam sayı veya
- Yığın numaraları olarak adlandırılan yığın nesneleri. Toplu sayılar, SMI biçimine sığmayan değerleri (ör. çift) depolamak veya bir değerin kutuya alınması gerektiğinde (ör. üzerinde özellikler ayarlama) kullanılır.
Dizeler aşağıdaki yerlerde depolanabilir:
- Sanal makine yığınını veya
- Oluşturucunun belleğinde harici olarak depolanır. Harici depolamaya erişmek için bir sarmalayıcı nesnesi oluşturulur ve kullanılır. Örneğin, komut dosyası kaynakları ve web'den alınan diğer içerikler, sanal makine yığınına kopyalanmak yerine bu depolama alanında saklanır.
Yeni JavaScript nesneleri için bellek, özel bir JavaScript yığınından (veya VM yığınından) ayrılır. Bu nesneler V8'in çöp toplayıcısı tarafından yönetilir ve bu nedenle, kendilerine en az bir güçlü referans olduğu sürece etkin kalır.
Yerli nesneler, JavaScript yığınında bulunmayan diğer tüm öğelerdir. Yerel nesne, yığın nesnesinin aksine kullanım ömrü boyunca V8 çöp toplayıcısı tarafından yönetilmez ve yalnızca JavaScript sarmalayıcı nesnesi kullanılarak JavaScript'den erişilebilir.
Cons dizesi, depolanan ve birleştirilen dize çiftlerinden oluşan bir nesnedir ve birleştirme işleminin sonucudur. cons dizesi içeriklerinin birleştirilmesi yalnızca gerektiğinde gerçekleşir. Bir örnek, birleştirilmiş bir dizenin alt dizesi oluşturulması gerektiğinde ortaya çıkar.
Örneğin, a ve b değerlerini birleştirirseniz birleştirmenin sonucunu temsil eden bir dize (a, b) elde edersiniz. Daha sonra bu sonuçla d öğesini birleştirirseniz başka bir birleştirilmiş dize ((a, b), d) elde edersiniz.
Diziler: Dizi, sayısal anahtarları olan bir nesnedir. Bunlar, büyük miktarda veri depolamak için V8 sanal makinesinde yaygın olarak kullanılır. Sözlük gibi kullanılan anahtar/değer çiftleri kümeleri diziler tarafından desteklenir.
Tipik bir JavaScript nesnesi, depolamak için kullanılan iki dizi türünden biri olabilir:
- adlandırılmış mülkler ve
- sayısal öğeler
Çok az sayıda özelliğin olduğu durumlarda, bu özellikler JavaScript nesnesinin içinde depolanabilir.
Harita: Nesnenin türünü ve düzenini açıklayan bir nesne. Örneğin, haritalar hızlı mülk erişimi için gizli nesne hiyerarşilerini tanımlamak amacıyla kullanılır.
Nesne grupları
Her yerel nesne grubu, birbirine karşılıklı referanslar içeren nesnelerden oluşur. Örneğin, her düğümün üst öğesine ve bir sonraki alt öğeye ve bir sonraki kardeş öğeye bağlantısı olan ve böylece bağlı bir grafik oluşturan bir DOM alt ağacı düşünün. Yerel nesnelerin JavaScript yığınında temsil edilmediğini unutmayın. Bu nedenle, sıfır boyuta sahiptirler. Bunun yerine sarmalayıcı nesneler oluşturulur.
Her sarmalayıcı nesnesi, komutları yönlendirmek için ilgili yerel nesneye referans içerir. Nesne grupları ise sarmalayıcı nesneleri barındırır. Ancak GC, sarmalayıcılarına artık referans verilmeyen nesne gruplarını serbest bırakacak kadar akıllı olduğundan bu durum, toplanamayan bir döngü oluşturmaz. Ancak tek bir sarmalayıcıyı serbest bırakmayı unuttuğunuzda tüm grup ve ilişkili sarmalayıcılar beklemeye alınır.