遭遇php的in_array低性能问题
PHP性能:揭示内部实现细节与性能优化之道
PHP的性能一直在提高,如果使用不当或者忽视其内部实现的一些细节,仍然可能遇到性能问题。最近,我在处理一个性能问题时深有体会。
事情是这样的,一位同事反馈我们的一个接口响应缓慢,每次返回需要5秒之久。我们一起审查了代码,发现了一个令人惊讶的问题:在一个大约900次的循环中,居然有一个读缓存的操作被调用了,而这个缓存的key并没有改变。我们将这段代码移至循环外部,再次测试,接口返回时间降至2秒。虽然性能有所提升,但这显然不是我们能接受的结果。
出现性能问题的代码量并不大,我们排除了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;
}
}
?>
```
我们使用了strace和ltrace两种Linux下的调试利器进行分析。通过ltrace,我们发现库函数__strtol_internal的调用非常频繁,达到了94%。这个函数是字符串转长整型的别名,可以猜测PHP引擎在比较字符串时可能进行了类型转换,导致了性能损耗。为了进一步验证,我们对in_array函数使用了严格比较(加第三个参数为true),避免了PHP自动类型转换。这样修改后,代码运行时间大大缩短。
在解决这个问题后,我们了解到性能瓶颈主要在于in_array这种松比较会在比较前将字符型数字串转换为长整型。知道了问题的根源,我们就可以采取相应的解决方案。在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;
}
}
?>
```
修改后的代码运行时间大大缩短,sys耗时几乎没有太大变化。我们再次使用ltrace进行分析,这次排除了内存分配的影响,因为我们实际应用中是从缓存里直接获取数据,不存在示例代码中那样的循环内存申请情况。我们发现__ctype_tolower_loc占用了最多的时间。尽管这是一个有趣的发现,但与主要的性能问题无关。主要的问题是字符串转整型时的性能损耗以及PHP内部实现的一些细节。了解这些细节后,我们可以更好地优化代码和PHP的使用方式,以提高性能。PHP的in_array函数背后的秘密之旅
当我们谈论将字符串转换为小写时,我们是否应该理解这暗示着in_array函数在比较字符串时不区分大小写呢?实际上,这个理解似乎与in_array函数的实际功能不太相关。为了深入理解这个函数的工作原理,我们需要深入PHP的源代码。
欢迎与我交流关于PHP的见解和疑问。如果您发现我的表述有误,请不吝指正。让我们深入一下in_array函数背后的神秘面纱。
时间回溯到2013年8月29日,我再次深入研究了PHP 5.4.10版本的源代码。我对in_array函数产生了浓厚的兴趣。在./ext/standard/array.c的第1248行,我发现它调用了php_search_array函数,与狼蚁网站SEO优化的array_serach类似,但参数有所不同。
随着我的追踪调查,我发现当使用in_array函数进行宽松比较时,它最终会调用一个名为zendi_smart_strcmp的函数进行比较。这个函数名听起来非常智能,确实它在处理字符串比较时展现出了极高的能力。该函数位于./Zend/zend_operators.c文件中。我使用ltrace工具捕获了大量关于转换成整型的操作,这些操作都是来自于is_numeric_string_ex函数的行为。这个函数在./Zend/zend_operators.h中被定义,并在一系列的判断和转换后,最终在232行调用了strtol系统函数。这正是我们在文章中提到的将字符串转换为长整型的操作。
这一切背后的逻辑和细节都充满了魅力,PHP的源代码世界充满了未知和惊喜。如果你也想这个神秘的世界,欢迎与我交流,让我们共同学习,共同进步。我期待着与你分享更多关于PHP源代码的见解和发现。也请随时指出我表述中的错误,我会虚心接受并改正。让我们共同揭开PHP的更多秘密吧!
提醒一下各位读者,本文所述的内容都是基于我所理解和分析的PHP源代码,如果您有更深的理解或者有其他观点,欢迎与我交流分享。期待与您共同学习进步!同时请注意,我的表达可能会存在一些偏差或误解,请在阅读时保持警惕并自行判断。感谢阅读!
微信营销
- 遭遇php的in_array低性能问题
- Mysql数据库实现多字段过滤的方法
- .net后台页面统一验证是否登录
- MySQL中无过滤条件的count详解
- PHP 枚举类型的管理与设计知识点总结
- 基于angular实现三级联动的生日插件
- 简述vue-cli中chainWebpack的使用方法
- 新东方考研英语视频
- asp.net自定义分页控件示例
- 精卫之歌:如何感受其独特魅力与情感表达
- BootStrap 图片样式、辅助类样式和CSS组件的实例详
- JS判断客服QQ号在线还是离线状态的方法
- 爱情的颜色是永恒之蓝吗
- JavaScript实现QQ列表展开收缩扩展功能
- 全面了解JavaScript的数据类型转换
- JavaScript实现图片本地预览功能【不用上传至服务