Bellek Sızıntısı Hakkında
webman, sürekli bellek üzerinde çalışan bir çerçeve olduğu için bellek sızıntısı durumuna biraz dikkat etmemiz gerekiyor. Ancak geliştiricilerin aşırı endişelenmesine gerek yok çünkü bellek sızıntıları çok aşırı koşullarda meydana geliyor ve kolayca önlenebilir. webman'ın geliştirilmesi, geleneksel çerçeve geliştirmenin deneyimiyle temelde aynıdır, bu nedenle bellek yönetimi için gereksiz bir işlem yapmaya gerek yoktur.
İpucu
webman ile birlikte gelen monitor (izleme) işlemi, tüm işlemlerin bellek kullanımını izler. Eğer bir işlem, php.ini'dekimemory_limit
değerine yaklaşırsa, ilgili işlemi güvenli bir şekilde otomatik olarak yeniden başlatır ve böylece bellek boşaltılır; bu süreçte işlere bir etkisi olmaz.
Bellek Sızıntısı Tanımı
İsteklerin sürekli artmasıyla, webman'ın kullandığı bellek de sonsuz artar (dikkat: sonsuz artar), yüzlerce M'ye veya daha fazlasına ulaşır; bu durum bellek sızıntısıdır. Eğer bellek artışı olursa fakat daha sonra artmaya devam etmezse bu, bellek sızıntısı sayılmaz.
Genellikle bir işlemin kullandığı bellek onlarla M arasında oldukça normaldir; bir işlem çok büyük istekleri işlediğinde veya çok sayıda bağlantıyı sürdürdüğünde, tek bir işlemde bellek kullanımı yüzlerce M'ye kadar çıkabilir. Bu bellek kullanıldıktan sonra php, tümünü işletim sistemine geri vermeyebilir. Bunun yerine, yeniden kullanılmak üzere tutulur, bu nedenle belirli bir büyük isteği işledikten sonra bellek kullanımının artması ve bellek boşaltılmaması durumu normaldir. (gc_mem_caches() yöntemini çağırmak, boş bellek alanlarının bir kısmını serbest bırakabilir)
Bellek Sızıntısı Nasıl Oluşur
Bellek sızıntısının meydana gelmesi için aşağıdaki iki koşulu sağlamak gereklidir:
- Uzun yaşam süreli bir dizi olmalıdır (dikkat: uzun yaşam süreli dizi, sıradan diziler sorun yaratmaz)
- Ve bu uzun yaşam süreli dizi sonsuz genişleyecektir (işlem sonsuz veri ekler, hiçbir zaman veri temizlemez)
Eğer 1 ve 2 koşulları aynı anda sağlanırsa (dikkat: aynı anda sağlanırsa), o zaman bellek sızıntısı meydana gelecektir. Aksi takdirde bu koşullardan biri veya her ikisi sağlanmazsa bu bir bellek sızıntısı değildir.
Uzun Yaşam Süreli Diziler
webman'daki uzun yaşam süreli diziler şunlardır:
- static anahtar kelimesiyle tanımlanan diziler
- Tekil (singleton) dizi özellikleri
- global anahtar kelimesiyle tanımlanan diziler
Dikkat
webman'da uzun yaşam süreli verilerin kullanılmasına izin verilir, ancak verinin içindeki verilerin sınırlı olduğundan ve eleman sayısının sonsuz genişlemeyeceğinden emin olunmalıdır.
Aşağıda birkaç örnekle açıklanmıştır.
Sonsuz Genişleyen Static Dizi
class Foo
{
public static $data = [];
public function index(Request $request)
{
self::$data[] = time();
return response('hello');
}
}
static
anahtar kelimesiyle tanımlanan $data
dizisi uzun yaşam süreli bir dizidir ve örnekte $data
dizisi her istekle birlikte sürekli artmakta ve genişlemekte, bu da bellek sızıntısına yol açmaktadır.
Sonsuz Genişleyen Tekil Dizi Özelliği
class Cache
{
protected static $instance;
public $data = [];
public function instance()
{
if (!self::$instance) {
self::$instance = new self;
}
return self::$instance;
}
public function set($key, $value)
{
$this->data[$key] = $value;
}
}
Çağrı kodu
class Foo
{
public function index(Request $request)
{
Cache::instance()->set(time(), time());
return response('hello');
}
}
Cache::instance()
bir Cache tekil örneği döndürmektedir, bu uzun yaşam süreli bir sınıf örneğidir. Her ne kadar $data
özelliği static
anahtar kelimesiyle kullanılmasa da, sınıfın kendisi uzun yaşam süreli olduğu için $data
da uzun yaşam süreli bir dizidir. Sürekli olarak $data
dizisine farklı anahtarlarla veri ekledikçe programın bellek kullanımı artmakta ve bellek sızıntısına yol açmaktadır.
Dikkat
Eğer Cache::instance()->set(key, value) ile eklenen anahtarların sınırlı sayıda olması durumunda bellek sızıntısı olmayacaktır çünkü$data
dizisi sonsuz genişlememektedir.
Sonsuz Genişleyen Global Dizi
class Index
{
public function index(Request $request)
{
global $data;
$data[] = time();
return response($foo->sayHello());
}
}
global anahtar kelimesiyle tanımlanan diziler, fonksiyon veya sınıf metodu tamamlandıktan sonra geri alınmadığı için uzun yaşam süreli dizilerdir. Yukarıdaki kod her istekle birlikte bellek sızıntısına yol açacaktır. Benzer şekilde, fonksiyon veya metot içinde static
anahtar kelimesiyle tanımlanan diziler de uzun yaşam süreli diziler olup, eğer dizi sonsuz genişlerse bellek sızıntısına yol açar; örneğin:
class Index
{
public function index(Request $request)
{
static $data = [];
$data[] = time();
return response($foo->sayHello());
}
}
Öneriler
Geliştiricilerin bellek sızıntısına özel bir dikkat göstermemeleri önerilir çünkü çok nadir durumlarda ortaya çıkar. Eğer talihsiz bir şekilde meydana gelirse, performans testleriyle hangi kodun sızıntıyı ürettiği bulabiliriz ve böylece sorunları belirleyebiliriz. Geliştiricilerin sızıntı noktasını bulamadığı durumlarda, webman'ın kendi monitor hizmeti bellek sızıntısının meydana geldiği işlemleri uygun bir zamanda güvenli bir şekilde yeniden başlatarak belleği serbest bırakır.
Eğer bellek sızıntısını mümkün olduğunca önlemek istiyorsanız, aşağıdaki önerileri dikkate alabilirsiniz.
- Mümkünse
global
,static
anahtar kelimelerini içeren dizileri kullanmaktan kaçının; eğer kullanacaksanız, sonsuz genişlemediğinden emin olun. - Tanımadığınız sınıfları tekil olarak kullanmaktan kaçının ve
new
anahtar kelimesiyle başlatın. Eğer tekil bir yapı gerekiyorsa, onun sonsuz genişleyen dizi özellikleri olup olmadığını kontrol edin.