首頁 後端開發 php教程 垃圾回收 PHP垃圾回收機制簡單說明

垃圾回收 PHP垃圾回收機制簡單說明

Jul 29, 2016 am 08:43 AM
垃圾回收

雖然自己也是PHP的學習者,但之前還真沒怎麼了解PHP內部的垃圾回收流程,只是在我們的程式碼中用了unset,null,mysql_close,__destruct等等一些函數去釋放物件防止記憶體溢出而已,所以上網GG下,找到了以下一些說明,作下記錄「PHP可以自動進行記憶體管理,清除不再需要的物件。PHP使用了引用計數(reference counting)這種單純的垃圾回收(garbage collection)機制。每個對像都內含一個引用計數器,每個reference連接到對象,計數器加1。不再需要使用這個對象,釋放其所佔的記憶體空間。」
眾所周知, PHP 引擎本身是用C 寫的,提到C 不能不提的就是GC(垃圾回收).透過PHP 手冊我們了解到, PHP 引擎會自動進行GC 動作.那麼我們不禁要問,到底它是怎麼回收的, & 引用操作是不是指針, unset() 了一個變量時它是不是真的被回收了呢?這些看似手冊有提及的問題,如果仔細分析會發現,遠沒有那麼簡單泛泛.也許有人會跳出來說:看PHP 源碼不就知道了.是的,等你通讀了PHP 源碼後這個問題肯定不在話下了,然本篇要僅從PHP 本身來分析這些看似平常卻被忽略的小細節,當然了,其中難免水平所限,有所疏漏,熱烈歡迎廣大phper 來共同討論.
首先咱先看到例子,最簡單不過的執行流程了:
Example 1: gc.php
error_reporting(E_ALL);
$a = 'I am test.';
$b = & $a;
echo $b ." ";
?>
不用說% php -f gc.php 輸出結果非常明了:
hy0kl% php -f gc.php
I am test.
好,下一個:
Example 2:
error_reporting(E_ALL);
$a = 'I am test.';
$b = & $a;
$b = ' I will change?';
echo $a ." ";
echo $b ." ";
?>
執行結果依然很明顯:
hy0kl% php -f gc. php
I will change?
I will change?
君請看:
Example 3:
error_reporting(E_ALL);
$a = 'I am test.';
$b = & $a;
unset($a);
echo $a ." ";
echo $b ." ";
?>
是不是得想一下呢?
hy0kl% php -f gc.php
Notice: Undefined variable: a in /usr/local/www/apache22/data/test/gc.php on line 8
I am test.
有點迷糊了嗎?
君再看:
Example 4:
error_reporting(E_ALL);
$a = '🎜>error_reporting(E_ALL);
$a = ' I am test.';
$b = & $a;
unset($b);
echo $a ." ";
echo $b ." ";
?>
其實如果Example 3 理解了,這個與之異曲同工.
hy0kl% php -f gc.php
I am test.
Notice: Undefined variable: b in /usr/local/www/www apache22/data/test/gc.php on line 9
君且看:
Example 5:
error_reporting(E_ALL);
$a = 'I am test. ';
$b = & $a;
$a = null;
echo '$a = '. $a ." ";
echo '$b = '. $b ." ";
?>
猛的第一感覺是什麼樣的?
hy0kl% php -f gc.php
$a =
$b =
沒錯,這就是輸出結果,對PHP GC 已有深入理解的phper 不會覺得有什麼奇怪,說實話,當我第一次運行這段程式碼時很意外,卻讓我對PHP GC 有更深刻的理解了.那麼下面與之同工的例子自然好理解了.
Example 6:
error_reporting(E_ALL);
$a = 'I am test.';
$b = & $a;
$b = null;
echo '$a = '. $a ." ";
echo '$b = '. $b ." ";
?>
OK,如果上面的例子的結果對看官來說無任何細節可言,那您可關閉本窗口了,歡迎有空再來!
下面我們來詳細分析GC 與引用.
1. 所有例子中,創建了一個變數,這個過程通俗一點講:是在內存中開闢了一塊空間,在裡面存放了一個字符串I am test. . PHP 內部有個符號表,用來記錄各塊記憶體參考計數,那麼此時會將這塊記憶體的引用計數加1,並且用一個名為$a 的標籤(變數)指向這塊記憶體,方便依標籤名來操作記憶體.
2. 對變量$a 進行& 操作,我的理解是找到$a 所指向的內存,並為$b 建立同樣的一引用指向,並將存放字符串I am test. 的內存塊在符號表中引用計數加1.換言之,我們的腳本執行到這一行的時候,存放字符串I am test. 的那塊內存被引用了兩次.這裡要強調的是, & 操作是建立了引用指向,而不是指針, PHP 沒有指針的概念!同時有人提出說類似於UNIX 的文件軟鏈接.可以在一定程度上這麼理解: 存放字符I am test. 的那塊內存是我們的一個真實的文件,而變量$a 與$b 是針對真實檔案建立的軟連結,但它們指向的是同一個真實檔案. So, 我們看到,在Example 2 中給$b 賦值的同時, $a 的值也跟著變化了.與透過某一軟鏈操作了檔案類似.
3. 在Example 3 與4 中,進行了unset() 操作.根據實際的執行結果,可以看出: unset() 只是斷開這個變數對它原先指向的記憶體的引用,使變數本身成為沒有定義過空引用,所在調用時發出了Notice ,並且使那塊內存在符號表中引用計數減1,並沒有影響到其他指向這塊內存的變量.換言之,只有當一塊內存在符號表中的引用計數為0 時, PHP 引擎才會將這塊記憶體回收.
PHP 手冊
4.0.0 unset() became an expression. (In PHP 3, unset() would always return 1 ).
這代表什麼?
看看下面的程式碼與其結果:
error_reporting(E_ALL);
$a = 'I am test.';
$b = & $a;
unset($a);
unset($a);
unset($a);
echo '$a = '. $a ." " ;
echo '$b = '. $b ." ";
?>
hy0kl% php -f gc.php Notice: Undefined variable: a in /usr/local/www/apache22/data/test/gc.php on line 10
$a =
$b = I am test.
第一次unset( ) 的操作已經斷開了指向,所以後繼的操作不會對符號表的任何內存的引用記數造成影響了.
4. 通過Example 5 & 6 可以明確無誤得出: 賦值null 操作是相當猛的,它會直接將變數所指向的內存在符號號中的引用計數置0, 那這塊內存自然被引擎回收了,至於何時被再次利用不得而知,有可能馬上被用作存儲別的資訊,也許再也沒有使用過.但是無論如何,原來所有指向那塊內存變量都將無法再操作被回收的內存了,任何試圖調用它的變量都將返回null.
error_reporting(E_ALL);
$a = 'I am test.';
$b = & $a;
$b = null;
echo '$a = '. $a ." ";
echo '$b = '. $b ." ";
if (null === $a)
{
echo '$a is null.';
} else
{
echo 'The type of $a is unknown.';
}
?>
hy0kl% php -f gc.php
$a =
hy0kl% php -f gc.php
$a =
hy0kl% php -f gc.php

$a =

hy0kl% php -f gc.php

$a =

hy0kl% php -f gc.php $a = hy0kl% php -f gc.php $a = hy0kl% php -f gc.php $a = hy0kl%。 >$b = $a is null. 綜上所述,充分說明了為什麼我們在看開源產品源碼的時候,常看到一些比較大的臨時變量,或使用完不再調用的重用資訊都會被集中或顯示的賦值為null 了.它相當於UNIX 中直接將真實文件幹掉了,所有指向它的軟鏈接自然成了空鏈了. 以上就介紹了垃圾回收 PHP垃圾回收機制簡單說明,包括了垃圾回收方面的內容,希望對PHP教程有興趣的朋友有所幫助。
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

C#開發中如何避免記憶體洩漏 C#開發中如何避免記憶體洩漏 Oct 08, 2023 am 09:36 AM

C#開發中如何避免記憶體洩漏,需要具體程式碼範例記憶體洩漏是軟體開發過程中常見的問題之一,特別是在使用C#語言進行開發時。記憶體洩漏會導致應用程式佔用越來越多的記憶體空間,最終導致程式運行緩慢甚至崩潰。為了避免記憶體洩漏,我們需要注意一些常見的問題並採取相應措施。及時釋放資源在C#中,使用完資源後一定要及時釋放它們,尤其是涉及文件操作、資料庫連線和網路請求等資源。可以

C#常見的記憶體管理問題及解決方法 C#常見的記憶體管理問題及解決方法 Oct 11, 2023 am 09:21 AM

C#中常見的記憶體管理問題及解決方法,需要具體程式碼範例在C#開發中,記憶體管理是一個重要的問題,不正確的記憶體管理可能會導致記憶體洩漏和效能問題。本文將向讀者介紹C#中常見的記憶體管理問題,並提供解決方法,並給出具體的程式碼範例。希望能幫助讀者更理解和掌握記憶體管理技術。垃圾回收器不及時釋放資源C#中的垃圾回收器(GarbageCollector)負責自動釋放不再使

PHP中的記憶體管理與垃圾回收技術 PHP中的記憶體管理與垃圾回收技術 May 11, 2023 am 08:33 AM

PHP作為一種廣泛使用的腳本語言,為了在運行時確保高效執行,具有獨特的記憶體管理和垃圾回收技術。本文將簡單介紹PHP記憶體管理和垃圾回收的原理與實作方式。一、PHP記憶體管理的原理PHP的記憶體管理採用了引用計數(ReferenceCounting)來實現,這種方式是現代化的語言中比較常見的記憶體管理方式之一。當一個變數被使用時,PHP會為其分配一段內存,並將這段內

Java 函數中記憶體管理技術與安全性的關係是什麼? Java 函數中記憶體管理技術與安全性的關係是什麼? May 02, 2024 pm 01:06 PM

Java中的記憶體管理涉及自動記憶體管理,使用垃圾回收和引用計數來分配、使用和回收記憶體。有效的記憶體管理對於安全性至關重要,因為它可以防止緩衝區溢位、野指標和記憶體洩漏,從而提高程式的安全性。例如,透過正確釋放不再需要的對象,可以避免記憶體洩漏,從而提高程式效能並防止崩潰。

Python開發中遇到的記憶體管理問題及解決方案 Python開發中遇到的記憶體管理問題及解決方案 Oct 09, 2023 pm 09:36 PM

Python開發中遇到的記憶體管理問題及解決方案摘要:在Python開發過程中,記憶體管理是一個重要的問題。本文將討論一些常見的記憶體管理問題,並介紹相應的解決方案,包括引用計數、垃圾回收機制、記憶體分配、記憶體洩漏等。並提供了具體的程式碼範例來幫助讀者更好地理解和應對這些問題。引用計數Python使用引用計數來管理記憶體。引用計數是一種簡單而有效率的記憶體管理方式,它記錄每

Python底層技術解析:如何實作垃圾回收機制 Python底層技術解析:如何實作垃圾回收機制 Nov 08, 2023 pm 07:28 PM

Python底層技術解析:如何實現垃圾回收機制,需要具體程式碼範例引言:Python作為一種高階程式語言在開發中極為方便且靈活,但是其底層實作卻是相當複雜的。本文將聚焦在Python的垃圾回收機制,包括垃圾回收的原理、演算法以及具體的實作程式碼範例。希望透過本文對Python垃圾回收機制的解析,讀者能夠更深入了解Python底層技術。一、垃圾回收原理首先,我

如何使用Go語言進行記憶體優化與垃圾回收 如何使用Go語言進行記憶體優化與垃圾回收 Sep 29, 2023 pm 05:37 PM

如何使用Go語言進行內存優化與垃圾回收Go語言作為一門高效能、並發、效率高的程式語言,對於內存的優化和垃圾回收有著很好的支援。在開發Go程式時,合理地管理和最佳化記憶體使用,能夠提高程式的效能和可靠性。使用適當的資料結構在Go語言中,選擇合適的資料結構對記憶體的使用有很大的影響。例如,對於需要頻繁新增和刪除元素的集合,使用鍊錶代替陣列可以減少記憶體碎片的產生。另外,

Java開發中如何解決堆疊記憶體空間不足問題 Java開發中如何解決堆疊記憶體空間不足問題 Jun 29, 2023 am 11:11 AM

Java作為一門廣泛使用的程式語言,由於其自動記憶體管理機制,特別是垃圾回收機制的存在,使得開發人員無需過多關注記憶體的分配和釋放。然而,在一些特殊情況下,例如處理大數據或執行複雜的演算法時,Java程式可能會遇到堆疊記憶體空間不足的問題。本文將討論如何解決這個問題。一、了解堆記憶體空間堆記憶體是Java虛擬機器(JVM)中指派給Java程式執行時間所使用的記憶體空間。它存儲了

See all articles