事情是這樣子的,一位同事反饋我們的一個接口每次返回需要5秒之久,我們一起revi " /> 亚瑟天堂久久一区二区影院,狠狠色综合久久丁香婷婷,肉动漫无码无删减在线观看

天天躁日日躁狠狠躁AV麻豆-天天躁人人躁人人躁狂躁-天天澡夜夜澡人人澡-天天影视香色欲综合网-国产成人女人在线视频观看-国产成人女人视频在线观看

遭遇php的in_array低性能問題

php的性能一直在提高。然而,若是用的不恰當,或是一個不留神,還是可能會踩到php內部實現方面的坑的。我在前幾天的一個性能問題上就碰到了。

事情是這樣子的,一位同事反饋我們的一個接口每次返回需要5秒之久,我們一起review了代碼,“驚喜”的發現居然在循環(大約900次)中調用了一個讀緩存的操作,而這個緩存的key并沒有改變,因此我們把這段代碼移到了循環外面,再測,接口返回時間降到了2秒,嗚呼!雖然提升了1倍,但明顯不是我們能接受的結果!
出現性能問題的代碼量并不大,我們排除了IO問題以后,寫了一段測試代碼,果然問題很快重現。

復制代碼 代碼如下:
<?php
$y="1800";
$x = array();
for($j=0;$j<2000;$j++){
$x[]= "{$j}";
}

for($i=0;$i<3000;$i++){
if(in_array($y,$x)){
continue;
}
}
?>


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

real 0m1.132s
user 0m1.118s
sys 0m0.015s

對的,我們用的就是字符串型的數字,從緩存拿出來就是這樣子的啦!所以這里是特意轉成字符串的(如果直接是數字,并不會出現這個問題 ,各位可以自行驗證)。可以看出時間耗掉了1秒,才3000次循環,后面的sys用時也注定我們用strace不會拿到什么有效信息。

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

in_array.strace

我們只看到這兩次系統調用之間的延時非常大,卻并不知道干了什么?一籌莫展了,幸好,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

in_array.ltrace1


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

復制代碼 代碼如下:
shell$ ltrace -e "__strtol_internal" /usr/local/php/bin/php test.php


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

tu3

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

復制代碼 代碼如下:
<?php
$y="1800";
$x = array();
for($j=0;$j<2000;$j++){
        $x[]= "{$j}";
}

for($i=0;$i<3000;$i++){
        if(in_array($y,$x,true)){
                continue;
        }
}
?>

復制代碼 代碼如下:
shell$ time /usr/local/php/bin/php test.php

real 0m0.267s
user 0m0.247s
sys 0m0.020s


快了好多倍啊!!!可以看到sys耗時幾乎沒有太大變化。我們再次ltrace一把,還是要把$x直接賦值,排除malloc調用的干擾,因為我們實際應用中是從緩存里一次拉出來的,所以也不存在示例代碼中這樣的循環來申請內存的情況。
再次執行

復制代碼 代碼如下:
shell$ ltrace -c /usr/local/php/bin/php test.php


如下圖:

in_array.ltrace2

__ctype_tolower_loc占用了最多的時間!查了一下庫函數__ctype_tolower_loc是干嘛的:簡單的理解是將字符串轉換成小寫,那么這說明in_array比較字符串不區分大小寫嗎?其實這個函數調用已經和我們這個in_array感覺聯系不大了,關于in_array的實現,還是去看看php的源碼,大概理解的更為透徹了,好了,沒法往下說了,歡迎與我交流,寫的不對的地方請多多斧正。

―――――――2013.08.29分割線――――――――――

晚上又翻了以下php 5.4.10的源碼,對in_array的興趣真大啊,哈哈,位于./ext/standard/array.c的第1248行,可以看到他調用了php_search_array函數,下面的array_serach也是調的這個,只是最后一個參數不同!經過一番跟蹤,在in_array松比較的情況下,他最終調用的函數 zendi_smart_strcmp(果然是個“聰明”函數)進行比較,位于./Zend/zend_operators.c,我們用ltrace抓到的大量轉換成整型的操作就是那個is_numeric_string_ex的行為。

%E5%B1%8F%E5%B9%95%E5%BF%AB%E7%85%A7-2013-08-29-23.13.20

函數is_numeric_string_ex是在./Zend/zend_operators.h中定義的,在前面進行了一堆的判斷和轉換之后,在232行調用了strtol,就是我們在文章中提到的系統函數了,將字符串轉換成長整型,有圖有真相

zend_operators-is_num

php技術遭遇php的in_array低性能問題,轉載需保留來源!

鄭重聲明:本文版權歸原作者所有,轉載文章僅為傳播更多信息之目的,如作者信息標記有誤,請第一時間聯系我們修改或刪除,多謝。

主站蜘蛛池模板: 久久免费看少妇高潮A片特爽 | 久久全国免费久久青青小草 | 97亚洲狠狠色综合久久久久 | 亚洲乱码中文字幕久久孕妇黑人 | 成人在线视频免费观看 | 日韩一本道无码v | 伊人AV一区二区三区夜色撩人 | qvod欧美电影| 高h 大尺度纯肉 np快穿 | 草草久久久无码国产专区全集观看 | 国产午夜精品一区二区三区 | 蜜芽视频在线观看视频免费播放 | 欧美日韩一区在线观看 | 野花日本韩国视频免费高清观看 | 无码中文字幕av免费放 | 男人脱女人衣服吃奶视频 | 久久精品亚洲视频 | 孕妇bbwbbwbbwbbw超清 | 在线观看国产区 | 日日踫夜夜爽无码久久 | 亚洲人女同志video | 日本熟妇乱妇熟色A片蜜桃 日本熟妇多毛XXXXX视频 | 久久精品国产欧美 | 色午夜日本高清视频www | 亚洲精品国产高清不卡在线 | 色柚视频网站ww色 | 四房色播手机版 | 国产三级在线精品男人的天堂 | 欧美熟妇VIVOE精品 | 51久久成人国产精品麻豆 | 亚洲日本欧美产综合在线 | 中文字幕不卡在线高清 | 国产精品嫩草影视在线观看 | 2020美女视频黄频大全视频 | 国产成人无码免费精品果冻传媒 | 欧美精品99久久久啪啪 | 色丁香婷婷综合缴情综 | 曰本xxⅹ孕妇性xxx | 国内精品人妻无码久久久影院蜜桃 | 国产内射AV徐夜夜 | 暖暖免费 高清 日本社区中文 |