Hi Internals,
I'd like to know whether references to
classes/functions/methods/properties/variables always go through a hash
table at runtime, or if the name is optimised into a pointer or fixed
offset. I recall seeing such an optimisation for local variables, but what
about the others?
Thanks
On Tue, May 17, 2016 at 3:03 PM, Jesse Schalken me@jesseschalken.com
wrote:
Hi Internals,
I'd like to know whether references to
classes/functions/methods/properties/variables always go through a hash
table at runtime, or if the name is optimised into a pointer or fixed
offset. I recall seeing such an optimisation for local variables, but what
about the others?Thanks
A property access $foo->bar (where "bar" is a literal and not the result of
an expression) uses a polymorphic runtime cache, which will store the class
entry and property offset the first time the instruction is executed.
Afterwards, if $foo is an instance of the same class, we will directly use
this offset. Otherwise, a full lookup from the property name table with
visibility checks and all those other bells an whistles has to be performed.
The same holds for pretty much all other symbol references as well, so
classes, functions, methods, etc.
Nikita
Thanks Nikita,
Does that mean a function which accepts an instance of an interface and
calls a method on it will have to do a full lookup of the method whenever
the concrete class isn't the same as when that function was first executed?
(or was last executed, depending on how the cache works)
On Tue, May 17, 2016 at 3:03 PM, Jesse Schalken me@jesseschalken.com
wrote:Hi Internals,
I'd like to know whether references to
classes/functions/methods/properties/variables always go through a hash
table at runtime, or if the name is optimised into a pointer or fixed
offset. I recall seeing such an optimisation for local variables, but what
about the others?Thanks
A property access $foo->bar (where "bar" is a literal and not the result
of an expression) uses a polymorphic runtime cache, which will store the
class entry and property offset the first time the instruction is executed.
Afterwards, if $foo is an instance of the same class, we will directly use
this offset. Otherwise, a full lookup from the property name table with
visibility checks and all those other bells an whistles has to be performed.The same holds for pretty much all other symbol references as well, so
classes, functions, methods, etc.Nikita
Does that mean a function which accepts an instance of an interface and
calls a method on it will have to do a full lookup of the method whenever
the concrete class isn't the same as when that function was first executed?
(or was last executed, depending on how the cache works)
Yes, but that doesn't mean you should micro-optimize around it. Just
write code that's easy to maintain and trust the compiler to do the
best job at making it not-slow. :)
-Sara
Yes, but that doesn't mean you should micro-optimize around it. Just
write code that's easy to maintain and trust the compiler to do the
best job at making it not-slow. :)
Do you happen to know whether or not HHVM does a better job in the case of
a function being called repeatedly with different implementations of a
class/interface?
I don't optimised prematurely, but if I've got performance problems today
and getting a more sophisticated compiler/runtime isn't an option, and I
can't work around it by some other means then I don't really have a choice.
Yes, but that doesn't mean you should micro-optimize around it. Just
write code that's easy to maintain and trust the compiler to do the
best job at making it not-slow. :)Do you happen to know whether or not HHVM does a better job in the case of a
function being called repeatedly with different implementations of a
class/interface?
Yes. In the case of HHVM, different types coming into a function
generate different tracelets and each tracelet is able to burn its own
target method into the native code. I say able, though. There are
also translation paths which result in simply punting to a lookup at
runtime. The decision making process the compiler goes through is...
complex.
I don't optimised prematurely, but if I've got performance problems today
and getting a more sophisticated compiler/runtime isn't an option, and I
can't work around it by some other means then I don't really have a choice.
Saying for the list archive benefit as much as yours. It's only too
easy for this to show up on StackOverflow with a recommendation to
"always break oop conventions by wrapping method calls in a chain of
if (instanceof) checks to cache the right method pointer, yadda
yadda..." and the next thing you know it's php sadness all over again.
-Sara