PHP: `get_class($this)` vs `static::class`

Without getting into too much detail, I recently wanted to see what the support was like for static::class, and came across this SO answer that got me to thinking.

First, it partially correctly stated that static::class was supported in PHP > 5.5.  I have since submitted an edit to correct for PHP >= 5.5, because – INTERNET JUSTICE – and frankly, that distinction matters.  Second, the answer said it was much more performant, and while I instinctively knew that to be true, I wanted to see for myself…

QUEUE THE OP-CODE COUNTING!!

Consider the following two methods:

These result in the following OPCodes.

Ignoring the calls to RETURN (for setting up and returning from the method), you can see that the two methods of getting the top level class result in 1 and 4 ops, respectively.

Now, mind you that op-codes are not direct indicators of performance, but they do indicate:

1. How many directives need to be parsed and checked.
2. How many calls to
underlying C-functions need to be made.

It is possible that FETCH_CLASS_NAME could be incredibly computationally intensive in the underlying C library. It isn’t, however, and is much more performant when compared to the initializing, fetching and sending of the get_class() alternative.

What is a little over-complication without an unnecessary benchmark!?

So I set up the following benchmark in trusty-ole perfdiff:

And here are the results:

{“Get Class”:[{“reruns”:[{“start”:1489420114.1973,”stop”:1489420120.769,”wall”:6.571720123291,”iterations”:5000000,”status”:true},{“start”:1489420120.7841,”stop”:1489420125.7089,”wall”:4.9247150421143,”iterations”:5000000,”status”:true},{“start”:1489420125.7236,”stop”:1489420130.5944,”wall”:4.8708648681641,”iterations”:5000000,”status”:true},{“start”:1489420130.6087,”stop”:1489420135.6428,”wall”:5.0341029167175,”iterations”:5000000,”status”:true},{“start”:1489420135.6572,”stop”:1489420140.4895,”wall”:4.8323137760162,”iterations”:5000000,”status”:true}],”tare”:{“reruns”:[{“start”:1489420140.5039,”stop”:1489420143.107,”wall”:2.6031401157379,”iterations”:5000000,”status”:true},{“start”:1489420143.1133,”stop”:1489420145.1357,”wall”:2.0224001407623,”iterations”:5000000,”status”:true},{“start”:1489420145.1499,”stop”:1489420147.183,”wall”:2.0330691337585,”iterations”:5000000,”status”:true},{“start”:1489420147.1973,”stop”:1489420149.2122,”wall”:2.014858007431,”iterations”:5000000,”status”:true},{“start”:1489420149.2264,”stop”:1489420151.2373,”wall”:2.0109038352966,”iterations”:5000000,”status”:true}],”best”:4,”worst”:2},”best”:4,”worst”:3}],”Static Class”:[{“reruns”:[{“start”:1489420151.256,”stop”:1489420155.0606,”wall”:3.8045680522919,”iterations”:5000000,”status”:true},{“start”:1489420155.0749,”stop”:1489420158.8889,”wall”:3.8139917850494,”iterations”:5000000,”status”:true},{“start”:1489420158.9072,”stop”:1489420162.7156,”wall”:3.8084299564362,”iterations”:5000000,”status”:true},{“start”:1489420162.7218,”stop”:1489420166.5406,”wall”:3.8187611103058,”iterations”:5000000,”status”:true},{“start”:1489420166.5552,”stop”:1489420170.3514,”wall”:3.7961971759796,”iterations”:5000000,”status”:true}],”tare”:{“reruns”:[{“start”:1489420170.3698,”stop”:1489420172.366,”wall”:1.9962110519409,”iterations”:5000000,”status”:true},{“start”:1489420172.3804,”stop”:1489420174.763,”wall”:2.3825349807739,”iterations”:5000000,”status”:true},{“start”:1489420174.7827,”stop”:1489420177.8247,”wall”:3.0419418811798,”iterations”:5000000,”status”:true},{“start”:1489420177.8311,”stop”:1489420179.9185,”wall”:2.087415933609,”iterations”:5000000,”status”:true},{“start”:1489420179.9329,”stop”:1489420181.9355,”wall”:2.0026040077209,”iterations”:5000000,”status”:true}],”best”:4,”worst”:2},”best”:4,”worst”:3}]}

Without digging in to it too much, we are looking at roughly 2.9 seconds for get_class() and 1.8 seconds for static::class (accounting for the tare), so roughly 1/3rd faster…

And there you have it, I saved fractions of a second in my code, and just spent an hour or more writing about it.  JOY!

Comments are closed.

Post Navigation