3

我正在玩弄 PHP 魔术方法(特别是属性重载),并且在进行微基准测试时遇到了一个我无法解释的怪癖:

似乎__set一个空主体的方法比一个有效的方法需要更多的时间来运行。下面的代码片段演示了这一点:

class EmptySetter {
    public function __set($name, $value) {}
}

class NonEmptySetter {
    public function __set($name, $value) {
        $this->{$name} = $value;
    }
}

function benchmark($obj) {
    $start_time = microtime(TRUE);
    for ($i = 0; $i < 10000000; $i++) {
        $obj->foo = 42;
    }
    return microtime(TRUE) - $start_time;
}

printf("EmptySetter: %.2f seconds\n", benchmark(new EmptySetter));
printf("NonEmptySetter: %.2f seconds\n", benchmark(new NonEmptySetter));

// output (on my Core 2 Duo laptop):
// EmptySetter: 4.39 seconds
// NonEmptySetter: 1.28 seconds

有没有人解释为什么会这样?

4

2 回答 2

2

你不能比较这两者,因为最终的结果是不相等的。

$o1 = (new NonEmptySetter);
$o1->foo = 42;

$o2 = (new EmptySetter);
$o2->foo = 42;

var_dump($o1, $o2, $o2->foo);

这给出了:

object(NonEmptySetter)[1]
  public 'foo' => int 42

object(EmptySetter)[2]

null

并加上最后一个通知:Notice: Undefined property: EmptySetter::$foo

这意味着该属性永远不会设置,它不存在,仙尘,我假设那里的违规行为需要时间。

在此处输入图像描述

如果你正确地声明你的班级(注意$foo):

class EmptySetter {
    public $foo = NULL;
    public function __set($name, $value) {}
}

时间将被捆绑:您声明 EmptySetter::$foo 的基准

于 2014-04-14T01:56:24.540 回答
2

哦,我看到这是错误的测试用例。

在第一个循环之后NonEmptySetter会有新的公共财产foo。Next 循环根本不调用__set方法,它们使用公共属性。

class NonEmptySetter {
    public function __set($name, $value) {
        echo 'called only once'; // would be echoed only once.
        $this->{$name} = $value;
    }
}

有效测试

class EmptySetter {
    public function __set($name, $value) {}
}

class NonEmptySetter {
    public function __set($name, $value) {
        $this->{$name} = $value;
    }
}

function benchmark($class_name) {
    $start_time = microtime(TRUE);
    for ($i = 0; $i < 1000000; $i++) {
        $obj = new $class_name();
        $obj->foo = 42;
    }
    return microtime(TRUE) - $start_time;
}

printf("NonEmptySetter: %.2f seconds\n", benchmark('NonEmptySetter'));
printf("EmptySetter: %.2f seconds\n", benchmark('EmptySetter'));

http://3v4l.org/gVtSq

空二传手更快。

于 2014-04-14T02:05:44.957 回答