php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Request #72224 Optimize reflection initialization
Submitted: 2016-05-16 14:18 UTC Modified: 2021-05-22 15:03 UTC
Votes:6
Avg. Score:4.7 ± 0.7
Reproduced:6 of 6 (100.0%)
Same Version:2 (33.3%)
Same OS:0 (0.0%)
From: dmri87 at hotmail dot com Assigned: krakjoe (profile)
Status: Closed Package: Reflection related
PHP Version: 7.0.7RC1 OS:
Private report: No CVE-ID: None
 [2016-05-16 14:18 UTC] dmri87 at hotmail dot com
Description:
------------
PHP should improve the creation of Reflection objects.

Almost literally any library or framework using Reflection non trivially I've encountered implements its own Reflection objects caching mechanism. That because creating such objects is incredibly expensive and it's way more expensive than caching them all, even if thousands of them. I had to do the same to keep performance acceptable.

PHP should do this internally if possible, or try to optimize something, because again, the amount of times I've seen this is incredible and it's a clear sign the creation of such object is just too slow.

Just to be clear (sorry if I sound harsh but I actually just want to be clear) Reflection object's creation performance is a problem even for those that are using it trivially. I don't think it's acceptable if the creation of few dozens of these objects turns out to be an important bottleneck for applications that would otherwise be extremely fast.

Thank you for reading and double thank you if you intend to work on this.


Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2016-05-20 19:29 UTC] krakjoe@php.net
-Status: Open +Status: Feedback
 [2016-05-20 19:29 UTC] krakjoe@php.net
I've flicked through the source code of the most common reflector constructors, and I see nothing that is obviously causing such problems.

Can you provide some example code that behaves extra ordinarily, perhaps that will help me to understand better ?
 [2016-05-23 20:03 UTC] dmri87 at hotmail dot com
Literally any reflection object, krakjoe.

It is comparable in performance to the creation of other objects, sure, but it is too slow considered that reflection is basically just static information.

For instance, why is this 6 (!!!) times slower than creating the actual object?

class A{}

for($i = 0; $i < 1000000; $i++){
    new A();
} // 0.3150179386 seconds

for($i = 0; $i < 1000000; $i++){
    new ReflectionClass('A');
} // 1.9061090946 seconds
 [2016-05-23 20:20 UTC] dmri87 at hotmail dot com
The example would probably make more sense if I assigned the object to a variable. 

Also notice how I left out the constructor. I'd expect ReflectionClass to compare in performance to the creation of an object without calling its constructor.

Sorry for the multiple replies.
 [2016-05-29 04:22 UTC] php-bugs at lists dot php dot net
No feedback was provided. The bug is being suspended because
we assume that you are no longer experiencing the problem.
If this is not the case and you are able to provide the
information that was requested earlier, please do so and
change the status of the bug back to "Re-Opened". Thank you.
 [2016-05-29 05:00 UTC] requinix@php.net
-Status: No Feedback +Status: Open
 [2016-05-29 10:04 UTC] nikic@php.net
The only obvious inefficiency in the ReflectionClass constructor is the population of the "name" property -- which will allocate and then destroy a temporary string. If we replace this with a persistent string we might get a 10% improvement there.

The difference between "new A" and "new ReflectionClass('A')" is that the latter has to perform a constructor call (expensive) and a runtime lookup of the class 'A' (expensive). This already accounts for most of the difference.

Some ctors like ReflectionProperty::__construct() could be optimized by using a union for different reflection object structures, rather than a separate allocation.
 [2020-02-28 15:09 UTC] nikic@php.net
Based on the script provided by OP:

<?php
class A{}

$t = microtime(true);
for($i = 0; $i < 50000000; $i++){
    new A();
}
var_dump(microtime(true) - $t);

$t = microtime(true);
for($i = 0; $i < 50000000; $i++){
    new ReflectionClass('A');
}
var_dump(microtime(true) - $t);

Numbers on master:

float(1.1946558952332)
float(3.4293010234833)

So ReflectionClass construction is now a bit less than 3x slower than the object construction.
 [2021-05-22 15:03 UTC] krakjoe@php.net
-Status: Open +Status: Closed -Assigned To: +Assigned To: krakjoe
 [2021-05-22 15:03 UTC] krakjoe@php.net
Today, the reflection class constructor makes no duplicate strings. You still have to perform a lookup if you pass the class name as a string, which as mentioned accounts for the majority of the difference. Comparing new Class to new ReflectionClass doesn't make a lot of sense, new has a cache slot for the class entry.

I think there's not much more that can be done here, so I'm closing this bug.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Mon Apr 29 09:01:28 2024 UTC