遭遇php的in array低效能的解決辦法

2021-06-19 06:32:47 字數 2475 閱讀 9781

php

的效能一直在提高進步。然而,若是用的不好,稍微不注意,一不留神還是可能會踩到php內部實現方面挖的陷阱裡面。我在前段時間的乙個效能問題上就遭遇到了這樣的後果。%>_

事情是這樣子的,一位同事反饋我們的乙個介面每次返回需要5秒之久,我們一起review了**,「驚喜」的發現居然在迴圈(大約900次)中呼叫了乙個讀快取的操作,而這個快取的key並沒有改變,因此我們把這段**移到了迴圈外面,再測,介面返回時間降到了2秒,嗚呼!雖然提公升了1倍,但明顯不是我們能接受的結果!

出現效能問題的**量並不大,我們排除了io問題以後,寫了一段測試**,果然問題很快重現。

<?php 

$y="1800";

$x = array();

for($j=0;$j<2000;$j++)";

}for($i=0;$i<3000;$i++)

}?>

shell$ time /usr/local/php/bin/php test.php

real0m1.132s

user0m1.118s

sys0m0.015s

對的,我們用的就是字串型的數字,從快取拿出來就是這樣子的啦!所以這裡是特意轉成字串的(如果直接是數字,並不會出現這個問題 ,各位可以自行驗證)。可以看出時間耗掉了1秒,才3000次迴圈,後面的sys用時也注定我們用strace不會拿到什麼有效資訊。

shell$ strace -ttt -o *** /usr/local/php/bin/php test.php

shell$ less ***

我們只看到這兩次系統呼叫之間的延時非常大,卻並不知道幹了什麼?一籌莫展了,幸好,linux下的除錯利器除了strace還有ltrace(當然還有dtrace,ptrace,不在本文討論範圍了,略去)。

引用:strace用來 跟蹤乙個程序的系統呼叫或訊號產生的情況,而 ltrace用來 跟蹤程序呼叫庫函式的情況(via ibm developerworks)。

為了排除干擾因素,我們將$x直接賦值為array(「0″,」1″,」2″,……)的形式,避免過多的malloc呼叫影響結果。執行

shell$ ltrace -c /usr/local/php/bin/php  test.php

如圖2我們看到庫函式__strtol_internal的呼叫非常之頻繁,達到了94%,太誇張了,然後我又查了一下這個庫函式__strtol_internal是幹嘛的,原來是strtol的別名,簡單的說就是把字串轉換成長整形,可以猜測php引擎已經檢測到這是乙個字串型的數字,所以期望將他們轉換成長整型來比較,這個轉換過程中消耗了太多時間,我們再次執行:

shell$ ltrace -e "__strtol_internal" /usr/local/php/bin/php test.php

可以輕鬆抓到大量下圖這樣的呼叫,到此,問題找到了,in_array這種松比較,會將兩個字元型數字串先轉換為長整型再進行比較,卻不知效能就耗在這上面了。

知道了癥結所在,我們解決的辦法就很多了,最簡單的就是為in_array加第三個引數為true,即變為嚴格比較,同時還要比較型別,這樣避免了php自作聰明的轉換型別,跑起來果然快多了,**如下:

<?php 

$y="1800";

$x = array();

for($j=0;$j<2000;$j++)";

}for($i=0;$i<3000;$i++)

}?>

shell$ time /usr/local/php/bin/php test.php

real0m0.267s

user0m0.247s

sys0m0.020s

快了好多倍啊!!!可以看到sys耗時幾乎沒有太大變化。我們再次ltrace一把,還是要把$x直接賦值,排除malloc呼叫的干擾,因為我們實際應用中是從快取裡一次拉出來的,所以也不存在示例**中這樣的迴圈來申請記憶體的情況。

再次執行

shell$ ltrace -c /usr/local/php/bin/php  test.php

如下圖:

__ctype_tolower_loc占用了最多的時間!查了一下庫函式__ctype_tolower_loc是幹嘛的:簡單的理解是將字串轉換成小寫,那麼這說明in_array比較字串不區分大小寫嗎?其實這個函式呼叫已經和我們這個in_array感覺聯絡不大了,關於in_array的實現,還是去看看

php的原始碼

,大概理解的更為透徹了,好了,沒法往下說了,歡迎與我交流,寫的不對的地方請多多斧正。

本文講述了遭遇php的in_array低效能的解決辦法,希望本文能給讀者帶來靈感,幫助讀者解決疑問,感謝閱讀本文。更多有關php技術問題歡迎****:304224365,驗證碼:csl,不寫驗證不予通過。

PHP中in array 函式的坑

arr array name test male age 0 if in array h232 arr else結果輸出 yes 查詢手冊,手冊上也只是說in array 檢查資料中是否存在某個值。in array mixed needle,array haystack bool strict fa...

PHP中in array函式使用的問題與解決辦法

先介紹一下需求背景 發票方式 0 捐贈 不要問我為什麼,歷史原因 1 對中寄送 2 索取 3 電子發票 現在要對使用者提交的資料進行檢測 php auto links false if in array post invoice action array 0,1,2,3 這個時候出現乙個問題,如果壓...

PHP 中 in array 需要注意的一點

示例 先來看乙個小示例 needle 1abc haystack array 1,2,3 var dump in array needle,haystack 輸出為 true 解釋 根據官方文件函式 in array 的描述 boolin array mixed needle,array hayst...