php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #55033 Memory Leak in magic method __get() [Zend Memory Manager]
Submitted: 2011-06-11 14:40 UTC Modified: 2011-06-11 22:47 UTC
Votes:1
Avg. Score:4.0 ± 0.0
Reproduced:1 of 1 (100.0%)
Same Version:0 (0.0%)
Same OS:0 (0.0%)
From: rodney dot rehm at medialize dot de Assigned:
Status: Not a bug Package: Performance problem
PHP Version: 5.3.6 OS: Mac OS X 10.6.7
Private report: No CVE-ID: None
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: rodney dot rehm at medialize dot de
New email:
PHP Version: OS:

 

 [2011-06-11 14:40 UTC] rodney dot rehm at medialize dot de
Description:
------------
For some reason values returned by __get() aren't released from memory.

$ php memory.php      # (without --debug)
0.0096 seconds and 1.3461 MB for 10000 accessing known property

$ php memory.php      # (with --debug)
0.0317 seconds and 2.6435 MB for 10000 accessing known property

$ export USE_ZEND_ALLOC=0
$ php memory.php      # (with --debug)
0.0267 seconds and 0.0000 MB for 10000 accessing known property


since disabling Zend Memory Manager solved the issue, the valgrind log is pretty much useless, thus not attached.

Test script:
---------------
<?php

class Memleak
{
    public function __get($name)
    {
        return "hello world";
    }
}

$iterations = 10000;
$foo = new Memleak();

$start = microtime(true);
$mem = memory_get_usage();

for ($i=0; $i < $iterations; $i++) {
    $foo->{'bar' . $i};
}

$_mem = memory_get_usage();
$_start = microtime(true);
printf("%0.4f seconds and %0.4f MB for %d accessing known property\n", $_start - $start, ($_mem - $mem) / 1024 / 1024, $iterations);

?>

Expected result:
----------------
0.0099 seconds and 0.0000 MB for 10000 accessing known property

Actual result:
--------------
0.0099 seconds and 1.3460 MB for 10000 accessing known property

Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2011-06-11 16:48 UTC] felipe@php.net
-Status: Open +Status: Bogus
 [2011-06-11 16:48 UTC] felipe@php.net
There is no memleak, what happens is that the return from __get() needs to be separated.
See bug #48197
 [2011-06-11 17:01 UTC] rodney dot rehm at medialize dot de
What exactly do you mean by "separating return from __get()"? The memory is pumped regardless of how I return (value, reference). How am I supposed to "separate" here?
 [2011-06-11 17:02 UTC] felipe@php.net
A copy of returned variable is done.
 [2011-06-11 17:42 UTC] rodney dot rehm at medialize dot de
Just to get this straight. This is not a bug, it's expected behavior.

Anything returned from a magic method is internally handled as a copy. That means that anything a magic methods returns, even if it's a reference to another object, is kept in memory. That is, until the $object the magic methods were invoked on, is unset().

Are you kidding me? Not a bug? Where is this not a bug?
A note on this topic wouldn't harm the docs, you know?
 [2011-06-11 21:45 UTC] rodney dot rehm at medialize dot de
Well, I figure since Bug #48197 is still open, the issue will be resolved eventually. 

If you're facing memory problems because of __get() you might want to sporadically clone the object: $object = clone $object; The wasted memory is not cloned. Beware that you are trading memory for runtime. Only consider this if you are facing memory issues or runtime is not an issue.
 [2011-06-11 22:47 UTC] felipe@php.net
Hi, this behavior is some needs to be changed, I'm not ignoring your point, just closed the report since it has been already reported.

Thanks.
 
PHP Copyright © 2001-2025 The PHP Group
All rights reserved.
Last updated: Sun Jan 05 09:01:27 2025 UTC