Edit report at https://bugs.php.net/bug.php?id=79392&edit=1
ID: 79392
Updated by: cmb@php.net
Reported by: tomas914 at gmail dot com
Summary: get_object_vars() memory leak
-Status: Not a bug
+Status: Re-Opened
-Type: Bug
+Type: Documentation Problem
Package: Performance problem
Operating System: Windows 10
PHP Version: Irrelevant
-Assigned To: cmb
+Assigned To:
Block user comment: N
Private report: N
Previous Comments:
------------------------------------------------------------------------
[2020-07-07 10:31:00] robert at korulczyk dot pl
This really should be documented at https://www.php.net/manual/en/function.get-object-vars.php,
since this is very surprising behavior. I have very similar use case where
get_object_vars($this) was used in toArray() method. Finding source of
memory usage increase took me 2-3 hours, because get_object_vars() was the last thing I
suspected to leak. Especially that manually building this array does not affect memory usage.
No leak:
```
public function toArray(): array {
return [
'a' => $this->a,
'b' => $this->b,
'c' => $this->c,
'd' => $this->d,
'e' => $this->e,
'f' => $this->f,
'g' => $this->g,
'h' => $this->h,
'i' => $this->i,
'j' => $this->j,
];
}
```
Leak:
```
public function toArray(): array {
return get_object_vars($this);
}
```
------------------------------------------------------------------------
[2020-03-18 14:14:37] cmb@php.net
The supposed "leak" is the properties table of the objects, which
is built lazily, because it is often not needed. However,
get_object_vars() requires the table to be built, and it is only
freed when the object is destroyed.
------------------------------------------------------------------------
[2020-03-18 12:05:56] tomas914 at gmail dot com
Issue is present in all PHP versions since at least 7.0, didn't test earlier ones.
------------------------------------------------------------------------
[2020-03-18 12:01:03] tomas914 at gmail dot com
Description:
------------
I'm developing an app which uses storage with fairly large amount of objects that are created
from unserialized cached data.
Objects properties are set by iterating through get_object_vars() which causes extremely high memory
usage.
Provided is reduced test case for reproducing this issue. The difference between two create
functions is only the amount of get_object_vars() calls which leads me to conclusion it's a
memory leak.
Results are:
Create(): Memory usage: 28.72MB
CreateWithLeak(): Memory usage: 95.1MB
Test script:
---------------
abstract class ObjectVarsCache
{
public static $vars = array();
}
class Test
{
public $a;
public $b;
public $c;
public $d;
public $e;
public $f;
public $g;
public $h;
public $i;
public $j;
public function CreateWithLeak()
{
$vars = get_object_vars($this);
}
public function Create()
{
$vars = &ObjectVarsCache::$vars;
if (!$vars)
$vars = get_object_vars($this);
}
}
$objects = array();
for ($i = 0; $i < 100000; ++$i)
{
$object = new Test;
//$object->Create(); // uncomment to compare
$object->CreateWithLeak();
$objects []= $object;
}
echo "Memory usage: ".round(memory_get_usage() / 1024 / 1024, 2)."MB, Peak memory
usage: ".round(memory_get_peak_usage() / 1024 / 1024, 2)."MB";
------------------------------------------------------------------------
--
Edit this bug report at https://bugs.php.net/bug.php?id=79392&edit=1