假设我们有一个问题,至少有两个解决方案。我们想要的是比较它们的效率。如何做到这一点?显然,最好的答案是:进行测试。对于特定于语言的问题(例如“对于PHP,echo 'foo','bar'
和echo('foo'. 'bar')
哪个更快”),我怀疑还有更好的方法。
现在,如果我们想测试一些代码,假设它等同于测试某些函数。为什么呢?因为我们可以将该代码封装到函数中,并将它的上下文(如果有)作为其参数传递。因此,我们所需要的只是拥有一个基准函数,它将完成所有工作。下面是一个非常简单的例子:
function benchmark(callable $function, $args=null, $count=1)
{
$time = microtime(1);
for($i=0; $i<$count; $i++)
{
$result = is_array($args)?
call_user_func_array($function, $args):
call_user_func_array($function);
}
return [
'total_time' => microtime(1) - $time,
'average_time' => (microtime(1) - $time)/$count,
'count' => $count
];
}
-这将适用于我们的问题,可以用来进行比较基准测试。在“比较”中,我指的是我们可以先使用上述函数测试代码X
,然后测试代码Y
,然后我们可以说代码X
比代码Y
快/慢Z%
。
问题
好的,我们可以轻松地测量时间。但内存呢?我们之前的假设“如果我们想测试一些代码,就等于测试一些函数”似乎在这里不成立。为什么?因为这个假设虽然从形式上是正确的,但如果我们把代码隐藏在函数内部,就永远无法在此之后测量内存。例如:
function foo($x, $y)
{
$bar = array_fill(0, $y, str_repeat('bar', $x));
//do stuff
}
function baz($n)
{
//do stuff, resulting in $x, $y
$bee = foo($x, $y);
//do other stuff
}
-并且我们想要测试baz
-也就是它在执行过程中会使用多少内存。所谓“如何”是指“函数执行期间最大内存使用量是多少”。很明显,我们不能像测量执行时间那样行事 -因为我们对函数之外的内容一无所知-它是一个黑盒子。实际上,我们甚至不能确定函数是否能够成功执行(想象一下,如果某种方式下baz
内的$ x
和$ y
分配为1E6,会发生什么情况)。因此,将我们的代码包装在函数内可能不是一个好主意。但是,如果代码本身包含其他函数/方法调用呢?
我的方案
我当前的想法是创建一个函数,可以在每个输入代码行后测量内存。这意味着像这样的东西:假设我们有以下代码:
$x = foo();
echo($x);
$y = bar();
-做完某事后,测量函数会执行:
$memory = memory_get_usage();
$max = 0;
$x = foo();//line 1 of code
$memory = memory_get_usage()-$memory;
$max = $memory>$max:$memory:$max;
$memory = memory_get_usage();
echo($x);//second line of code
$memory = memory_get_usage()-$memory;
$max = $memory>$max:$memory:$max;
$memory = memory_get_usage();
$y = bar();//third line of code
$memory = memory_get_usage()-$memory;
$max = $memory>$max:$memory:$max;
$memory = memory_get_usage();
//our result is $max
-但看起来很奇怪,而且它没有回答一个问题-如何测量函数的内存使用情况。
用例
该用例是:在大多数情况下,复杂度理论可以为某些代码提供至少big-O
估计值。但:
- 首先,代码可能非常庞大-我希望尽可能地避免手动分析。这就是为什么我的当前想法不好的原因:它可以应用,是的,但仍然需要手动处理代码。而且,为了深入代码的结构,我需要递归应用它:例如,在应用了顶层后,我发现一些
foo()
函数占用了太多内存。我要做什么?是的,转到此foo()
函数,并且...在其中重复我的分析。以此类推。 - 其次-正如我所提到的,有些特定于语言的事情只能通过进行测试来解决。这就是为什么像时间测量那样拥有一些自动方式是我的目标。
另外,启用了垃圾回收。我正在使用PHP 5.5(我相信这很重要)
问题
我们如何有效地测量某个函数的内存使用情况?在PHP中是否可行?也许可以使用一些简单的代码(如上面用于时间测量的benchmark
函数)吗?
echo(a,b);
是语法错误,而echo a,b;
不是。 - bwoebiecho('foo'.'bar')
- 已修复,谢谢。 - Alma Do