PHP Academy · Ders

Bellek Yönetimi ve Çöp Toplama

zval'ların, başvuru sayımının ve GC'nin nasıl çalıştığını görün.

2. ders / 413 adım

Bellek Yönetimi ve Çöp Toplama, CoddyKit'te ücretsiz bir PHP Academy dersidir. Bu, 4 dersinin 2. dersidir. Aşağıdan dersin tamamını ücretsiz okuyabilir, sonra tarayıcıda yerleşik kod editörü ve 7/24 yapay zeka koçu ile uygulamalı olarak pratik yapabilirsin. Bu, PHP Academy öğrenme yolunun bir parçasıdır ve ilerlemeniz web ve CoddyKit uygulaması arasında senkronize olur. PHP Academy kursu toplamda 4 dersten oluşur.

PHP Belleği Nasıl Yönetir

PHP değerleri çoğunlukla referans sayımı ile yönetilen zval yapılarında yaşar; referans sayımının yakalayamadığı durumları bulmak için bir döngü toplayıcısı kullanılır. Bunu anlamak, uzun süre çalışan işçilerdeki bellek sızıntılarını, kopyaların maliyetini ve gc_collect_cycles() işlevinin ne zaman önem kazandığını açıklar.

zval

Bir zval, herhangi bir PHP değerinin kapsayıcısıdır: bir tür etiketi ve değer depolama birleşimi içerir. Skalerler (int, float, bool) zval içinde değer olarak saklanır ve NOT referans sayımına tabi tutulur. Karmaşık türler (string, array, object) yığın üzerinde referans sayımı yapılan bir yapıya işaret eder.

<?php
// debug_zval_refcount-style inspection via gc + count
$arr = [1, 2, 3];
$copy = $arr;   // refcount of the array bumps, no data copy yet (CoW)

// Modifying triggers copy-on-write separation
$copy[] = 4;

var_dump($arr);   // still [1,2,3]
var_dump($copy);  // [1,2,3,4]
?>

Referans Sayımı

Referans sayımı yapılan her değer, kendisine işaret eden zval sayısını takip eder. Atama sayıyı artırır; bir değeri kaldırma veya kapsamdan çıkma sayıyı azaltır. Sayı sıfıra ulaştığında bellek, bir çöp toplayıcı geçişinin yapılması beklenmeden hemen serbest bırakılır. PHP belleğinin büyük bölümü bu şekilde geri kazanılır.

<?php
$a = str_repeat('x', 1000);  // refcount 1 on the string
$b = $a;                      // refcount 2
unset($a);                    // refcount 1
unset($b);                    // refcount 0 -> freed instantly

echo "Refcounting frees deterministically\n";
?>

Yazma Sırasında Kopyalama

Atama verileri kopyalamaz; verileri paylaşır ve referans sayısını artırır (yazma sırasında kopyalama). Gerçek çoğaltma, yalnızca paylaşılan bir değere ilk kez yazıldığında gerçekleşir. Bu nedenle büyük dizileri aktarmak, değiştirilene kadar ucuzdur.

<?php
$big = range(1, 100000);
$shared = $big;          // O(1): shared, refcount++

// Reads stay shared and cheap
echo count($shared), PHP_EOL;

// First write separates (copies) — now it costs O(n)
$shared[0] = -1;
echo $big[0], ' vs ', $shared[0], PHP_EOL;  // 1 vs -1
?>

Sorun: Döngüler

Tek başına referans sayımı referans döngülerini serbest bırakamaz. A nesnesi B'ye, B de A'ya referans tutuyorsa, tüm harici değişkenleri kaldırsanız bile sayaçları hiçbir zaman sıfıra ulaşmaz; bellek, döngü toplayıcısı çalışana kadar sızar.

<?php
class Node { public ?Node $ref = null; }

$a = new Node();
$b = new Node();
$a->ref = $b;   // a -> b
$b->ref = $a;   // b -> a  (cycle!)

unset($a, $b);  // external refs gone, but internal cycle keeps refcount > 0

// The objects are unreachable but NOT yet freed by refcounting alone.
echo gc_collect_cycles() . " cycles collected\n";
?>

Döngü Toplayıcısı

PHP'nin çöp toplayıcısı kökler üzerinde eşzamanlı işaretle-ve-süpür algoritması uygular. Olası döngü kökleri (referans sayımı azaltılıp sıfıra inmeyen değerler) arabelleğe alınır. Kök arabelleği dolduğunda (varsayılan olarak 10.000), çöp toplayıcı çalışır: azaltma işlemlerini benzetir, gerçekten erişilemez grupları bulur ve serbest bırakır.

<?php
// GC status exposes the root buffer and run stats
for ($i = 0; $i < 3; $i++) {
    $a = new stdClass();
    $b = new stdClass();
    $a->b = $b; $b->a = $a;   // create a cycle
    unset($a, $b);            // becomes a GC root
}

print_r(gc_status());
?>

Çöp Toplayıcıyı Denetleme

Toplayıcının davranışını yönlendirebilirsiniz: gc_disable()/gc_enable() onu devre dışı bırakır veya etkinleştirir, gc_collect_cycles() bir geçişi zorlar ve serbest bırakılan sayıyı döndürür. Üretim hızı açısından kritik toplu işlerde bazen sıkı bir aşama boyunca çöp toplayıcı devre dışı bırakılır, ardından aşamanın sonunda bir kez çalıştırılır.

<?php
gc_disable();              // no automatic cycle collection

// ... heavy phase that creates and drops many cycles ...
for ($i = 0; $i < 1000; $i++) {
    $x = new stdClass(); $y = new stdClass();
    $x->y = $y; $y->x = $x; unset($x, $y);
}

$freed = gc_collect_cycles();   // reclaim all at once
gc_enable();
echo "Freed $freed objects\n";
?>

Uzun Süre Çalışan İşçiler

CLI arka plan programlarında, kuyruk tüketicilerinde ve Swoole/RoadRunner işçilerinde bellek, isteğin sonlandırılmasıyla geri kazanılmaz; süreç saatlerce yaşar. Şunlara dikkat edin: sınırsız büyüyen statik önbellekler, biriken döngüler ve kapatılmamış kaynaklar. memory_get_usage(true) ile izleyin ve işçileri belirli aralıklarla yeniden başlatın.

<?php
$peakStart = memory_get_usage(true);

// Simulate processing a batch of jobs
for ($job = 0; $job < 5; $job++) {
    $payload = range(0, 10000);
    // ... process ...
    unset($payload);
}

printf("start: %d KB, peak: %d KB, now: %d KB\n",
    $peakStart >> 10,
    memory_get_peak_usage(true) >> 10,
    memory_get_usage(true) >> 10
);
?>

WeakReference ve WeakMap

Bir nesneyi hayatta tutmadan onunla veri önbelleğe almak veya veriyi nesneyle ilişkilendirmek için WeakReference (8.0) ve WeakMap (8.0) kullanın. WeakMap girdisi, anahtar nesnesinin referans sayısını artırmaz; bu nedenle nesne toplanabilir ve girdisi otomatik olarak kaldırılır. Bu, bellek sızıntısına yol açmaması gereken üstveri yan tabloları için idealdir.

<?php
$map = new WeakMap();

$obj = new stdClass();
$map[$obj] = 'metadata';      // does NOT keep $obj alive

echo count($map) . PHP_EOL;   // 1
unset($obj);                  // object collectible -> entry removed
echo count($map) . PHP_EOL;   // 0
?>

Tekilleştirilmiş Dizeler ve Değişmezler

Kaynağınızdaki sabit dizeler tekilleştirilir: bir kez saklanır, paylaşılır ve istek sırasında ne referans sayımına tabi tutulur ne de serbest bırakılır. OPcache, tekilleştirilmiş dizeleri ve değişmez (önbelleğe alınmış) iş kodu dizilerini istekler arasında paylaşılan belleğe taşır. Bu nedenle dize sabitlerini kopyalamak fiilen ücretsizdir.

Bellek Sınırı ve Ayırıcı

PHP, sistem ayırıcısının üzerinde çalışan kendi emalloc ayırıcısını (Zend Bellek Yöneticisi) kullanır ve istek başına kullanımı memory_limit değerine göre izler. Sınıra ulaşılması ölümcül bir hata oluşturur. memory_get_usage(true) içindeki true, betiğinizin o anda tuttuğu değerleri değil, OS tarafından gerçekten ayrılmış blokları raporlar.

<?php
echo 'limit: ' . ini_get('memory_limit') . PHP_EOL;
echo 'emalloc usage: ' . memory_get_usage() . " bytes\n";   // ZendMM tracked
echo 'real usage:    ' . memory_get_usage(true) . " bytes\n"; // from OS
?>

Hızlı Kontrol

Tek başına referans sayımı neden bazı nesnelerde bellek sızıntısına yol açabilir?

Özet

PHP değerleri zval yapılarında saklar; skalerler değer olarak tutulur, karmaşık türler ise yığın üzerinde ayrılır ve referans sayımı ile yazma sırasında kopyalama kullanılarak yönetilir. Referans sayımı sayaç sıfıra ulaştığında belleği belirli bir şekilde serbest bırakır, ancak döngüleri geri kazanamaz. Bu nedenle eşzamanlı bir işaretle-ve-süpür toplayıcısı, kök arabelleği dolduğunda (veya gc_collect_cycles() aracılığıyla) çalışır. Sahiplik oluşturmayan ilişkiler için WeakMap/WeakReference kullanın ve uzun süre çalışan işçilerde sınırsız büyümeye dikkat edin.

Başlamak ücretsiz

Yapay zeka eğitmeniyle PHP öğren — ücretsiz

Tarayıcında gerçek kod yaz ve çalıştır, 7/24 yapay zeka eğitmeninden anında yardım al; web'de ya da uygulamada kaldığın yerden devam et.

Kurslar
49
Dersler
195

Sıkça Sorulan Sorular

“Bellek Yönetimi ve Çöp Toplama” dersi ücretsiz mi?

Evet — “Bellek Yönetimi ve Çöp Toplama” dersin tüm metni burada web'de ücretsiz olarak okunabilir. Etkileşimli olarak pratik yapmak (yerleşik kod editörü ve 7/24 yapay zeka koçu) ve PHP Academy kursunun geri kalanını açmak için CoddyKit PRO'ya yükselt. PHP Academy kursu toplamda 4 dersten oluşur.

“Bellek Yönetimi ve Çöp Toplama” dersinde ne öğreneceğim?

zval'ların, başvuru sayımının ve GC'nin nasıl çalıştığını görün. PHP Academy ile uygulamalı kodu tarayıcıda doğrudan çalıştırarak pratik yaparsın ve 7/24 yapay zeka koçu dersi çalışırken sorularını yanıtlar.

PHP Academy öğrenmeye başlamak için deneyim gerekli mi?

Önceden deneyim gerekmez. CoddyKit'te PHP Academy, başlangıçtan ileri seviyeye kadar yapılandırıldığı için buradan başlayabilir veya başından başlayıp kendi hızında ilerleme yapabilirsin. Bu, 4 dersinin 2. dersidir.

“Bellek Yönetimi ve Çöp Toplama” dersi ne kadar sürer?

Çoğu CoddyKit dersi yaklaşık 5–10 dakika sürer. Her biri kısa ve etkileşimli olduğu için sabit ilerleme yaparsın ve web ile uygulama arasında tam olarak bıraktığın yerden devam edebilirsin.

Bu PHP Academy dersinde kod yazıp çalıştırabilir miyim?

Evet. Her PHP Academy dersi yerleşik bir kod editörü içerir, bu sayede tarayıcıda gerçek kod yazıp çalıştırabilir ve anlık yapay zeka geri bildirimi alırsın — yerel kurulum gerekli değildir.

Bu kursun tüm dersleri

  1. Zend Engine Nasıl Çalışır
  2. Bellek Yönetimi ve Çöp Toplama
  3. OPcache ve JIT Derlemesi
  4. C ile Temel PHP Uzantısı Yazma
← PHP Academy Sayfasına Dön