Kaloyan K. Tsvetkov


Can you guess the number of objects created in PHP ?

Quick and dirty way (not a very accurate one) to count object instances in PHP

April 27, 2021

There are these situations where you do need to figure out what and how many objects were created when you run your PHP scripts. There are a lot of reasons to do this:

You can use sophisticated tools such as php-meminfo and get really granular and deep into what is going on. Or ... you can do something quick and dirty although not very accurate, but yet a good guess.

That thing is to take a profiling output and count the number of constructors called. You can do that with a local xdebug cachegrind output, or you can use a Blackfire profile too - they are more or less the same thing. Here is an example from a public Blackfire profile I found on the web:

https://blackfire.io/profiles/355d29d5-5e6d-4977-bdb9-e49d9c7c5bdd/graph

Now go there and search for __construct() and you get 36 constructors, which most likely means 36 instantiated objects.

36 constructors

You can do the same with your favorite cachegrind reader (qcachegrind, kcachegrind, wincachegrind or whatever): just search to find how many times __construct() methods have been called.

As I said at the beginning, this is not accurate.

First, there are classes that do not have constructors, like stdClass for example. You will not be able to count those types of objects this way

Second, speaking of stdClass - all of the objects returned from json_decode() will also not have constructors.

Finally, unserialize(): when you unserialize objects their constructors are not called. If the classes of the serialized objects implement the Serializable interface, then the Serializable::unserialize() method acts as the constructor:

Note:

This method acts as the constructor of the object. The __construct() method will not be called after this method.

https://www.php.net/manual/en/serializable.unserialize.php

You can also look for __wakeup() and __unserialize() as those are also used when unserializing objects.

Perhaps there might be one or more few other places where new objects are created without calling their constructors, but so far these three are the only ones I know of at the moment.

With that being said, I hope this will be of a tiny bit of help for you as it is for me.

Edit 05/01/2021

Few days ago I wrote this, and at the time I felt I was missing something, but I could not figure out what it was, so arrogant me published this post anyway:

Perhaps there might be one or more few other places where new objects are created without calling their constructors, but so far these three are the only ones I know of at the moment.

As it usually happens, I did missed a very obvious one. I got reminded of this when I was inspecting another Blackfire profile for a Laravel demo, and yet it only had few constructors for Symfony classes and ReflectionClass. Surely there should be some Laravel objects created under the Illuminate\ namespace, but I didn't see any. That's when I realized what I was missing from that list: ReflectionClass::newInstanceArgs().

public ReflectionClass::newInstanceArgs ( array $args = [] ) : object

Creates a new instance of the class, the given arguments are passed to the class constructor.

https://www.php.net/manual/en/reflectionclass.newinstanceargs.php

It's very obvious, isn't it? Nowadays almost nobody is creating new objects directly and everyone is using one form of another of IoC container. To resolve all the dependencies injected via the constructors, the containers must be able to create instances with specific list of arguments, and that is not possible when using the new keyword. What you must do instead is use ReflectionClass::newInstanceArgs() to create this instance with the provided arguments.

There are two more sibling methods that can be used to create new objects, ReflectionClass::newInstanceWithoutConstructor() and ReflectionClass::newInstance(), so you can also search for them when you want to count the number of objects created.