PHP程式應該減少brk呼叫,否則效能會受影響
昨天工作上遇到一個非常有意思的問題,特此分享給大家,也給大家提個醒,在 PHP 程式中儘量減少系統呼叫。在我們系統中有一個 cron 指令碼,完成的主要工作就是從 memcached 中獲取資料,然後同步到資料庫中。平時執行的好好的,但昨天卻遇到了問題,唯一的變化就是本次任務從 memcached 中獲取的資料非常多,總共有 100 萬條記錄。話不多少,先上虛擬碼:
//共100萬個memcached資料
$tnum = 1000000;
//共1萬個key,每個100條memcached資料
$knum = ceil($tnum/100);
$mem->connect("localhost", "11211");
for ($i = 1; $i <= $knum; $i++)
$k[] = $mckey."_".$i;
# 一次性從 memcached 中獲取到資料
$emailmc = $mem->get($k);
$email = array();
foreach ($emailmc as $v) {
$s = unserialize($v);
$s = explode(",", $s);
# 合併陣列
$email = array_merge($email, $s);
}
# 一次性匯入到 mecached 中
importdb($email);
彪悍的 memcached
由於指令碼本次執行對業務非常重要,我一直在監視,發現執行了半個小時也沒有結束,開始我思索是不是memcached一次性獲取太多了,導致memcached查詢遇到問題了?
使用 wireshark 和 strace 抓取了相關資料,發現獲取 memcached 非常快,幾秒鐘就返回了,贊一下 memcached 效能。
brk
接下去繼續分析,strace 出現了滿屏的 brk 系統呼叫,如下:
$ strace -p 27429 -T
brk(0x6d4c000) = 0x6d4c000 <0.000007>
brk(0x6d8c000) = 0x6d8c000 <0.000007>
brk(0x6dcc000) = 0x6dcc000 <0.000007>
brk(0x6e0c000) = 0x6e0c000 <0.000007>
brk(0x6e4c000) = 0x6e4c000 <0.000006>
雖然每次的 brk 呼叫響應並不慢,但次數太多了,那麼到底什麼是 brk?
brk, sbrk - change data segment size
也就是說 brk 在不斷的改變某個指標物件的內容,按照上面的虛擬碼,email 變數的記憶體越來越大,執行速度也越來越慢,而且執行到一定時間,php出現了記憶體不夠的錯誤,我做了相關調整:
ini_set('memory_limit', '500M');
$email = array();
foreach ($emailmc as $v) {
$s = unserialize($v);
$s = explode(",", $s);
$email = array_merge($email, $s);
echo memory_get_usage();
}
memory_limit 是限制 php 程式能夠使用的記憶體大小,通過 memory_get_usage 函式發現,記憶體使用越來越大,雖然最後程式碼也能夠執行,但卻要花費至少半個小時。
call_user_func_array
對於 php 程式來說,應用程式碼是涉及不到 brk 呼叫的,但如果能夠減少呼叫,程式執行時間肯定會提高很多,現在的目的就是減少 array_merge 操作,我先修改了部分程式碼,分批次從 memcached 中獲取:
//共100萬個memcached資料
$tnum = 1000000;
//共1萬個key,每個100條memcached資料
$knum = ceil($tnum/100);
$mem->connect("localhost", "11211");
$j = 1;
for ($i = 1; $i <= $knum; $i++) {
$k[] = $mckey."_".$i;
if (count($k)>100) {
$emailmc = $mem->get($k);
foreach ($emailmc as $v) {
$s = unserialize($v);
$s = explode(",", $s);
$emailarr[$j] = $s;
$j++;
}
$k = array();
}
}
# 要執行 100 次
for ($i=1;$i<=$j;$i++) {
$email = array_merge($email,$emailarr[$j]);
}
importdb($email);
我分批次從 memcached 中獲取資料,然後儲存到 $emailarr 陣列變數中,如果再迴圈 array_merge,雖然速度快了一些,但仍然要100次,執行速度仍然非常慢。
我思索是不是在 php 內部能夠將 $emailarr 陣列一次性合併呢?雖然有思路,但不知道具體如何操作,諮詢了 php 大牛,提出了 call_user_func_array 函式。
修改如下:
$email = call_user_func_array('array_merge', $email);
importdb($email);
程式碼居然2秒就返回了,避免了由 php 應用程式碼進行大量的 array_merge 合併,由 php 內部一次性完成了 array_merge。
可能有些同學說,為啥你不能從 memcached 中獲取一部分資料就匯入到資料庫中呢?主要原因是後面程式碼太複雜,怕出現新的問題,所以本次的改造思路就是一次性獲取到 $email 變數對應的資料。
總結:php 應用程式碼不會和系統呼叫直接產生聯絡,可系統呼叫非常昂貴,應該減少呼叫,所以在開發的時候,應該想象下php程式碼的執行邏輯,從而提升效能。
相關文章
- 怎麼減少行鎖對效能的影響?
- 總公司投標,會不會受分公司的影響?
- 減少程式碼中該死的 if else 巢狀巢狀
- 減少該死的 if else 巢狀巢狀
- padding會影響到元素的大小,那不想讓它影響到元素的寬度應該怎麼辦?padding
- /etc/hosts.deny會被誰呼叫,又會影響誰呢?
- GSMA報告:移動技術對減少碳排放量的影響
- 哪些公司受華為影響最大?
- 貨幣政策受什麼影響?
- 程式設計師應該少做些"工作" - johnwhiles程式設計師While
- Win11舊版將會受到時間影響!微軟:請使用者們立即升級否則將會被重啟微軟
- 你知道CPU結構也會影響Redis效能嗎?Redis
- PHP中什麼是垃圾回收?對效能有什麼影響PHP
- php響應PHP
- 分支對程式碼效能的影響和優化優化
- 史丹佛大學:研究發現女性受視訊會議影響更大
- AMoneyDJ:2024年ASML的訂單受臺積電縮減資本支出影響 同比恐遭削減逾40%ASM
- 哪本書是對程式設計師最有影響且最應該讀的?程式設計師
- Qt5 GUI 開發的應用易受遠端程式碼執行漏洞的影響QTGUI
- 受盜版影響最大的行業是?行業
- 注意!SQLite被曝漏洞,Chrome 火狐等數千應用或受影響SQLiteChrome
- 小心在 Blade 模板裡的大量 include 將會影響效能
- 哪些方面會影響伺服器資料庫效能伺服器資料庫
- 恆訊科技科普:減少伺服器響應時間的10種方法伺服器
- Booking:過半遊客做旅遊決策時會受評論影響
- PHP 基金會:2023 年影響力和透明度報告PHP
- 少曬太陽有利減肥?Cell 子刊研究發現季節和光照時間不同會影響人體代謝健康
- 區塊鏈受ChatGPT等強人工智慧影響會帶來哪些變革區塊鏈ChatGPT人工智慧
- 受新冠疫情影響,Unity宣佈Unite 2020大會線下活動取消Unity
- YouGov:44%的美國人不會受企業對LGBTQ的態度影響Go
- 首爾國立大學:研究發現睡多睡少都會影響健康
- 10月受疫情影響新車銷量走低,豪華車繼續受益購置稅減半政策
- 影響mysql效能的因素都有哪些MySql
- 影響HTTP效能的常見因素HTTP
- Java UUID生成的效能影響 – fastthreadJavaUIASTthread
- 影響MySQL效能的硬體因MySql
- 影響MySQL效能的硬體因素MySql
- 突發!阿里雲崩了:全線產品受影響阿里