Bug->Doc #79392 [Nab->ReO]: get_object_vars() memory leak

From: Date: Tue, 07 Jul 2020 11:09:54 +0000
Subject: Bug->Doc #79392 [Nab->ReO]: get_object_vars() memory leak
References: 1  Groups: php.doc.bugs 
Request: Send a blank email to doc-bugs+get-17695@lists.php.net to get a copy of this message
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


Thread (1 message)

  • cmb@php.net
  • Unknown Message
    • cmb@php.net
« previous php.doc.bugs (#17695) next »