简体   繁体   English

PHP - 为什么按引用传递使用相同数量的内存?

[英]PHP - why does passing by reference use the same amount of memory?

I am getting 'memory exhausted' in my PHP script.我的 PHP 脚本“内存耗尽”。 I cannot figure out why.我不明白为什么。 The limit is 128Mb.限制为 128Mb。 I am sending, from a javascript xmlrequest(), a json string that is maximum 10MB (usually under 1MB).我正在从 javascript xmlrequest() 发送一个最大 10MB(通常小于 1MB)的 json 字符串。 The PHP script itself is 43K. PHP 脚本本身是 43K。 Even copying everything a dozen times over I shouldn't run out of memory.即使将所有内容复制十几次,我也不应该耗尽内存。 I do a few calls to the database at getParentFolders() but that produces only a few rows.我在 getParentFolders() 处对数据库进行了几次调用,但只产生了几行。 Certainly not the 62 megabytes it claims I am using.当然不是它声称我正在使用的 62 兆字节。 I have used Xdebug (see picture) but this tells me nothing useful, only that yup, I'm using a lot of memory.我使用过 Xdebug(见图片),但这告诉我没有任何用处,只是,是的,我使用了大量内存。

So at this point I am trying to do 'best practices' to minimize memory usage.所以在这一点上,我正在尝试做“最佳实践”来最小化内存使用。 A simple fix, or so I thought, was to pass in values by reference.一个简单的解决方法,或者我认为,是通过引用传递值。 So I put a '&' before every variable in every function.所以我在每个函数的每个变量之前都放了一个“&”。 To my surprise, there was no change in memory consumption.令我惊讶的是,内存消耗没有变化。 It was slightly worse by a few bytes, in fact.事实上,它稍微差了几个字节。 I have also tried using every variable as a global, but again, to my surprise, there was little difference.我也尝试将每个变量用作全局变量,但同样令我惊讶的是,几乎没有区别。

So what's going on?发生什么了? Why is passing by reference and using globals not producing the performance benefits I expected?为什么通过引用传递和使用全局变量没有产生我预期的性能优势? (see images) (见图片)

Xdebug 'pass by value' Xdebug '按值传递'

在此处输入图片说明

Xdebug 'pass by reference' Xdebug '通过引用'

在此处输入图片说明

Note they are pretty much identical.请注意,它们几乎相同。

For those who want code, here is the getParentFolders() function, which returns just a short string but somehow uses 70Mb!对于那些想要代码的人,这里是 getParentFolders() 函数,它只返回一个短字符串,但不知何故使用了 70Mb!

function getParentFolders(&$node) {  //returns a string of folders
    debugprint("GetParentFOlders()");  //prints if $DEBUG flag is on
    $parent = getParent($node);
    $path = "";
    while ($parent) {  //goes till we hit root folder
        $path = $parent->title . '/' . $path;  //prepend it
        $parent = getParent($parent);
    }
    return $path;
}

function getParent(&$node) {  //return node that is the parent 
    global $email;
    $parentId = $node->parentId;
    $clientId = $node->parentClient;
    $idCol = $clientId . "_id";
    $tablename = $email . "_bookmarks";
    $query = "SELECT * FROM `$tablename`
                        WHERE $idCol = '$parentId'";  //only return one row since id is unique
    $result = sendquery($query);
    return (object) $result[0];
}

Edit:编辑:

Just to clarify, I am looking for a technical explanation of PHP memory usage and best practices - specifically why I am not seeing memory differences - not a workaround for the issue.只是为了澄清,我正在寻找 PHP 内存使用和最佳实践的技术解释 - 特别是为什么我没有看到内存差异 - 不是该问题的解决方法。

Make sure the query result returns one row by using LIMIT 1 ;使用LIMIT 1确保查询结果返回一行; If no result found then make the getParent() return false or null so that it can be set to $parent to exit from while loop.如果未找到结果,则使getParent()返回falsenull以便将其设置为$parent以退出while循环。 And I don't think so that you need to pass the $node argument by reference in your case.而且我认为您不需要在您的情况下通过引用传递$node参数。

The value of $node is a reference, ie a pointer to an object. $node的值是一个引用,即指向对象的指针。 In PHP 5+, "objects" are not values directly.在 PHP 5+ 中,“对象”不是直接的值。 You always work with objects through pointers to them: when you do new ClassName , it evaluates to a pointer to an object;你总是通过指向对象的指针来处理对象:当你执行new ClassName ,它的计算结果是一个指向对象的指针; when you use the -> operator, it takes a pointer to an object on the left side.当您使用->运算符时,它需要一个指向左侧对象的指针。

So if both of these functions were pass-by-value, the size of the thing passed is just the size of a pointer.所以如果这两个函数都是按值传递的,那么传递的东西的大小就是一个指针的大小。 When you passed by reference, that basically wraps the pointer in another level of pointer, which is the same size (though the total memory is greater since there are two pointers).当您通过引用传递时,这基本上将指针包装在另一个级别相同的指针中(尽管总内存更大,因为有两个指针)。 The only point of passing by reference is that it allows you to assign to $node inside the function to point to a different object or hold a different type of value, and have it be reflected in the passed variable in the calling function, but you do not assign to $node anywhere here (modifying a field of the object pointed to $node is not the same as assigning to $node ), so pass-by-reference is pointless here.通过引用传递的唯一一点是它允许您在函数内部分配给$node以指向不同的对象或保存不同类型的值,并使其反映在调用函数中传递的变量中,但是您不要在这里任何地方分配给$node (修改指向$node的对象的字段与分配给$node ),因此传递引用在这里毫无意义。

(Plus, even if you passed a value type, like arrays in PHP, they have copy-on-write semantics, and is not copied until you write to it. And even if you wrote to it and caused it to make a copy, that copy would only last for the lifetime of this local variable, which ends at the end of the function, so it would not create persistent memory usage.) (另外,即使你传递了一个值类型,比如 PHP 中的数组,它们也具有写时复制语义,并且在你写入之前不会被复制。即使你写入并导致它复制,该副本仅在此局部变量的生命周期内持续,该生命周期在函数结束时结束,因此它不会创建持久内存使用。)

The answer is that objects cannot be passed by value.答案是对象不能按值传递。 They are always passed by reference.它们总是通过引用传递。 The 'pass by reference' operator, '&', will do nothing other than wrap the object reference (ie a pointer) in a wrapper, then pass that new pointer. “通过引用传递”运算符“&”除了将对象引用(即指针)包装在包装器中,然后传递该新指针之外,什么都不做。

As for the memory usage, there is no simple answer other than database query results seem to come with a lot of overhead, and you want to make your 'footprint' (ie any results returned from a database, or any variables) as small as possible.至于内存使用,除了数据库查询结果似乎带来很多开销之外,没有其他简单的答案,并且您希望使您的“足迹”(即从数据库返回的任何结果或任何变量)尽可能小可能的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 为什么在PHP中通过引用传递? - Why Passing by Reference in PHP? 为什么简单的 PHP unset() memory 测试在 Z2FEC3922524A5C2B3AC138 中使用两倍的 memory 量? - Why does a simple PHP unset() memory test utilize twice the amount of memory in PHP 5.3? 如何或为什么通过引用传递用PHP覆盖其他引用? - How or why does passing by reference overwrite other references with PHP? 为什么循环中的 php 引用不指向同一个地方? - Why does the php reference in a loop not point to the same place? PHP-APCu是否使用与为opcache定义的相同的内存池? - PHP - Does APCu use the same memory pool as defined for opcache? 为什么PHP脚本在两个服务器上使用不同的内存量? - Why does a PHP script use different amounts of memory on two servers? 为什么php抱怨在此代码中引用传递? - why is php complaining about passing by reference in this code? 通过引用-它如何工作以及为什么使用它? - Passing by reference - how does it work and why is it used? 为什么 PHP 的 call_user_func() function 不支持引用传递? - Why does PHP's call_user_func() function not support passing by reference? 为什么PHP允许在一种情况下将文字传递给pass-by-reference参数而不允许其他情况? - Why does PHP allow passing a literal to a pass-by-reference parameter in one case but not others?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM