我有一个关于PHP 中的copy one write optimization 的问题,我认为它与https://stackoverflow.com/questions/11074970/will-copy-on-write-prevent-data-duplication-on-arrays 不同,并且这个问题标记为https://stackoverflow.com/questions/66703161/does-phps-copy-on-write-work-with-arrays。 https://stackoverflow.com/questions/628938/what-is-copy-on-write 我也觉得这里没有解决这个问题。
在我的观察中,copy on write 优化似乎与 arrays 和 objects 的工作方式不同。使用 arrays,似乎如果有任何变化,无论数组的深度如何,都会发生副本。对于objects,似乎copy on write 只看浅层。
考虑:
class B{
var $b;
function __construct($x) { $this->b = $x; }
}
$w = [new B(0)];
$x = $w; // $x references $w
$x[0]->b = 1; // now $x does not reference $w
$y = new B(0);
$z = $y; // $z references $y
$z->b = 1; // $z still references $y
我根据将 $w、$x、$y 和 $z 传递给 debug_zval_dump 函数来确认这些引用。
有人可以解释为什么会这样吗?我提供的第二个链接中的答案提到“只要没有更改单个字节”,也许这就是我需要更好地理解的内容。我对 PHP objects 的心智模型一直是它们是有效的指针。并且 "$x[0]->b = 1" 中指向 B 的指针没有改变,所以我认为这不是单个字节的改变。
我也不明白为什么在这方面 objects 的行为与 arrays 不同。
除了必须阅读或发布在 Stack Overflow 上之外,这种行为是否被正确记录在了某个地方? PHP.net 手册对于该语言的更多理论细节毫无帮助。例如,使用 JavaScript,可以查看 ECMAScript 标准。 PHP 似乎不存在这种情况。
回答1
您可以简单地使用 var_dump()
来查看 object ID,而不是尝试根据 refcount 进行推断。
例如:
class B{
var $b;
function __construct($x) { $this->b = $x; }
}
$w = [new B(0)];
$x = $w;
$x[0]->b = 1;
var_dump($w, $x);
$y = new B(0);
$z = $y;
$z->b = 1;
var_dump($y, $z);
输出:
array(1) {
[0]=>
object(B)#1 (1) {
["b"]=>
int(1)
}
}
array(1) {
[0]=>
object(B)#1 (1) {
["b"]=>
int(1)
}
}
object(B)#2 (1) {
["b"]=>
int(1)
}
object(B)#2 (1) {
["b"]=>
int(1)
}
在这里我们可以看到 object(B)#1
是通过数组赋值保留的。