Nesne Havuzları ile statik bellek JavaScript

Colt McAnlis
Colt McAnlis

Giriş

Bu yüzden, web oyununuzun / web uygulamanızın belirli bir süre sonra nasıl kötü performans gösterdiğini belirten bir e-posta alırsınız, Chrome'un bellek performansı araçlarını açana kadar kodunuzu ayrıntılı olarak inceler ve göze çarpan hiçbir şey görmezsiniz:

Bellek zaman çizelgenizden anlık görüntü

İş arkadaşlarınızdan biri, bellekle ilgili bir performans sorununuz olduğunu fark ettiği için gülüyor.

Bellek grafiği görünümünde, bu testere diş kalıbı kritik olabilecek bir performans sorununu çok iyi açıklıyor. Bellek kullanımınız arttıkça zaman çizelgesi görüntüsünde grafik alanının da büyüdüğünü görürsünüz. Grafik aniden düşüş gösterdiğinde bu, Çöp Toplayıcı'nın çalışıp başvuruda bulunduğunuz bellek nesnelerinizi temizlediği bir örnektir.

Testere Dişleri ne anlama gelir?

Böyle bir grafikte, web uygulamalarınızın performansına zarar verebilecek çok sayıda Çöp Toplama etkinliği gerçekleştiğini görebilirsiniz. Bu makalede, bellek kullanımınızı kontrol ederek performansınız üzerindeki etkiyi nasıl azaltacağınız hakkında bilgi verilmektedir.

Atık toplama ve performans maliyetleri

JavaScript'in bellek modeli, Atık Toplayıcı olarak bilinen bir teknoloji üzerine kurulmuştur. Birçok dilde programcı, sistemin Bellek Yığını'ndaki belleği ayırmaktan ve boşaltmaktan doğrudan sorumludur. Bununla birlikte, Atık Toplayıcı sistemi bu görevi programcı adına yönetir. Diğer bir deyişle, programcı referanssız hale geldiğinde nesneler doğrudan bellekten serbest bırakılmaz. Bunun yerine, daha sonra GC'nin bulgusal yöntemi bunun yararlı olacağına karar verdiğinde. Bu karar süreci, GC'nin etkin ve etkin olmayan nesneler üzerinde bir miktar istatistiksel analiz yapmasını gerektirir.

Atık toplama genellikle manuel bellek yönetiminin tam tersi olarak gösterilir. Bu da programcının hangi nesnelerin ayrılacağını ve bellek sistemine döndürüleceğini belirtmesini gerektirir.

GC'nin belleği geri kazanma işlemi serbest değildir. Bu sistem, genellikle işini yapmak için biraz zaman ayırarak mevcut performansınızda kesinti yapar. Bununla birlikte, ne zaman çalıştırılacağına sistemin kendisi karar verir. Bu işlem üzerinde kontrolünüz yoktur. Kod yürütme sırasında herhangi bir zamanda bir GC sinyali gerçekleşebilir ve bu, işlem tamamlanana kadar kod yürütmeyi engeller. Bu nabızın süresini genellikle siz bilemezsiniz. Programınızın herhangi bir noktada belleği nasıl kullandığına bağlı olarak çalışması biraz zaman alır.

Yüksek performanslı uygulamalar, kullanıcılara sorunsuz bir deneyim sunmak için tutarlı performans sınırlarına güvenir. Çöp toplayıcı sistemleri, rastgele süreler için rastgele zamanlarda çalışıp uygulamanın performans hedeflerine ulaşması için gereken süreyi tükettiğinden bu hedefe kısa devre dışı bırakabilir.

Bellek karmaşasını ve çöp toplama vergilerini azaltın

Belirtildiği gibi, bir dizi bulgu, bir atımın faydalı olacağı yeterli sayıda etkin olmayan nesne olduğunu belirlediğinde bir GC sinyali oluşur. Bu nedenle, Çöp Toplayıcı'nın uygulamanızın harcadığı zamanı azaltmanın anahtarı, aşırı sayıda nesne oluşturulması ve serbest bırakılması durumlarını mümkün olduğunca ortadan kaldırmaktır. Sık sık nesne oluşturma/serbest bırakma işlemine "bellek karmaşası" adı verilir. Uygulamanızın kullanım ömrü boyunca bellek karmaşasını azaltabilirseniz GC'nin yürütmeniz için aldığı süreyi de azaltabilirsiniz. Bu, oluşturulan ve yok edilen nesnelerin sayısını azaltmanız / kaldırmanız gerektiği, yani bellek ayırmayı durdurmanız gerektiği anlamına gelir.

Bu işlem, bellek grafiğinizi buradan taşır :

Bellek zaman çizelgenizden anlık görüntü

şuna ekleyin:

Statik Bellekli JavaScript

Bu modelde, grafiğin artık teste dişi benzeri bir kalıbın olmadığını, bunun yerine başlangıçta büyük oranda büyüdüğünü, ardından zamanla yavaşça arttığını görebilirsiniz. Bellek karmaşası nedeniyle performans sorunlarıyla karşılaşıyorsanız oluşturmak isteyeceğiniz grafik türü budur.

Statik bellekli JavaScript'e geçiş

Statik Bellekli JavaScript, uygulamanızın başlangıcında kullanım ömrü boyunca ihtiyaç duyacak tüm belleği önceden ayırmayı ve nesnelere artık ihtiyaç duyulmadığından yürütme sırasında bu belleği yönetmeyi içeren bir tekniktir. Bu hedefe birkaç basit adımda yaklaşabiliriz:

  1. Çeşitli kullanım senaryolarında gerekli canlı bellek nesnelerinin (tür başına) maksimum sayısını belirlemek üzere uygulamanızı kullanın.
  2. Bu maksimum tutarı önceden ayırmak için kodunuzu yeniden uygulayın ve daha sonra ana belleğe gitmek yerine manuel olarak alın/yayınlayın.

Aslına bakılırsa, 1 numarada başarıya ulaşmak için 2 numarada ilerlemek zorundayız. O yüzden bu noktadan başlayalım.

Nesne Havuzu

Basit bir şekilde açıklamak gerekirse nesne havuzlama, aynı türü paylaşan, kullanılmayan bir grup nesneyi tutma işlemidir. Kodunuz için yeni bir nesneye ihtiyacınız olduğunda Bellek Yığını sisteminden yeni bir nesne ayırmak yerine havuzdaki kullanılmayan nesnelerden birini geri dönüştürür. Harici kod nesneyle işlendikten sonra, nesneyi ana belleğe bırakmak yerine havuza geri döndürülür. Nesnenin koddan çıkarılmadığı (başka bir ifadeyle silinmediği) için atık toplama işlemi yapılmaz. Nesne havuzlarını kullanmak, bellek kontrolünü programcıya geri vererek çöp toplayıcının performans üzerindeki etkisini azaltır.

Bir uygulamanın yönettiği çok çeşitli nesne türleri olduğundan, nesne havuzlarının uygun kullanımı, uygulamanızın çalışma zamanı boyunca yüksek kayıp yaşanması durumunda her tür için bir havuza sahip olmanızı gerektirir.

var newEntity = gEntityObjectPool.allocate();
newEntity.pos = {x: 215, y: 88};

//..... do some stuff with the object that we need to do

gEntityObjectPool.free(newEntity); //free the object when we're done
newEntity = null; //free this object reference

Uygulamaların büyük çoğunluğunda, yeni nesneler tahsis etme gereksinimi açısından nihayetinde bazı düşüşler yaşayacaksınız. Uygulamanız birden fazla kez çalıştırıldığında, bu üst sınırın ne olduğuna dair iyi bir fikir edinebilir ve bu sayıdaki nesneleri uygulamanızın başında önceden ayırabilirsiniz.

Nesneleri önceden ayırma

Nesne havuzunu projenize uygulamak, uygulamanızın çalışma zamanı boyunca gereken nesne sayısı için teorik bir maksimum değer sağlar. Sitenizi çeşitli test senaryolarında çalıştırdıktan sonra, gerekli bellek gereksinimleri türlerini anlayabilir, bu verileri bir yerde kataloglayabilir ve uygulamanız için geçerli bellek gereksinimlerinin üst sınırlarını anlamak üzere bunları analiz edebilirsiniz.

Ardından, uygulamanızın gönderim sürümünde başlatma aşamasını, tüm nesne havuzlarını belirtilen bir miktarla önceden dolduracak şekilde ayarlayabilirsiniz. Bu işlem, tüm nesne başlatma işlemlerini uygulamanızın önüne aktarır ve yürütme sırasında dinamik olarak gerçekleşen ayırma miktarını azaltır.

function init() {
  //preallocate all our pools. 
  //Note that we keep each pool homogeneous wrt object types
  gEntityObjectPool.preAllocate(256);
  gDomObjectPool.preAllocate(888);
}

Seçtiğiniz tutar, uygulamanızın davranışı üzerinde büyük bir etkiye sahiptir; bazen teorik maksimum değer en iyi seçenek olmayabilir. Örneğin, ortalama maksimum değeri seçmek, deneyimli olmayan kullanıcılar için daha küçük bir bellek alanı sağlayabilir.

Sihirli değnek çok değil

Statik bellek artışı kalıplarının başarılı olabileceği uygulamalar için tam bir sınıflandırma vardır. Ancak Chrome DevRel Renato Mangini'nin de belirttiği gibi birkaç dezavantaj var.

Sonuç

JavaScript'in web için ideal olmasının nedenlerinden biri, uygulamanın hızlı, eğlenceli ve kolay bir şekilde kullanılmaya başlanmasıdır. Bunun ana nedeni, söz dizimi kısıtlamalarının ve sizin adınıza bellek sorunlarını işlemesinin önündeki engellerin düşük olmasıdır. Kodlayarak kirli işlerle ilgilenmesini sağlayabilirsiniz. Ancak, HTML5 oyunları gibi yüksek performanslı web uygulamalarında GC genellikle ihtiyaç duyulan kare hızını tüketebilir ve bu da son kullanıcı deneyimini azaltır. Bazı dikkatli enstrümantasyon ve nesne havuzlarının benimsenmesiyle, kare hızınızın üzerindeki bu yükü azaltabilir ve bu süreyi daha harika şeyler için geri alabilirsiniz.

Kaynak Kodu

Web'de çok sayıda nesne havuzu vardır, dolayısıyla başka bir tanesiyle canınızı sıkmayacağım. Bunun yerine sizi, uygulama ile ilgili belirli nüanslar içeren bu noktalara yönlendireceğim. Her uygulama kullanımının kendine özgü uygulama ihtiyaçları olabileceği düşünüldüğünde bunlar önemlidir.

Referanslar