Bellek sorunlarını düzeltme

Bellek sızıntısı, bellek şişmesi ve sık çöp toplama işlemleri gibi sayfa performansını etkileyen bellek sorunlarını bulmak için Chrome ve Geliştirici Araçları'nı nasıl kullanacağınızı öğrenin.

Özet

  • Chrome Görev Yöneticisi'ni kullanarak sayfanızın ne kadar bellek kullandığını öğrenin.
  • Zaman çizelgesi kayıtlarıyla zaman içindeki bellek kullanımını görselleştirin.
  • Ayrılmış DOM ağaçlarını (bellek sızıntılarının yaygın bir nedeni) yığın anlık görüntüleriyle tanımlayın.
  • Ayırma zaman çizelgesi kayıtlarını kullanarak JS yığınınızda ne zaman yeni bellek ayrıldığını öğrenin.
  • JavaScript referansı tarafından saklanan ayrılmış öğeleri tanımlama.

Genel Bakış

RAIL performans modelinin ruhuna uygun olarak, performans çalışmalarınızda kullanıcılarınıza odaklanmanız gerekir.

Hafıza sorunları, genellikle kullanıcılar tarafından fark edilebildiği için önemlidir. Kullanıcılar aşağıdaki şekillerde bellek sorunlarını algılayabilir:

  • Sayfanın performansı zaman içinde giderek kötüleşiyor. Bu durum, muhtemelen hafıza sızıntısının bir belirtisidir. Bellek sızıntısı, sayfadaki bir hatanın sayfanın zaman içinde giderek daha fazla bellek kullanmasına neden olmasıdır.
  • Sayfanın performansı sürekli olarak kötü. Bu durum, bellek şişmesinin bir belirtisi olabilir. Bellek şişmesi, bir sayfanın optimum sayfa hızı için gerekenden daha fazla bellek kullanmasıdır.
  • Sayfanın performansı gecikiyor veya sık sık duraklatılıyor. Bu durum, sık sık çöp toplamanın bir belirtisi olabilir. Çöp toplama, tarayıcının belleği geri almasıdır. Bu işlemin ne zaman yapılacağına tarayıcı karar verir. Koleksiyonlar sırasında tüm komut dosyası yürütme duraklatılır. Bu nedenle, tarayıcı çok fazla çöp topluyorsa komut dosyası yürütme çok sık duraklatılır.

Bellek şişmesi: "Çok fazla" ne kadardır?

Bellek sızıntısını tanımlamak kolaydır. Bir site giderek daha fazla bellek kullanıyorsa bellek sızıntısı vardır. Ancak bellek şişmesinin tespit edilmesi biraz daha zordur. "Çok fazla bellek kullanımı" ne anlama gelir?

Farklı cihazlar ve tarayıcıların farklı özellikleri olduğundan kesin bir sayı yoktur. Üst düzey bir akıllı telefonda sorunsuz çalışan sayfa, düşük kaliteli bir akıllı telefonda kilitlenebilir.

Buradaki anahtar, RAIL modelini kullanmak ve kullanıcılarınıza odaklanmaktır. Kullanıcılarınız arasında popüler olan cihazları öğrenin ve ardından sayfanızı bu cihazlarda test edin. Deneyim sürekli olarak kötüyse sayfa, bu cihazların bellek kapasitesini aşıyordur.

Chrome Görev Yöneticisi ile bellek kullanımını gerçek zamanlı olarak izleme

Bellek sorunuyla ilgili incelemenizin başlangıç noktası olarak Chrome Görev Yöneticisi'ni kullanın. Görev Yöneticisi, bir sayfanın ne kadar bellek kullandığını gösteren gerçek zamanlı bir izleyicidir.

  1. Görev Yöneticisi'ni açmak için Üst Karakter+Esc tuşlarına basın veya Chrome ana menüsüne gidip Diğer araçlar > Görev Yöneticisi'ni seçin.

    Görev Yöneticisi'ni açma.

  2. Görev Yöneticisi'nin tablo başlığını sağ tıklayın ve JavaScript belleği'ni etkinleştirin.

    Görev yöneticisi başlığında JS belleğini etkinleştirme.

Bu iki sütun, sayfanızı belleğin nasıl kullandığı hakkında farklı bilgiler verir:

  • Bellekte kaplanan yer sütunu, işletim sistemi belleğini temsil eder. DOM düğümleri, işletim sistemi belleğinde saklanır. Bu değer artıyorsa DOM düğümleri oluşturuluyor demektir.
  • JavaScript Bellek sütunu, JS yığınını temsil eder. Bu sütun iki değer içerir. İlgilendiğiniz değer, canlı sayı (parantez içindeki sayı) olur. Canlı sayı, sayfanızdaki erişilebilir nesnelerin ne kadar bellek kullandığını gösterir. Bu sayı artıyorsa yeni nesneler oluşturuluyor veya mevcut nesneler büyüyor demektir.

    JavaScript bellek başlığı etkinleştirilmiş Görev Yöneticisi.

Performans kayıtlarıyla bellek sızıntılarını görselleştirme

İncelemenizde başka bir başlangıç noktası olarak Performans panelini de kullanabilirsiniz. Performans paneli, bir sayfanın zaman içindeki bellek kullanımını görselleştirmenize yardımcı olur.

  1. Geliştirici Araçları'nda Performans panelini açın.
  2. Hafıza onay kutusunu etkinleştirin.
  3. Kayıt yapın.

Performans bellek kayıtlarını göstermek için aşağıdaki kodu kullanabilirsiniz:

var x = [];

function grow() {
  for (var i = 0; i < 10000; i++) {
    document.body.appendChild(document.createElement('div'));
  }
  x.push(new Array(1000000).join('x'));
}

document.getElementById('grow').addEventListener('click', grow);

Kodda referans verilen düğmeye her basıldığında doküman gövdesine on bin div düğümü eklenir ve x dizisine bir milyon x karakterlik bir dize aktarılır. Bu kodu çalıştırdığınızda aşağıdaki ekran görüntüsüne benzer bir zaman çizelgesi kaydı oluşturulur:

Basit bir büyüme örneği.

Öncelikle kullanıcı arayüzünü açıklayalım. Genel bakış bölmesinde (NET'in altında) bulunan HEAP grafiği, JS yığınını temsil eder. Genel Bakış bölmesinin altında Sayaç bölmesi bulunur. Burada, bellek kullanımını JS yığınına (Genel Bakış bölmesinde yer alan Yığın grafiğiyle aynıdır), dokümanlara, DOM düğümlerine, dinleyicilere ve GPU belleğine göre ayrılmış olarak görebilirsiniz. Devre dışı bırakılan onay kutuları grafikte gizlenir.

Şimdi, ekran görüntüsüyle karşılaştırmalı olarak kodun analizini göreceğiz. Düğüm sayıcıya (yeşil grafik) bakarsanız kodun düzgün bir şekilde eşleştiğini görebilirsiniz. Düğüm sayısı ayrı adımlarda artar. Düğüm sayısında yapılan her artışın grow() çağrısı olduğunu varsayabilirsiniz. JS yığın grafiği (mavi grafik) o kadar basit değildir. En iyi uygulamalara uygun olarak, ilk düşüş aslında zorunlu bir atık toplama işlemidir (Atık topla düğmesine basılarak yapılır). Kayıt ilerledikçe JS yığın boyutunun ani artışlar gösterdiğini görebilirsiniz. Bu durum doğal ve beklenen bir durumdur: JavaScript kodu, her düğme tıklamasında DOM düğümlerini oluşturur ve bir milyon karakterlik dize oluştururken çok fazla iş yapar. Buradaki en önemli nokta, JS yığınının başladığı noktadan daha yüksek bir noktada sona ermesidir (burada "başlangıç", zorunlu çöp toplamadan sonraki noktadır). Gerçek dünyada, JS yığın boyutunun veya düğüm boyutunun arttığı bu kalıbı görürseniz muhtemelen bellek sızıntısı söz konusudur.

Yığın anlık görüntüleriyle ayrılmış DOM ağacı bellek sızıntılarını keşfetme

Bir DOM düğümü yalnızca sayfanın DOM ağacından veya JavaScript kodundan kendisine referans olmadığında çöp toplanabilir. Bir düğüm, DOM ağacından kaldırılmış ancak bazı JavaScript'ler hâlâ ona referans veriyorsa"bağlantısı kaldırılmış" olarak adlandırılır. Ayrılmış DOM düğümleri, hafıza sızıntılarının yaygın bir nedenidir. Bu bölümde, ayrılmış düğümleri tanımlamak için DevTools'un yığın profilleyicilerini nasıl kullanacağınız açıklanmaktadır.

Ayrılmış DOM düğümlerine dair basit bir örnek aşağıda verilmiştir.

var detachedTree;

function create() {
  var ul = document.createElement('ul');
  for (var i = 0; i < 10; i++) {
    var li = document.createElement('li');
    ul.appendChild(li);
  }
  detachedTree = ul;
}

document.getElementById('create').addEventListener('click', create);

Kodda atıfta bulunulan düğmeyi tıkladığınızda on li alt öğesi olan bir ul düğümü oluşturulur. Bu düğümler kod tarafından referans gösterilir ancak DOM ağacında bulunmadığından ayrılır.

Ayrılmış düğümleri belirlemenin bir yolu yığın anlık görüntüleridir. Adından da anlaşılacağı gibi, yığın anlık görüntüleri, belleğin anlık görüntünün alındığı anda sayfanızı JS nesneleri ve DOM düğümleri arasında nasıl dağıtıldığını gösterir.

Anlık görüntü oluşturmak için DevTools'u açıp Bellek paneline gidin, Yığın Anlık Görüntüsü radyo düğmesini seçin ve ardından Anlık görüntü al düğmesine basın.

Yığın anlık görüntüsü al radyo düğmesi seçili.

Anlık görüntünün işlenmesi ve yüklenmesi biraz zaman alabilir. İşlem tamamlandığında sol panelden (Toplu görüntüler olarak adlandırılır) seçin.

Ayrılmış DOM ağaçları aramak için Sınıf filtresi giriş kutusuna Detached yazın.

Ayrılmış düğümleri filtreleme.

Ayrılmış bir ağacı incelemek için karat işaretlerini genişletin.

Ayrılmış bir ağacı inceleme.

Daha ayrıntılı incelemek istediğiniz bir düğümü tıklayın. Nesneler bölmesinde, söz konusu nesneye referans veren kod hakkında daha fazla bilgi görebilirsiniz. Örneğin, aşağıdaki ekran görüntüsünde detachedTree değişkeninin düğüme referans verdiğini görebilirsiniz. Bu bellek sızıntısını düzeltmek için detachedTree kullanan kodu inceleyip artık gerekli olmadığında düğüme referansını kaldırdığından emin olursunuz.

Ayrılmış bir düğümü inceleme.

Tahsis zaman çizelgeleriyle JS yığın bellek sızıntılarını tespit etme

Ayrılma Zaman Çizelgesi, JS yığınınızdaki bellek sızıntılarını izlemenize yardımcı olabilecek başka bir araçtır.

Ayrılma Zaman Çizelgesi'ni göstermek için aşağıdaki kodu ele alalım:

var x = [];

function grow() {
  x.push(new Array(1000000).join('x'));
}

document.getElementById('grow').addEventListener('click', grow);

Kodda referans verilen düğmeye her basıldığında x dizisine bir milyon karakterlik bir dize eklenir.

Ayrıntı Zaman Çizelgesi kaydetmek için DevTools'u açın, Bellek paneline gidin, Zaman çizelgesinde ayrılan yerler radyo düğmesini seçin, Kaydet düğmesine basın, bellek sızıntısına neden olduğundan şüphelendiğiniz işlemi gerçekleştirin ve işiniz bittiğinde Kaydı durdur düğmesine basın.

Kayıt yaparken Ayrıntı Zaman Çizelgesi'nde aşağıdaki ekran görüntüsünde gösterildiği gibi mavi çubuklar olup olmadığına dikkat edin.

Performans zaman çizelgesinde yeni ayrıştırmalar.

Bu mavi çubuklar yeni bellek tahsislerini gösterir. Bu yeni bellek atamalarının, bellek sızıntısı olasılığı taşıyan alanlar olduğunu unutmayın. Oluşturucu bölmesini yalnızca belirtilen zaman aralığında ayrılan nesneleri gösterecek şekilde filtrelemek için bir çubuğu yakınlaştırabilirsiniz.

Yakınlaştırılmış bir ayırma zaman çizelgesi.

Nesne bölmesinde ilgili daha fazla ayrıntı görüntülemek için nesneyi genişletin ve değerini tıklayın. Örneğin, aşağıdaki ekran görüntüsünde yeni atanan nesnenin ayrıntılarını görüntüleyerek Window kapsamındaki x değişkenine atandığını görebilirsiniz.

Bir dize dizisinin nesne ayrıntıları.

Bellek tahsisini işleve göre inceleme

JavaScript işlevine göre bellek tahsisini görüntülemek için Bellek panelindeki Tahsis örnekleme profil türünü kullanın.

Bellek panelinde tahsis örnekleme profilleyicisi.

  1. Ayrıntılandırma örnekleme radyo düğmesini seçin. Sayfada bir işleyici varsa JavaScript VM örneğini seçin penceresinden bunu profil oluşturma hedefi olarak seçebilirsiniz.
  2. Başlat düğmesine basın.
  3. İncelemek istediğiniz sayfadaki işlemleri gerçekleştirin.
  4. Tüm işlemlerinizi tamamladığınızda Durdur düğmesine basın.

DevTools, bellek tahsisinin işleve göre dökümünü gösterir. Varsayılan görünüm, en fazla bellek ayıran işlevleri en üstte gösteren Ağır (Aşağıdan Yukarı)'dır.

Ayırma profili sonuçları sayfası.

JS referansı tarafından saklanan nesneleri tanımlama

Ayrılmış öğeler profili, JavaScript kodu tarafından referans verildiği için kalıcı olan ayrılmış öğeleri gösterir.

Tam HTML düğümlerini ve düğüm sayısını görüntülemek için bir Bağımsız öğeler profili kaydedin.

Ayrılmış öğeler profili örneği.

Sık atık toplama noktalarını tespit etme

Sayfanız sık sık duraklatılıyorsa çöp toplama sorunları yaşıyor olabilirsiniz.

Sık sık çöp toplama işlemi yapıldığını tespit etmek için Chrome Görev Yöneticisi'ni veya Zaman Çizelgesi bellek kayıtlarını kullanabilirsiniz. Görev Yöneticisi'nde sık sık yükselip düşen Bellek veya JavaScript Bellek değerleri, sık sık çöp toplama işlemi yapıldığını gösterir. Zaman çizelgesi kayıtlarında, JS yığın veya düğüm sayısı grafiklerinin sık sık yükselip düşmesi sık sık çöp toplama işlemi yapıldığını gösterir.

Sorunu tespit ettikten sonra, belleğin nereye ayrıldığını ve hangi işlevlerin bu ayarlamalara neden olduğunu öğrenmek için bir Ayırma Zaman Çizelgesi kaydını kullanabilirsiniz.