在composer個別庫中,會include配置文件,在調(diào)用時會重復(fù)include,并且不會釋放內(nèi)存,導(dǎo)致實際業(yè)務(wù)不復(fù)雜,但是循環(huán)之后內(nèi)存占滿進程被kill掉。分享一下這個過程,開發(fā)時要留意。
pinyin.php:
<?php
return [
'key1' => 'value1',
];
demo.php:
<?php
$list = []; // 假設(shè)這里有10萬條數(shù)據(jù)庫記錄要處理
foreach ($list as $item) {
$pinyin = include('pinyin.php');
unset($pinyin); // 變量內(nèi)存釋放了,但是include的那部分內(nèi)存無法釋放
}
這里就沒辦法主動釋放內(nèi)存,這種情況我在composer的拼音庫(overtrue/pinyin)遇到過一次。
<?php
use Overtrue\Pinyin\Pinyin;
foreach ($db_list as $item) {
$pinyin = Pinyin::sentence('你好,世界');
}
因為這里作者為了開發(fā)方便封裝了過程,但是在循環(huán)引用時候其內(nèi)部邏輯重復(fù)include,最終導(dǎo)致進程內(nèi)存占滿被kill掉
還有一種情況是:
PHPQuery庫,不停的向一個變量追加string,但是并未釋放,因為他使用的是靜態(tài)類,所以在用完之后要調(diào)用phpquery的釋放方法來釋放內(nèi)存。
jaeger/querylist 庫因為引用的是PHPQuery,所以也存在這個問題。
php為了高性能并不會每次釋放變量都會將內(nèi)存交還給操作系統(tǒng),而是留著下次復(fù)用。業(yè)務(wù)不用調(diào)用unset去主動釋放變量,因為臨時變量函數(shù)或方法運行完畢會自動釋放。
不斷include并不會導(dǎo)致內(nèi)存泄露問題。
Pinyin::sentence('你好,世界');本地經(jīng)過10次-1000次測試也沒出現(xiàn)內(nèi)存泄露問題。
PHPQuery庫因為沒有測試代碼并未測試。
另外webman有內(nèi)存檢測機制,如果某個進程內(nèi)存增長到一定程度會自動reload對應(yīng)進程釋放內(nèi)存,所以即使有內(nèi)存泄露也不用擔(dān)心。