(Tutorial yang disyorkan: Tutorial video PHP)
Setiap php Pembolehubah disimpan dalam bekas berubah yang dipanggil zval.
Bekas pembolehubah zval, selain mengandungi jenis dan nilai pembolehubah, ia juga termasuk dua bait maklumat tambahan.
Yang pertama ialah is_ref, iaitu nilai bool yang digunakan untuk mengenal pasti sama ada pembolehubah ini tergolong dalam koleksi rujukan. Melalui bait ini, enjin PHP boleh membezakan pembolehubah biasa daripada pembolehubah rujukan Memandangkan PHP membenarkan pengguna menggunakan rujukan tersuai dengan menggunakan &, terdapat juga mekanisme pengiraan rujukan dalaman dalam bekas pembolehubah zval untuk mengoptimumkan penggunaan memori.
Bait tambahan kedua ialah pengiraan semula, yang mewakili bilangan pembolehubah yang menunjuk ke bekas pembolehubah zval ini.
Semua simbol wujud dalam jadual simbol, di mana setiap simbol mempunyai skop, begitu juga dengan skrip utama (contohnya: skrip yang diminta melalui penyemak imbas) dan setiap fungsi atau kaedah.
Apabila pembolehubah diberikan nilai malar, bekas pembolehubah zval akan dijana
Jika Xdebug dipasang, anda boleh menggunakan xdebug_debug_zval() Lihat kedua-dua ini
<?php $a = "new string"; xdebug_debug_zval('a'); //结果 a: (refcount=1, is_ref=0)='new string'
Menetapkan satu pembolehubah kepada pembolehubah lain akan meningkatkan bilangan rujukan
<?php $a = "new string"; $b = $a; xdebug_debug_zval( 'a' ); //结果 a: (refcount=2, is_ref=0)='new string'
Gunakan unset() untuk mengurangkan bilangan rujukan
Bekas pembolehubah yang mengandungi jenis dan nilai akan dipadamkan daripada memori
<?php $a = "new string"; $c = $b = $a; xdebug_debug_zval( 'a' ); unset( $b, $c ); xdebug_debug_zval( 'a' ); //结果 a: (refcount=3, is_ref=0)='new string' a: (refcount=1, is_ref=0)='new string'
<?php $a = array( 'meaning' => 'life', 'number' => 42 ); xdebug_debug_zval( 'a' ); //结果 a: (refcount=1, is_ref=0)=array ( 'meaning' => (refcount=1, is_ref=0)='life', 'number' => (refcount=1, is_ref=0)=42 )
Tambahkan elemen sedia ada pada tatasusunan
<?php $a = array( 'meaning' => 'life', 'number' => 42 ); $a['life'] = $a['meaning']; xdebug_debug_zval( 'a' ); //结果 a: (refcount=1, is_ref=0)=array ( 'meaning' => (refcount=2, is_ref=0)='life', 'number' => (refcount=1, is_ref=0)=42, 'life' => (refcount=2, is_ref=0)='life' )
Memadamkan elemen dalam tatasusunan
adalah serupa dengan memadamkan pembolehubah daripada skop.
Selepas pemadaman, bekas yang menempatkan elemen dalam tatasusunan "refcount " nilai menurun
<?php $a = array( 'meaning' => 'life', 'number' => 42 ); $a['life'] = $a['meaning']; unset( $a['meaning'], $a['number'] ); xdebug_debug_zval( 'a' ); //结果 a: (refcount=1, is_ref=0)=array ( 'life' => (refcount=1, is_ref=0)='life' )
Apabila kita menambah tatasusunan itu sendiri sebagai elemen tatasusunan ini, perkara menjadi menarik
Sama seperti di atas, Panggilan tidak ditetapkan pada pembolehubah akan memadamkan simbol, dan bilangan rujukan dalam bekas pembolehubah yang ditunjukkannya juga akan dikurangkan sebanyak 1
<?php $a = array( 'one' ); $a[] = &$a; xdebug_debug_zval( 'a' ); //结果 a: (refcount=2, is_ref=1)=array ( 0 => (refcount=1, is_ref=0)='one', 1 => (refcount=2, is_ref=1)=... )
Walaupun tiada lagi sebarang simbol dalam skop yang menunjuk kepada struktur ini (iaitu, bekas berubah), memandangkan elemen tatasusunan "1" masih menunjuk kepada tatasusunan itu sendiri, bekas ini tidak boleh dikosongkan .
Oleh kerana tiada simbol lain yang menunjuk kepadanya, pengguna tidak mempunyai cara untuk mengosongkan struktur ini, mengakibatkan kebocoran memori.
Nasib baik, PHP akan mengosongkan struktur data ini pada penghujung pelaksanaan skrip, tetapi sebelum PHP mengosongkannya, ia akan menggunakan banyak memori.
Tidak mengapa jika situasi di atas berlaku hanya sekali atau dua kali, tetapi jika kebocoran ingatan berlaku beribu-ribu atau bahkan ratusan ribu kali, ini jelas menjadi masalah besar
Mekanisme memori pengiraan rujukan yang digunakan oleh PHP pada masa lalu tidak dapat menangani kebocoran memori rujukan bulat
Tetapi dalam PHP 5.3.0, algoritma penyegerakan digunakan untuk menangani masalah kebocoran memori ini
Jika jumlah rujukan ditambah, ia akan terus digunakan dan sudah tentu tidak lagi di dalam sampah.
Jika kiraan rujukan berkurangan kepada sifar, bekas berubah-ubah akan dikosongkan
Maksudnya, kitaran sampah hanya akan berlaku apabila kiraan rujukan berkurangan kepada nilai bukan sifar
Dalam kitaran sampah, ketahui bahagian mana yang merupakan sampah dengan menyemak sama ada kiraan rujukan dikurangkan sebanyak 1 dan menyemak bekas pembolehubah yang mempunyai rujukan sifar
Untuk mengelakkan daripada perlu menyemak semua kiraan rujukan, kemungkinan kitaran sampah dikurangkan
Algoritma ini meletakkan semua kemungkinan akar (akar yang mungkin adalah bekas pembolehubah zval) dalam penimbal akar (ditandai dengan ungu, dipanggil sampah yang disyaki), supaya setiap kemungkinan sampah dapat dipastikan pada masa yang sama Akar (kemungkinan akar sampah) muncul sekali sahaja dalam penimbal. Pengumpulan sampah dilakukan pada semua bekas berubah yang berbeza dalam penimbal hanya apabila penimbal akar penuh. Lihat langkah A dalam imej di atas.
Dalam langkah B, simulasi pemadaman setiap pembolehubah ungu. Apabila mensimulasikan pemadaman, kiraan rujukan pembolehubah biasa yang tidak berwarna ungu mungkin dikurangkan sebanyak "1". Setiap pembolehubah hanya boleh disimulasikan dipadam sekali, dan ditandakan dengan kelabu selepas pemadaman simulasi
Dalam langkah C, simulasi memulihkan setiap pembolehubah ungu. Pemulihan adalah bersyarat Apabila kiraan rujukan pembolehubah lebih besar daripada 0, pemulihan simulasi dilakukan. Begitu juga, setiap pembolehubah hanya boleh dipulihkan sekali Selepas pemulihan, ia ditandakan sebagai hitam Pada asasnya adalah operasi songsang bagi langkah B. Dengan cara ini, longgokan nod biru yang tidak boleh dipulihkan ialah nod biru yang harus dipadamkan dalam langkah D dan benar-benar padamkannya
Terdapat dua yang utama. Domain mempunyai kesan ke atas prestasi
Yang pertama ialah penjimatan ruang memori
Yang lain ialah peningkatan dalam masa yang diperlukan untuk mekanisme kutipan sampah melepaskan memori yang bocor
Mekanisme kutipan sampah dalam PHP hanya akan meningkatkan penggunaan masa apabila algoritma kitar semula sebenarnya berjalan. Tetapi dalam skrip biasa (lebih kecil) seharusnya tiada kesan prestasi sama sekali.
Walau bagaimanapun, dalam kes skrip biasa dengan mekanisme kitar semula berjalan, penjimatan memori akan membolehkan lebih banyak skrip sedemikian dijalankan pada pelayan anda pada masa yang sama. Kerana jumlah memori yang digunakan belum mencapai had atas.
Faedah ini amat ketara dalam skrip jangka panjang, seperti suite ujian jangka panjang atau skrip daemon.
(Tutorial disyorkan: Tutorial video PHP)
Atas ialah kandungan terperinci Ketahui lebih lanjut tentang mekanisme pengumpulan sampah PHP. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!