PHP的性能一直在提高。然而,若是用的不恰当,或是一个不留神,还是可能会踩到PHP内部实现方面的坑的。我在前几天的一个性能问题上就碰到了。
事情是这样子的,一位同事反馈我们的一个接口每次返回需要5秒之久,我们一起review了代码,“惊喜”的发现居然在循环(大约900次)中调用了一个读缓存的操作,而这个缓存的key并没有改变,因此我们把这段代码移到了循环外面,再测,接口返回时间降到了2秒,呜呼!虽然提升了1倍,但明显不是我们能接受的结果!
出现性能问题的代码量并不大,我们排除了IO问题以后,写了一段测试代码,果然问题很快重现。
复制代码 代码如下:
$y="1800";
$x = array();
for($j=0;$j$x[]= "{$j}";
}
for($i=0;$iif(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
我们只看到这两次系统调用之间的延时非常大,却并不知道干了什么?一筹莫展了,幸好,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自作聪明的转换类型,跑起来果然快多了,代码如下:
复制代码 代码如下:
$y="1800";
$x = array();
for($j=0;$j $x[]= "{$j}";
}
for($i=0;$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
如下图:
__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的行为。
函数is_numeric_string_ex是在./Zend/zend_operators.h中定义的,在前面进行了一堆的判断和转换之后,在232行调用了strtol,就是我们在文章中提到的系统函数了,将字符串转换成长整型,有图有真相

PHP主要是過程式編程,但也支持面向對象編程(OOP);Python支持多種範式,包括OOP、函數式和過程式編程。 PHP適合web開發,Python適用於多種應用,如數據分析和機器學習。

PHP起源於1994年,由RasmusLerdorf開發,最初用於跟踪網站訪問者,逐漸演變為服務器端腳本語言,廣泛應用於網頁開發。 Python由GuidovanRossum於1980年代末開發,1991年首次發布,強調代碼可讀性和簡潔性,適用於科學計算、數據分析等領域。

PHP適合網頁開發和快速原型開發,Python適用於數據科學和機器學習。 1.PHP用於動態網頁開發,語法簡單,適合快速開發。 2.Python語法簡潔,適用於多領域,庫生態系統強大。

PHP在現代化進程中仍然重要,因為它支持大量網站和應用,並通過框架適應開發需求。 1.PHP7提升了性能並引入了新功能。 2.現代框架如Laravel、Symfony和CodeIgniter簡化開發,提高代碼質量。 3.性能優化和最佳實踐進一步提升應用效率。

PHPhassignificantlyimpactedwebdevelopmentandextendsbeyondit.1)ItpowersmajorplatformslikeWordPressandexcelsindatabaseinteractions.2)PHP'sadaptabilityallowsittoscaleforlargeapplicationsusingframeworkslikeLaravel.3)Beyondweb,PHPisusedincommand-linescrip

PHP類型提示提升代碼質量和可讀性。 1)標量類型提示:自PHP7.0起,允許在函數參數中指定基本數據類型,如int、float等。 2)返回類型提示:確保函數返回值類型的一致性。 3)聯合類型提示:自PHP8.0起,允許在函數參數或返回值中指定多個類型。 4)可空類型提示:允許包含null值,處理可能返回空值的函數。

PHP中使用clone關鍵字創建對象副本,並通過\_\_clone魔法方法定制克隆行為。 1.使用clone關鍵字進行淺拷貝,克隆對象的屬性但不克隆對象屬性內的對象。 2.通過\_\_clone方法可以深拷貝嵌套對象,避免淺拷貝問題。 3.注意避免克隆中的循環引用和性能問題,優化克隆操作以提高效率。

PHP適用於Web開發和內容管理系統,Python適合數據科學、機器學習和自動化腳本。 1.PHP在構建快速、可擴展的網站和應用程序方面表現出色,常用於WordPress等CMS。 2.Python在數據科學和機器學習領域表現卓越,擁有豐富的庫如NumPy和TensorFlow。


熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

AI Hentai Generator
免費產生 AI 無盡。

熱門文章

熱工具

MinGW - Minimalist GNU for Windows
這個專案正在遷移到osdn.net/projects/mingw的過程中,你可以繼續在那裡關注我們。 MinGW:GNU編譯器集合(GCC)的本機Windows移植版本,可自由分發的導入函式庫和用於建置本機Windows應用程式的頭檔;包括對MSVC執行時間的擴展,以支援C99功能。 MinGW的所有軟體都可以在64位元Windows平台上運作。

記事本++7.3.1
好用且免費的程式碼編輯器

WebStorm Mac版
好用的JavaScript開發工具

Dreamweaver Mac版
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)