分配变量与分配+添加所需的时间

时间:2013-07-28 05:42:06

标签: php performance

<?php

$a = microtime(true);
$num = 0;
for($i=0;$i<10000000;$i++)
{
$num = $i;
}

$b= microtime(true);

echo $b-$a;
?>

我在Ubuntu 12.10和Apache 2上运行它 会给我约。 .50秒......当我执行一百万次任务时......但是......

相同的代码,而不是$num = $i ...我去......

$num = $i + 10;现在执行的时间减少了近1.5倍..大约.36。

为什么简单的任务需要更多,而分配和在其上添加10 ...需要更少的时间!

2 个答案:

答案 0 :(得分:1)

我绝不是专家,但这是我的发现:

$s = microtime(true);
for($i=0;$i<100000000;$i++) $tmp = $i;
$t = microtime(true);
for($i=0;$i<100000000;$i++) $tmp = $i+10;
$u = microtime(true);
echo ($t-$s).chr(10).($u-$t);

结果:

  

9.9528648853302
  9.0821340084076

另一方面,使用常量值进行分配测试:

$x = 0;
$s = microtime(true);
for($i=0;$i<100000000;$i++) $tmp = $x;
$t = microtime(true);
for($i=0;$i<100000000;$i++) $tmp = $x+10;
$u = microtime(true);
echo ($t-$s).chr(10).($u-$t);

结果:

  

6.1365358829498
  9.3231790065765

这让我相信答案与操作码缓存有关。老实说,我无法告诉你它是如何产生差异的,但正如你所看到的,使用一个常量值来进行分配会产生巨大的差异。

答案 1 :(得分:0)

这只是一个有根据的猜测,基于在Github上查看最新的php源代码,但我会说这种差异是由于解释器源中的函数调用开销。


$tmp = $i;

编译为单个操作码ASSIGN !2, !1;,将一个名为变量的值复制到另一个名为的变量。在源代码中,the key part看起来像这样:

if (EXPECTED(Z_TYPE_P(variable_ptr) <= IS_BOOL)) {
    /* nothing to destroy */
    ZVAL_COPY_VALUE(variable_ptr, value);
    zendi_zval_copy_ctor(*variable_ptr);
}

$tmp = $i + 10;

编译为两个操作码ADD ~8 !1, 10; ASSIGN !2, ~8;,它创建一个临时变量~8并将其值赋给名为的变量。在源代码中,the key part看起来像这样:

if (EXPECTED(Z_TYPE_P(variable_ptr) <= IS_BOOL)) {
    /* nothing to destroy */
    ZVAL_COPY_VALUE(variable_ptr, value);
}

请注意,在第一种情况下,对zendi_zval_copy_ctor()进行了额外的函数调用。该函数根据需要执行一些簿记(例如,如果原始变量是资源,则需要确保在该新变量消失之前不释放资源,等等)。对于诸如数字之类的原始类型,没有什么可做的,但函数调用本身会引入一些开销,这会累积超过1000万次的测试迭代。你应该注意到这个开销通常可以忽略不计,因为即使在1000万次迭代中它也只累积到.14秒。


@Kolink关于常数更快的观察也可以在同一个函数中回答。如果新值与旧值相同,则为includes a check to avoid redundant copying

if (EXPECTED(variable_ptr != value)) {
copy_value:
    // the same code that handles `$tmp = $i` above
    if (EXPECTED(Z_TYPE_P(variable_ptr) <= IS_BOOL)) {
        /* nothing to destroy */
        ZVAL_COPY_VALUE(variable_ptr, value);
        zendi_zval_copy_ctor(*variable_ptr);
    } else {
        /* irrelevant to the question */
    }
}

因此,只有$tmp = $x的第一个分配才会复制$x的值,以下内容会看到$tmp的值不会更改并跳过复制,从而使其更快。< / p>