Mobil ve Oyun Geliştirme kod örnekli
Nesne Havuzu (Object Pool) ile Oyunda Kare Düşmesini Önlemek
Her mermi için yeni nesne üretmek çöp toplayıcıyı tetikler ve oyun takılır. Nesne havuzu bu maliyeti nasıl sıfırlar?

İçindekiler
Bu yazıyı dinle
Yapay zekâ sesiyle yaklaşık 2 dakikalık özet
Nesne havuzu, sık üretilip sık yok edilen nesneleri her seferinde yeniden yaratmak yerine, önceden hazırlanmış bir koleksiyondan ödünç alıp iş bitince geri vermektir. Oyun geliştirmede bu desen bir stil tercihi değil, çoğu zaman akıcı kare hızının önkoşuludur.

Problem: çöp toplayıcı duraklaması
Bir nişancı oyununda saniyede 60 kare çiziliyorsa ve her karede on mermi doğuyorsa, dakikada 36.000 kısa ömürlü nesne üretiyorsunuz demektir. Bu nesneler hemen ölür, ama ölmeleri bedavaya gelmez: çöp toplayıcı belirli aralıklarla devreye girip belleği tarar ve bu sırada oyun donar. Duraklama 16 milisaniyeyi aştığı anda oyuncu bunu takılma olarak hisseder.
Ortalama kare süresi iyi görünse bile takılma yaşanabilir. Çöp toplayıcı duraklamaları ortalamayı değil, en kötü yüzdelik dilimi (p99 kare süresi) bozar. Ölçerken ortalamaya değil, en kötü kareye bakın.
Havuzun iskeleti
Havuz üç işten sorumludur: hazırla, ödünç ver, geri al. Aşağıdaki uygulama JavaScript ile yazıldı ama mantık her dilde aynıdır.
class NesneHavuzu {
/**
* @param {Function} uret Yeni nesne üreten fabrika
* @param {Function} sifirla Nesneyi ilk hâline döndüren fonksiyon
* @param {number} onIsitma Başlangıçta kaç nesne hazırlansın
*/
constructor(uret, sifirla, onIsitma = 64) {
this.uret = uret;
this.sifirla = sifirla;
this.bosta = [];
this.kullanimda = 0;
// Ön ısıtma: oyun başlarken bir kez tahsis, oyun sırasında hiç
for (let i = 0; i < onIsitma; i++) this.bosta.push(uret());
}
al() {
this.kullanimda++;
const nesne = this.bosta.pop();
return nesne !== undefined ? nesne : this.uret(); // havuz boşsa büyüt
}
birak(nesne) {
this.sifirla(nesne);
this.bosta.push(nesne);
this.kullanimda--;
}
get istatistik() {
return { bosta: this.bosta.length, kullanimda: this.kullanimda };
}
}Kullanımı, mermi mantığını neredeyse hiç değiştirmez:
const mermiHavuzu = new NesneHavuzu(
() => ({ x: 0, y: 0, hiz: 0, aktif: false }),
(m) => { m.x = 0; m.y = 0; m.hiz = 0; m.aktif = false; },
256
);
function atesEt(x, y, hiz) {
const m = mermiHavuzu.al();
m.x = x; m.y = y; m.hiz = hiz; m.aktif = true;
sahne.push(m);
}
function guncelle(dt) {
for (let i = sahne.length - 1; i >= 0; i--) {
const m = sahne[i];
m.y -= m.hiz * dt;
if (m.y < 0) {
sahne.splice(i, 1);
mermiHavuzu.birak(m); // ← unutulursa havuz büyür, sızıntı olur
}
}
}En büyük risk: geri vermeyi unutmak
Havuzun getirdiği tek yeni hata sınıfı budur. Nesne ödünç alınır ama iade edilmezse havuz sürekli büyür ve elle yönetilen bir bellek sızıntısı elde edersiniz. İki savunma işe yarar: her karede kullanimda sayacını izlemek ve nesneyi iade eden kodu, onu alan kodun hemen yanında tutmak. Bu, farklı bellek modellerinde sahiplik kavramının neden bu kadar merkezî olduğunu da açıklar — konuyu bellek yönetimi modelleri yazımızda ele almıştık.
Sabit zaman adımıyla birlikte düşünün
Havuz, tahsis kaynaklı takılmayı çözer; ancak fizik hesabı kare süresine bağlıysa yavaş karelerde nesneler yine sıçrar. İki teknik birlikte kullanılmalıdır: havuz belleği sabitler, sabit zaman adımı ise hareketi sabitler.
Ne zaman gerek yok?
Havuz da bir tür önbellektir; hangi katmanda ne kadar tutulacağını toplu yükleme deseni yazımızdaki gibi ölçerek belirlemek gerekir. Havuz her nesne için gerekmez. Ölçüt basittir: nesne sık üretiliyor mu ve kısa mı yaşıyor? İkisi birden doğruysa aday, biri yanlışsa gereksiz karmaşıklıktır. Menü ekranındaki düğmeler için havuz kurmak, kazanç sağlamadan kod okunurluğunu düşürür. Uzun ömürlü ama tahsisi pahalı kaynaklar (ağ bağlantısı, doku belleği) ise farklı bir desenle — tembel yükleme ve önbellek — yönetilmelidir.
Ölçmeden karar vermeyin
// En kötü kare süresini izlemek, ortalamadan çok daha bilgilendiricidir
let kareler = [];
function olc(dt) {
kareler.push(dt);
if (kareler.length === 600) {
kareler.sort((a, b) => a - b);
console.log('medyan', kareler[300].toFixed(2), 'p99', kareler[594].toFixed(2));
kareler = [];
}
}Tarayıcı tarafında bellek davranışını görmek için MDN bellek yönetimi belgeleri ve tarayıcının performans profil aracı birlikte kullanılmalıdır.
Sonuç
Nesne havuzu, oyunlarda takılmanın en yaygın sebeplerinden birini — sık tahsis ve ardından gelen çöp toplayıcı duraklamasını — ortadan kaldırır. Uygulaması kırk satırdır, ama beraberinde tek bir disiplin gerektirir: aldığınız her nesneyi geri verin. Önce ölçün, testere dişi bir bellek grafiği görüyorsanız havuzu kurun, sonra en kötü kare süresini yeniden ölçüp kazancı kanıtlayın. Bir sonraki oyun döngünüzde saniyede kaç nesne doğduğunu bir kez sayın; sayı sizi şaşırtırsa doğru deseni bulmuşsunuz demektir.
İlgili Yazılar
Sık sorulan sorular
Nesne havuzu her oyun için gerekli mi?
Hayır. Basit bir bulmaca oyununda kare başına birkaç nesne üretiliyorsa havuz kazanç getirmez, yalnızca karmaşıklık ekler. Havuz, saniyede yüzlerce kısa ömürlü nesne üreten sistemlerde (mermi, parçacık efekti, düşman dalgası) anlamlıdır.
Havuz boyutunu nasıl seçmeliyim?
Oyunun en yoğun anındaki eşzamanlı nesne sayısını ölçün ve üzerine pay ekleyin. Havuz boşaldığında yeni nesne üretmesine izin veren esnek bir tasarım, yanlış tahmini ölümcül olmaktan çıkarır; sadece o anda bir tahsis maliyeti oluşur.
Havuzdan alınan nesneyi sıfırlamayı unutursam ne olur?
Önceki kullanımdan kalan değerler yeni nesneye sızar ve son derece zor bulunan hatalar üretir: örneğin ölmüş bir düşmanın canı yeni düşmana geçer. Bu yüzden sıfırlama fonksiyonunu havuzun kendi sorumluluğunda tutmak, çağıran koda bırakmaktan güvenlidir.
Çöp toplayıcısı olmayan dillerde havuz gerekli mi?
C++ veya Rust gibi dillerde çöp toplayıcı duraklaması yoktur, ama tahsis işleminin kendisi ve bellek parçalanması hâlâ maliyetlidir. Bu dillerde havuz, öngörülebilir bellek düzeni sağladığı için önbellek isabet oranını da artırır — gerekçe değişir, fayda kalır.
Yazan
Çılgın Yazılım
Ben Evren Çılgın; yazılım geliştirme, web teknolojileri ve sistem tasarımı alanlarında uzmanlaşmış bir geliştiriciyim. Uzun yıllardır hem frontend hem de backend tarafında üretken, ölçeklenebilir ve kullanıcı dostu çözümler üretiyorum.
Bu konuda bir projeniz mi var?
İhtiyacınızı birkaç cümleyle anlatın; uygun yaklaşımı birlikte belirleyelim.
İlgili yazılar
Yorumlar
Henüz yorum yok. Sorunuzu ya da deneyiminizi ilk siz yazın.
Yorum yazın
Yorumunuz onaylandıktan sonra yayınlanır. Ekibimiz gerekirse konuyla ilgili bir yanıt da paylaşır.

