我正在使用PHP魔术方法(特别是Property overloading),并且,在进行微基准测试时遇到了一个奇怪的问题,我无法解释:
似乎一个空主体的__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
有没有人解释为什么会这样?
答案 0 :(得分: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) {}
}
答案 1 :(得分:2)
哦,我认为这是错误的测试用例。
第一个循环NonEmptySetter
之后会有新的公共属性foo
。接下来的循环根本不会调用__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'));
空的setter更快。