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程式碼的執行邏輯,從而提升效能。
相關文章
- 哪些因素影響Java呼叫的效能?Java
- 使用rownum減少函式呼叫函式
- 減少程式碼中該死的 if else 巢狀巢狀
- 減少.NET應用程式記憶體佔用的一則實踐記憶體
- 高效能web建站規則(儘量減少http請求)WebHTTP
- 修改欄位長度應用會影響到生產效能
- 減少該死的 if else 巢狀巢狀
- Java Web效能優化之一:減少DAO層的呼叫次數JavaWeb優化
- GSMA報告:移動技術對減少碳排放量的影響
- 貨幣政策受什麼影響?
- notification後,程式應該如何響應
- GHOST漏洞可能影響WordPress和PHP應用PHP
- 使用MVVM減少控制器程式碼實戰(減少56%)MVVM
- Win11舊版將會受到時間影響!微軟:請使用者們立即升級否則將會被重啟微軟
- 通過減少動態派送提升效能
- Nginx接收的host值會影響alias的規則匹配Nginx
- 你知道CPU結構也會影響Redis效能嗎?Redis
- 影響Oracle效能會有很多方面的原因Oracle
- 受盜版影響最大的行業是?行業
- 恆訊科技科普:減少伺服器響應時間的10種方法伺服器
- 哪些方面會影響伺服器資料庫效能伺服器資料庫
- 執行緒安全的單態類會影響效能麼?執行緒
- 程式設計師應該少做些"工作" - johnwhiles程式設計師While
- 注意!SQLite被曝漏洞,Chrome 火狐等數千應用或受影響SQLiteChrome
- 分支對程式碼效能的影響和優化優化
- try catch 對程式碼執行的效能影響
- PHP中什麼是垃圾回收?對效能有什麼影響PHP
- AMoneyDJ:2024年ASML的訂單受臺積電縮減資本支出影響 同比恐遭削減逾40%ASM
- 關於在javabean裡的方法,這樣做會不會影響效能JavaBean
- 哪本書是對程式設計師最有影響且最應該讀的?程式設計師
- 為什麼程式設計師應該少寫程式碼程式設計師
- Qt5 GUI 開發的應用易受遠端程式碼執行漏洞的影響QTGUI
- php響應PHP
- 關於多個執行緒同時呼叫單例模式的物件,該物件中方法的區域性變數是否會受多個執行緒的影響執行緒單例模式物件變數
- 通過減少記憶體使用改善.NET效能記憶體
- 新會計準則實施對財務軟體的影響
- YouGov:44%的美國人不會受企業對LGBTQ的態度影響Go
- 區塊鏈受ChatGPT等強人工智慧影響會帶來哪些變革區塊鏈ChatGPT人工智慧