Tow*_*wer 37 php optimization performance
我是一名PHP开发人员,我一直认为微优化不值得花时间.如果你真的需要额外的性能,你可以编写你的软件,使其在架构上更快,或者你编写一个C++扩展来处理慢速任务(或者更好的是,使用HipHop编译代码).然而,今天一位工作伙伴告诉我,这有很大的不同
is_array($array)
Run Code Online (Sandbox Code Playgroud)
和
$array === (array) $array
Run Code Online (Sandbox Code Playgroud)
而且我就像"呃,这真是一个毫无意义的比较",但他不同意我的看法......他是我们公司最好的开发人员,并且负责一个每天大约有5000万次SQL查询的网站 - - 例如.所以,我在这里想知道:他可能是错的还是微优化真的值得花时间和时间?
irc*_*ell 138
好吧,对于一个简单的小阵列,$array === (array) $array明显快于is_array($array).大约快7倍的顺序.但每次调用只有大约1.0 x 10 ^ -6秒(0.000001 seconds).因此,除非你真的称它为数千次,否则它不值得.如果你打电话数千次,我建议你做错了......
当你处理一个大型数组时会出现差异.由于$array === (array) $array需要复制一个新变量,因此需要在内部迭代数组进行比较,对于大型数组来说,它可能会显着变慢.例如,在具有100个整数元素的数组上,使用小数组(在几秒钟内进行10,000次迭代)is_array($array)的error(< 2%)范围内.但是非常慢.对于只有100个元素,它已经超过两倍(在几秒钟内进入).对于1000个元素,保持不变,但演员比较增加到秒......is_array()0.0909$array = (array) $arrayis_array()0.203is_array2.0699
小数组更快的原因是它is_array()具有函数调用的开销,其中转换操作是一个简单的语言构造...并且迭代一个小变量(在C代码中)通常比函数调用开销更便宜.但是,对于较大的变量,差异会增大......
这是一个权衡.如果数组足够小,迭代将更有效.但随着数组大小的增加,它将变得越来越慢(因此函数调用将变得更快).
另一种看待它的方法是检查每个演员的算法复杂性.
我们先来看一看is_array().它的源代码基本上表明它是一个O(1)操作.这意味着它是一个恒定的时间操作.但我们还需要查看函数调用.在PHP中,具有单个数组参数的函数调用是O(1)或者O(n)取决于是否需要触发copy-on-write.如果在is_array($array)何时调用$array变量引用,则将触发copy-on-write并且将发生变量的完整副本.
因此,这is_array()是一个最好的案例O(1)和最坏的情况O(n).但只要你不使用引用,它总是O(1)......
另一方面,演员版本执行两项操作.它做一个演员,然后进行相等检查.那么让我们分别看一下.转换操作符处理程序首先强制输入变量的副本.无论是否参考.因此,简单地使用(array)转换操作符强制O(n)对数组进行迭代以进行转换(通过copy_ctor调用).
然后,它将新副本转换为数组.这适用O(1)于数组和基元,但O(n)适用于对象.
然后,执行相同的运算符.该处理器只是一个代理的is_identical_function().现在,如果$array不是数组,is_identical将短路.因此,它具有最好的情况下的O(1).但是如果$array 是一个数组,如果哈希表是相同的,它可以再次短路(意味着两个变量都是彼此的写时复制副本).所以那个案子也是O(1)如此.但请记住,我们强制上面的副本,所以如果它是一个数组我们不能这样做.所以这O(n)要归功于zend_hash_compare ......
所以最终结果就是这个最坏情况运行时表:
+----------+-------+-----------+-----------+---------------+
| | array | array+ref | non-array | non-array+ref |
+----------+-------+-----------+-----------+---------------+
| is_array | O(1) | O(n) | O(1) | O(n) |
+----------+-------+-----------+-----------+---------------+
| (array) | O(n) | O(n) | O(n) | O(n) |
+----------+-------+-----------+-----------+---------------+
Run Code Online (Sandbox Code Playgroud)
请注意,对于引用,它们看起来相同.他们没有.它们都为参考变量线性扩展.但是不变因素会发生变化.例如,在大小为5的引用数组中,is_array将执行5个内存分配,5个内存副本,然后执行1个类型检查.另一方面,强制转换版本将执行5次内存分配,5次内存复制,然后进行2次类型检查,然后进行5次类型检查和5次相等检查(memcmp()或类似检查).所以n=5收获11个操作is_array,但22个操作===(array)...
现在,is_array()确实有堆栈推送的O(1)开销(由于函数调用),但是这只会占据运行时的极小值n(我们在基准测试中看到只有10个数组元素足以完全消除所有的区别).
我建议去寻求可读性.我发现is_array($array)它比可读性更强$array === (array) $array.所以你可以充分利用这两个世界.
我用于基准测试的脚本:
$elements = 1000;
$iterations = 10000;
$array = array();
for ($i = 0; $i < $elements; $i++) $array[] = $i;
$s = microtime(true);
for ($i = 0; $i < $iterations; $i++) is_array($array);
$e = microtime(true);
echo "is_array completed in " . ($e - $s) ." Seconds\n";
$s = microtime(true);
for ($i = 0; $i < $iterations; $i++) $array === (array) $array;
$e = microtime(true);
echo "Cast completed in " . ($e - $s) ." Seconds\n";
Run Code Online (Sandbox Code Playgroud)
编辑:为了记录,这些结果是在Linux上的5.3.2 ...
Edit2:修复了数组较慢的原因(这是由于迭代比较而不是内存原因).有关迭代代码,请参阅compare_function ...
Jon*_*eet 81
当您有证据表明您正在优化瓶颈时,微优化是值得的.
通常它是不值得的 - 编写最可读的代码,并使用实际的基准来检查性能.如果您发现自己遇到了瓶颈,那么微优化一下代码(随时测量).有时,少量的微优化可以产生巨大的差异.
但是不要微观优化你的所有代码......它最终会变得难以维护,你很可能会发现你要么错过了真正的瓶颈,要么你的微观优化正在损害性能而不是帮助.
Mik*_*vey 11
微观优化值得花时间吗?
不,除非是.
换句话说,先验,答案是"不",但在您知道特定的代码行消耗了健康的时钟时间百分比之后,那么只有这样才值得优化.
换句话说,首先描述,否则你没有那种知识.这是我依赖的方法,无论语言或操作系统如何.
补充:当许多程序员讨论性能时,从专家那里开始,他们倾向于谈论程序花费时间的"位置".在"哪里" 导致他们远离可以节省大部分时间的东西,即函数调用站点,这是一种狡猾的模糊.毕竟,应用程序顶部的"呼叫主"是一个"地方",该程序几乎从不"处于",但是100%的时间负责.现在你不会摆脱"呼叫主",但几乎总有其他的呼叫,你可以摆脱.当程序打开或关闭文件,或将某些数据格式化为一行文本,或等待套接字连接,或"新" - 一块内存时,调用函数,但它是"在哪里"?无论如何,这些调用很快就会发现堆栈样本.
正如陈词滥调,只有在您证明这是瓶颈所在之后,微优化通常才值得在代码的最小、最关键的性能热点上花费时间。但是,我想稍微充实一下,指出一些例外情况和误解领域。
这并不意味着不应该预先考虑性能。我将微优化定义为基于编译器/解释器、硬件等的低级细节的优化。根据定义,微优化不会影响大 O 复杂度。 应预先考虑宏观优化,尤其是当它们对高层设计产生重大影响时。例如,可以肯定地说,如果您有一个大的、经常访问的数据结构,那么 O(N) 线性搜索不会削减它。即使只是常数项但有大量明显开销的事情也值得预先考虑。两个重要的例子是过多的内存分配/数据复制和两次计算相同的事情,而你可以计算一次并存储/重用结果。
如果您正在做一些以前在略有不同的上下文中做过的事情,那么可能存在一些众所周知的瓶颈,因此提前考虑它们是合理的。例如,我最近正在研究 D 标准库的 FFT(快速傅立叶变换)算法的实现。由于之前用其他语言编写了这么多FFT,众所周知最大的瓶颈是缓存性能,因此我立即进入项目考虑如何优化它。
| 归档时间: |
|
| 查看次数: |
9729 次 |
| 最近记录: |