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