Bu bölümde bellek analizinde kullanılan yaygın terimler açıklanmaktadır ve farklı diller için çeşitli bellek profili oluşturma araçları için geçerlidir.
Burada açıklanan terimler ve kavramlar, Chrome Geliştirici Araçları Yığın Profil Aracı'na yöneliktir. Daha önce Java, .NET veya başka bir bellek profili oluşturucuyla çalıştıysanız bilgilerinizi tazeleyebilirsiniz.
Nesne boyutları
Hafızayı temel türleri (ör. sayılar ve dizeler) ve nesneleri (ilişkili diziler) içeren bir grafik olarak düşünebilirsiniz. Bağlantılı noktaların yer aldığı bir grafik aşağıdaki gibi görsel olarak sunulabilir:
Bir nesne, belleği iki şekilde saklayabilir:
- Doğrudan nesnenin kendisine.
- Dolaylı olarak, diğer nesnelere referans vererek ve dolayısıyla bu nesnelerin bir çöp toplayıcı (kısaca GC) tarafından otomatik olarak atılmasını engelleyerek.
Geliştirici Araçları'nda ("Profiller" altında bulunan bellek sorunlarını araştırmaya yönelik bir araç) Yığın Profil Aracı ile çalışırken muhtemelen birkaç farklı bilgi sütununa bakarsınız. Öne çıkan iki boyut Sığ Boyut ve Tutulan Boyut'tur. Peki bunlar neyi temsil eder?
Sığ boyut
Bu, nesnenin kendisinin tuttuğu bellek boyutudur.
Tipik JavaScript nesnelerinin açıklamaları ve anlık değerleri depolamak için ayrılmış bir belleğe sahiptir. Genellikle yalnızca dizi ve dizelerin önemli bir sığ boyutu olabilir. Bununla birlikte, dizeler ve harici dizilerin ana depolama alanları genellikle oluşturucu belleğinde bulunur. Bu durum, JavaScript yığınında yalnızca küçük bir sarmalayıcı nesnesini açığa çıkarır.
Oluşturucu belleği, incelenen bir sayfanın oluşturulduğu işlemin belleğidir: sayfanın yerel bellek + 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 otomatik atık toplama işlemi tarafından diğer nesnelerin atılmasını önleyerek büyük miktarda belleği dolaylı olarak saklayabilir.
Tutulan boyut
Bu, nesnenin kendisi silindikten sonra GC köklerinden erişilememesi nedeniyle ulaşılamayan bağımlı nesnelerle birlikte serbest bırakılan belleğin boyutudur.
GC kökleri, yerel koddan V8 dışındaki bir JavaScript nesnesine referans verirken oluşturulan (yerel veya genel) herkese açık kullanıcı adlarından oluşur. Bu tür herkese açık kullanıcı adlarının tümü, bir yığın anlık görüntüsünde GC kökleri > Handle scope (Kapsamı yönet) ve GC roots (GC kökleri) > Global işleyici (Genel kullanıcı adı) altında bulunabilir. Bu dokümandaki herkese açık kullanıcı adlarını, tarayıcı uygulamasının ayrıntılarına değinmeden açıklamak kafa karıştırıcı olabilir. Hem GC kökleri hem de herkese açık kullanıcı adları endişelenmeniz gereken bir konu değildir.
Çoğu kullanıcı için ilgi çekici olmayan çok sayıda dahili GC kökü vardır. Uygulamalar açısından bakıldığında aşağıdaki kök türleri bulunur:
- Pencere genel nesnesi (her iframe'de). Yığın anlık görüntülerinde, pencereden en kısa tutma yolundaki özellik başvurularının sayısı olan bir mesafe alanı bulunur.
- Belgede gezinerek erişilebilen tüm yerel DOM düğümlerini içeren belge DOM ağacı. Hepsinin JS sarmalayıcıları olmayabilir ancak sarmalayıcılar varsa doküman yayındayken aktif kalır.
- Bazen nesneler hata ayıklayıcı bağlamı ve Geliştirici Araçları konsolu tarafından saklanabilir (ör. konsol değerlendirmesinden sonra). Net bir konsolla ve hata ayıklayıcıda etkin kesme noktası olmadan yığın anlık görüntüleri oluşturun.
Bellek grafiği bir kökle başlar. Bu, tarayıcının window
nesnesi veya Node.js modülünün Global
nesnesi olabilir. Bu kök nesnenin nasıl GC'lendiğini kontrol edemezsiniz.
Kökten erişilemeyen öğeler GC'yi alır.
Nesne tutan ağaç
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 adı verilir. Kenarlar aracılığıyla bağlanan düğümlerden bir grafik oluşturulur. Her ikisine de etiket verilir.
- Düğümler (veya nesneler), bunları oluşturmak için kullanılan kurucu işlevinin adı kullanılarak etiketlenir.
- Kenarlar, özelliklerin adları kullanılarak etiketlenir.
Yığın Profil Aracı'nı kullanarak profil kaydetme hakkında bilgi edinin. Aşağıdaki Yığın Profil Aracı kaydında görebildiğimiz dikkat çekici şeylerden bazıları mesafe, yani GC köküne olan mesafedir. Aynı türdeki neredeyse tüm nesneler aynı mesafedeyse ve birkaçı daha uzaksa, bu araştırmaya değer.
Dominatörler
Her nesnenin tam bir baskın olduğu için baskın nesneler bir ağaç yapısından oluşur. Bir nesnenin baskın öğesi, hakim olduğu nesneye doğrudan referans vermeyebilir. Diğer bir deyişle, baskın kişinin ağacı, grafikte kapsayan bir ağaç değildir.
Aşağıdaki şemada:
- Düğüm 1, düğüm 2'ye hakim
- 2. düğüm 3, 4 ve 6. düğümlere hakimdir
- Düğüm 3, düğüm 5'e hakim
- Düğüm 5, düğüm 8'e hakim
- Düğüm 6, 7. düğüme hükmediyor
Aşağıdaki örnekte #3
, #10
düğümünün baskın öğesidir ancak #7
aynı zamanda GC'den #10
'a giden her basit yolda da bulunur. Bu nedenle, kökten A nesnesine kadar her basit yolda B varsa B nesnesi A nesnesinin baskın maddesidir.
V8 ile ilgili ayrıntılar
Belleğin profilini çıkarırken, yığın anlık görüntülerinin neden belirli bir şekilde göründüğünü anlamak faydalı olur. Bu bölümde, özellikle V8 JavaScript sanal makinesine (V8 sanal makine veya sanal makine) karşılık gelen bellekle ilgili bazı konular açıklanmaktadır.
JavaScript nesnesi temsili
Üç temel tür vardır:
- Sayılar (ör. 3.14159..)
- Boole değerleri (doğru veya yanlış)
- Dizeler (ör. "Werner Heisenberg")
Diğer değerlere başvuruda bulunamazlar ve her zaman yapraklar veya sonlandırma düğümleridirler.
Numaralar şunlardan biri olarak depolanabilir:
- Küçük tam sayılar (SMI'ler) adı verilen doğrudan 31 bitlik tam sayı değerleri veya
- yığın numaraları olarak adlandırılan yığın nesneleridir. Yığın numaraları, SMI formuna uymayan değerleri (ör. çift değerler) veya bir değerin kutuya alınması gerektiğinde (ör. üzerindeki özellikleri ayarlamak) depolamak için kullanılır.
Dizeler şunlardan birinde depolanabilir:
- Sanal makine yığını veya
- harici olarak oluşturucunun belleğinde. Sarmalayıcı nesnesi, harici depolama alanına erişmek için oluşturulur ve kullanılır. Bu nesnede, örneğin web'den alınan komut dosyası kaynakları ve diğer içeriğin sanal makine yığınına kopyalanmak yerine depolanır.
Yeni JavaScript nesneleri için bellek, özel bir JavaScript yığınından (veya sanal makine yığınından) ayrılır. Bu nesneler, V8'in atık toplayıcısı tarafından yönetilir ve bu nedenle, en az bir güçlü referans olduğu sürece varlıklarını korur.
Yerel nesneler, JavaScript yığınında olmayan diğer her şeydir. Yığın nesnesinin aksine yerel nesne, kullanım ömrü boyunca V8 çöp toplayıcı tarafından yönetilmez ve JavaScript'ten yalnızca JavaScript sarmalayıcı nesnesi kullanılarak erişilebilir.
Eksi dizesi, depolanan ve birleştirilen dize çiftlerinden oluşan ve birleştirme işleminin sonucu olan bir nesnedir. Eksileri dizesi içeriğinin birleştirilmesi yalnızca gerektiğinde gerçekleşir. Birleştirilmiş bir dizenin alt dizesinin oluşturulması gerektiğinde buna örnek olarak verilebilir.
Örneğin, a ve b'yi birbirine bağlarsanız birleştirme işleminin sonucunu temsil eden bir dize (a, b) elde edersiniz. Daha sonra bu sonuçla d öğesini bir araya getirirseniz başka bir eksi dizesi ((a, b), d) elde edersiniz.
Diziler: Dizi, sayısal anahtarlara sahip bir nesnedir. Bunlar, V8 sanal makinesinde büyük miktarlarda veriyi depolamak için yaygın olarak kullanılır. Sözlük gibi kullanılan anahtar/değer çifti kümeleri, dizilerle yedeklenir.
Tipik bir JavaScript nesnesi, depolamak için kullanılan iki dizi türünden biri olabilir:
- ve
- sayısal öğeler
Çok az sayıda özellik olduğu durumlarda, özellikler JavaScript nesnesinin içinde dahili olarak depolanabilir.
Harita: Nesnenin türünü ve düzenini açıklayan bir nesnedir. Örneğin, haritalar hızlı mülk erişimi için örtülü 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 ve bir sonraki eşdüzey öğeye bağlantı verdiği bir DOM alt ağacı düşünün. Böylece bağlantılı bir grafik oluşturulur. Yerel nesnelerin JavaScript yığınında temsil edilmediğini unutmayın. Bu yüzden boyutları sıfırdır. Bunun yerine sarmalayıcı nesneleri oluşturulur.
Her sarmalayıcı nesnesi, komutların kendisine yönlendirilmesi için karşılık gelen yerel nesneye bir referans içerir. Bir nesne grubu kendi sırasında sarmalayıcı nesneleri tutar. 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ı yayınlamayı unutmak, tüm grubu ve ilişkili sarmalayıcıları saklar.