Re: Object getter method optimization
| From: | Dmitry Stogov | Date: | Fri, 01 Apr 2016 19:49:04 +0000 |
| Subject: | Re: Object getter method optimization | ||
| References: | 1 2 3 | Groups: | php.internals |
| Request: | Send a blank email to internals+get-92066@lists.php.net to get a copy of this message | ||
HI Yo-An Lin,
I added comments to PR.
After fixing obvious errors (explained in comments), few tests are still failed
tests/classes/unset_properties.phpt
Zend/tests/bug52614.phpt
The introduced run-time check in ZEND_INIT_METHOD_CALL speed-ups getters in cost of small overhead
for all other methods.
I don't see any visible performance change on real-life apps.
Thanks. Dmitry.
________________________________
From: Lin Yo-An <cornelius.howl@gmail.com>
Sent: Friday, April 1, 2016 19:14
To: Dmitry Stogov
Cc: internals; Xinchen Hui; Nikita Popov
Subject: Re: [PHP-DEV] Object getter method optimization
I submitted my PR here https://github.com/php/php-src/pull/1847
On Fri, Apr 1, 2016 at 11:41 PM, Lin Yo-An <cornelius.howl@gmail.com<mailto:cornelius.howl@gmail.com>> wrote:
Hi internals,
Here comes the result:
Without getter optimization (3 runs):
250.76603889465ms
With getter optimization (3 runs)
110.88299751282ms
Microbench result: https://gist.github.com/c9s/0273ac21631562724cabf86c42e86e32
On Fri, Apr 1, 2016 at 4:35 PM, Lin Yo-An <cornelius.howl@gmail.com<mailto:cornelius.howl@gmail.com>> wrote:
Hi Dmitry, Nikita, Andrea
My implementation now is able to get the property offset and fetch object property directly without
invoking zend_std_read_property and pushing new call frame onto the stack.
The current behavior:
1. In compile-time, the pass_two() function now marks the getter functions in op_array.accessor.type
2. When Zend Engine first time attempt to read the property, it saves the property offset in the
accessor field and mark the method as a "getter".
3. When Zend Engine second time invoke the getter method, it checks the accessor field and try to
read the property value directly instead a "method call"
The implementation did some change:
1. Added accessor struct to op_array to save "accessor" related information (getter or
setter, property offset)
2. Added two statement in zend_std_read_property to save property offset.
3. Added op code check in zend_compile (The pass_two() function) to mark a function is a getter)
But now I encountered a problem, I can't store the result value in INIT_METHOD_CALL op, the
result var is only available in DO_FCALL_*
I have an idea for solving this, but I'm not sure if it's good or not:
If DO_FCALL_* will always follow a INIT_METHOD_CALL, then I think we can store result var from the
next op (DO_FCALL) and skip DO_FCALL directly.
Would be great if I can have your advices and suggestion. :-)
Thanks, Yo-An Lin
On Tue, Mar 22, 2016 at 4:45 PM, Dmitry Stogov <dmitry@zend.com<mailto:dmitry@zend.com>> wrote:
Hi Yo-An Lin,
This "run-time inlining" approach may work.
PHP compiler (or optimizer) may mark functions and methods suitable for "run-time"
inlining (e.g. methods without arguments and FETCH_OBJ_R UNUSED, CONST -> TMP; RETURN TMP).
Then INIT_METHOD_CALL may check this flag and execute "optimized code sequence" instead of
pushing stack frame and real call.
However, I'm not sure what kind of performance impact this may make, because we will have to
make additional check on each INIT_METHOD_CALL execution.
Thanks. Dmitry.
________________________________
From: Lin Yo-An <cornelius.howl@gmail.com<mailto:cornelius.howl@gmail.com>>
Sent: Saturday, March 19, 2016 10:08
To: Dmitry Stogov
Cc: internals; Xinchen Hui
Subject: Re: [PHP-DEV] Object getter method optimization
Hi Dmitry,
Thanks for your reply! You're correct. let me try to explain your points:
If I have a main.php and worker.php
And I defined work($worker) { $status = $worker->getStatus(); } inside main.php
when main.php is compiled, we don't know what the class entry of $worker is.. What we only know
is invoking a method "getStatus" on $worker CV unless we know we have to compile
worker.php before main.php and add a type hint on $worker.
Is it correct?
Since the original approach doesn't work, here comes another new idea:
When executing method call on an object, if we found the method body are just 2 op codes
(FETCH_OBJ_R and RETURN), we then denote the method is a "getter method"
And the next time, when we execute the same method, we found the "getter method" flag, we
simply execute FETCH_OBJ_R on that object and return the value to avoid extra op code execution
time.
Do you think if this could work?
Best Regards and Thanks for your work on PHP VM
Yo-An Lin
On Fri, Mar 18, 2016 at 3:36 PM, Dmitry Stogov <dmitry@zend.com<mailto:dmitry@zend.com>> wrote:
Hi Yo-An Lin,
Unfortunately, this approach won't work.
At first, at compile time we don't know the body of called getter.
At second, the called method might be changed even at run-time, because of polymorphism.
Tricks like this might be implemented using JIT and polymorphic inline caches.
Thanks. Dmitry.
________________________________________
From: Lin Yo-An <cornelius.howl@gmail.com<mailto:cornelius.howl@gmail.com>>
Sent: Friday, March 18, 2016 05:23
To: internals
Subject: [PHP-DEV] Object getter method optimization
Hello Everyone,
I am recently trying to write an optimizer that could optimize the getter
method call into just one object fetch opcode.
I'd like to know thoughts from you guys, here is the note:
https://c9s.hackpad.com/INLINE-OP-TVGo9WcshbZ
--
Best Regards,
Yo-An Lin
https://github.com/c9s
--
Best Regards,
Yo-An Lin
--
Best Regards,
Yo-An Lin
--
Best Regards,
Yo-An Lin
--
Best Regards,
Yo-An Lin