JavaScript Engine, Memory Leaks

Mehmet Sağır
FowApps
Published in
3 min readDec 23, 2022

Bu makalede Memory Leaks (Bellek Sızıntısı) nedir? Ne gibi durumlarda karşımıza çıkar ve bellek sızıntılarından nasıl kaçınırız gibi soruları cevaplayacağız.

Bildiğiniz gibi JavaScript motoru, değişken ve nesneler tanımlandığında geliştiricinin müdahalesi olmadan bellek üzerinde bir yer tahsil eder ve artık bellek tarafında tutulmasına gerek kalmayan durumlarda değişken ve nesneleri kaldırarak belleği boşaltır.

Bellek yönetiminin temel aşamalarını hatırlayacak olursak;

  • Bellek alanı tahsil et
  • Kullan (Okuma ve yazma)
  • Temizle (İhtiyaç duyulmayan nesne ve değişkenlerin bellekten kaldırılması)

Son aşama olan ihtiyaç duyulmayan nesne ve değişkenlerin bellekten kaldırılma işini bizim için çöp toplayıcı yapar. Aslında Memory Management (bellek yönetimi) konusunda JavaScript, geliştiricinin bir müdahalesini beklemez. Tüm işlemleri arka planda otomatik olarak gerçekleştirir. Fakat bu, biz geliştiricilerin bu konuyu önemsemeden devam edebileceği anlamına gelmez. Yaptığımız mantıksal bir hata bellek tarafında tanımlanan değişken veya nesnenin kaldırılamamasına yol açabilir. Bu da uygulamanın yavaş çalışmasına, yüksek gecikme sürelerine ve hatta çökmelere sebep olur. Özetle bellek sızıntısı, bellek tarafında kullanılmayı bekleyen unutulmuş verilerdir.

Bellek sızıntısına yol açacak bir kod parçasını incelemek isterseniz boş bir dizi tanımlayıp sonsuz bir döngü içerisinde o diziye değer ekleyebilirsiniz.

const arr = [];

while(true) {
arr.push(Math.random())
}

Bu kod parçası Chrome üzerinde bulunduğunuz sekmeyi çökertecektir.

Yaygın Bellek Sızıntıları

1- Global Değişkenler

JavaScript’te tanımlanmamış değişkene yapılan çağrı global nesnenin içinde yeni bir değişken oluşturur. Global değişkenler her zaman kökten elde edilebilir ve hiçbir zaman çöp toplayıcı tarafından toplanmaz.

Tarayıcı üzerinde bu Window’u temsil eder.

name = "Mehmet"

Bu şekilde yazılmış bir kod,

window.name = "Mehmet"

Aslında bu şekilde algılanır.

Bu tarz hataların önüne geçebilmek için JavaScript dosyalarınızın başına 'use strict' yazarak daha katı JavaScript ayrıştırma moduna sahip olabilirsiniz.

2- Zamanlayıcılar

setTimeout veya setInterval ile bir nesneye atıfta bulunmak, nesnenin çöp toplayıcı tarafından temizlenememesinin en yaygın yoludur.

Aşağıdaki örnekte nesne yalnızca zamanlayıcı temizlendikten sonra çöp toplayıcı tarafından temizlenir. Referansımız olmadığı için Interval asla silinmez ve data.hugeStringhiç kullanılmasa da uygulama durana kadar hafızada tutulur.

function setCallback() {
const data = {
counter: 0,
hugeString: new Array(100000).join('x')
};

return function cb() {
data.counter++;
console.log(data.counter);
}
}

setInterval(setCallback(), 1000);

Bunu önlemek için zamanlayıcıyı bir şarta bağlayarak veya bir tetikleyici ile ‘clearInterval’ kullanarak temizleyebiliriz.

const btn = document.getElementById("btn")

function setCallback() {
const data = {
counter: 0,
hugeString: new Array(100000).join('x')
};

return function cb() {
data.counter++;
console.log(data.counter);
}
}

const interval = setInterval(setCallback(), 1000);

/**
if (true) { // your condition
clearInterval(interval);
}
*/

// or

btn.addEventListener("click", () => {
clearInterval(interval)
}, { once: true })

3- Olay dinleyicileri

Olay dinleyici, kapsamında bulunan tüm değişkenlerin çöp toplayıcı tarafından toplanmasını önleyecektir.

DOM öğesi, Nesne Grafiği Belleğinde de bulunur. Bu nedenle, ilkini silerseniz ikincisini de silmeniz gerekir.

const btn = document.getElementById("btn");
const text = document.getElementById("text");

btn.addEventListener("click", () => {
text.remove();
});

Örnekte gördüğünüz gibi buton elemanına tıklanınca Text elemanı DOM’dan kaldırılır. Ancak dinleyici için ayrılan bellek hala kullanılır.

const btn = document.getElementById("btn");
const text = document.getElementById("text");

btn.addEventListener("click", () => {
text.remove();
}, { once: true });

Bunu engellemek için işlem bittiğinde removeEventListener ile dinleyiciyi temizleyebilir veya örnekteki gibi üçüncü bir parametre olarak once: true diyerek dinleyicinin olayı bir defa işledikten sonra sonlanmasını sağlayabiliriz.

JavaScript bellek sızıntılarını belirleyip düzeltmek süreç ilerledikçe daha zorlu bir göreve dönüşebilir. Bu nedenle en mantıklı çözüm, bellek yönetimi sürecinin ayrılmaz bir parçası tipik bellek sızıntısı kaynaklarını anlamak ve bunların olmasını en baştan önlemektir. Sonuç olarak konu bellek ve performans ve söz konusu olan kullanıcı deneyimidir.

Okuduğunuz için teşekkürler 🥳

Kaynaklar:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Memory_Management
https://auth0.com/blog/four-types-of-leaks-in-your-javascript-code-and-how-to-get-rid-of-them/

--

--