Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:92104 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 66764 invoked from network); 5 Apr 2016 14:14:14 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 5 Apr 2016 14:14:14 -0000 Authentication-Results: pb1.pair.com smtp.mail=dmitry@zend.com; spf=pass; sender-id=pass Authentication-Results: pb1.pair.com header.from=dmitry@zend.com; sender-id=pass Received-SPF: pass (pb1.pair.com: domain zend.com designates 157.56.111.102 as permitted sender) X-PHP-List-Original-Sender: dmitry@zend.com X-Host-Fingerprint: 157.56.111.102 mail-bn1bbn0102.outbound.protection.outlook.com Received: from [157.56.111.102] ([157.56.111.102:50384] helo=na01-bn1-obe.outbound.protection.outlook.com) by pb1.pair.com (ecelerity 2.1.1.9-wez r(12769M)) with ESMTP id FB/37-27948-038C3075 for ; Tue, 05 Apr 2016 10:14:10 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=RWSoftware.onmicrosoft.com; s=selector1-zend-com; h=From:To:Date:Subject:Message-ID:Content-Type:MIME-Version; bh=zoJqSpsv/ddpbeZvu4gUqZdgwo/TDoqkhvRcVf6Z18o=; b=gCFVDSogyaeNLbvLHo+IFI3GYeMSJXPlVSOknHNcXu2ZfvK16KDXpoB6NS7KR1yNyfw9JZzy7BNhYiJqpT8ghIroKPGSxI45ITHQ11Z4RH5NFZXCjmdFxnXrtvpmN0PdZJ/UkeArf3edFXokgxSdpCk334LcScfKD0X8uK/qva8= Received: from BY2PR0201MB1784.namprd02.prod.outlook.com (10.163.72.26) by BY2PR0201MB1783.namprd02.prod.outlook.com (10.163.72.25) with Microsoft SMTP Server (TLS) id 15.1.447.15; Tue, 5 Apr 2016 14:14:03 +0000 Received: from BY2PR0201MB1784.namprd02.prod.outlook.com ([10.163.72.26]) by BY2PR0201MB1784.namprd02.prod.outlook.com ([10.163.72.26]) with mapi id 15.01.0447.028; Tue, 5 Apr 2016 14:14:03 +0000 To: Lin Yo-An CC: Xinchen Hui , Nikita Popov , Bob Weinand , Joe Watkins , internals Thread-Topic: Object getter method optimization Thread-Index: AQHRj0OLiX8X0BnQ5U+SlXD9k2g53597aoW+ Date: Tue, 5 Apr 2016 14:14:03 +0000 Message-ID: References: In-Reply-To: Accept-Language: en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: authentication-results: php.net; dkim=none (message not signed) header.d=none;php.net; dmarc=none action=none header.from=zend.com; x-originating-ip: [132.245.81.165] x-ms-office365-filtering-correlation-id: bfab6b2c-bd24-491e-70c2-08d35d5c8ac7 x-microsoft-exchange-diagnostics: 1;BY2PR0201MB1783;5:1yVydQ1Zsap3n8oRrVPJTDGppgy6FiWUUpf8kx5iXhHPWmH5IrKev8GNPY2W6kDwwzfP4qV8GrXP9VUvkK/fzUX2tLCtd3RGPrqhJkGptxA2w6WABMB8WJMmDw+v5q7Pw2T0wyM2ALDusFqHAz3OQA==;24:ZIPIJ1FAs+mUbkFfeEr5+toOw/Ubd1yFrZNzB1evC2BYUajUOr2Ca4x2WJY97uTcaKm7v3Kc/8H7c7Pai7P/r0Wet1DZobTZIjZQdZs7CBE= x-microsoft-antispam: UriScan:;BCL:0;PCL:0;RULEID:;SRVR:BY2PR0201MB1783; x-microsoft-antispam-prvs: x-exchange-antispam-report-test: UriScan:; x-exchange-antispam-report-cfa-test: BCL:0;PCL:0;RULEID:(601004)(2401047)(8121501046)(5005006)(10201501046)(3002001);SRVR:BY2PR0201MB1783;BCL:0;PCL:0;RULEID:;SRVR:BY2PR0201MB1783; x-forefront-prvs: 0903DD1D85 x-forefront-antispam-report: SFV:NSPM;SFS:(10019020)(53754006)(377454003)(52604005)(24454002)(52314003)(164054003)(122556002)(2950100001)(575784001)(2900100001)(2906002)(76176999)(54356999)(50986999)(3480700003)(586003)(66066001)(4326007)(86362001)(3846002)(6116002)(10400500002)(102836003)(76576001)(3280700002)(74316001)(3660700001)(19627405001)(92566002)(81166005)(3900700001)(19617315012)(99286002)(11100500001)(5004730100002)(87936001)(106116001)(1096002)(33656002)(1220700001)(19625215002)(5003600100002)(5008740100001)(5002640100001)(15975445007)(16236675004)(19580405001)(19580395003)(16799955002)(189998001)(110136002)(77096005);DIR:OUT;SFP:1102;SCL:1;SRVR:BY2PR0201MB1783;H:BY2PR0201MB1784.namprd02.prod.outlook.com;FPR:;SPF:None;MLV:sfv;LANG:en; spamdiagnosticoutput: 1:23 spamdiagnosticmetadata: NSPM Content-Type: multipart/alternative; boundary="_000_BY2PR0201MB17840923D3AF209A4ADD914DBF9E0BY2PR0201MB1784_" MIME-Version: 1.0 X-OriginatorOrg: zend.com X-MS-Exchange-CrossTenant-originalarrivaltime: 05 Apr 2016 14:14:03.5447 (UTC) X-MS-Exchange-CrossTenant-fromentityheader: Hosted X-MS-Exchange-CrossTenant-id: 32210298-c08b-4829-8097-6b12c025a892 X-MS-Exchange-Transport-CrossTenantHeadersStamped: BY2PR0201MB1783 Subject: Re: Object getter method optimization From: dmitry@zend.com (Dmitry Stogov) --_000_BY2PR0201MB17840923D3AF209A4ADD914DBF9E0BY2PR0201MB1784_ Content-Type: text/plain; charset="iso-2022-jp" Content-Transfer-Encoding: quoted-printable I think, op_array->type and op_array->fn_flags can't be reused. Also, usage of op_array->run_time_cache is safer (I remember, I saw some SI= GSEGV with your patch and opcache.protect_memory=3D1) Most probably, I'll able to return to this idea only at the end of the week= or even on next week. Thanks. Dmitry. ________________________________ From: Lin Yo-An Sent: Tuesday, April 5, 2016 17:00 To: Dmitry Stogov Cc: Xinchen Hui; Nikita Popov; Bob Weinand; Joe Watkins; internals Subject: Re: Object getter method optimization Hi Dmitry, Glad to hear your news, I just checked your patch and I like the approach y= ou've done. :] I'm also still working on this idea this week, the const value accessor sup= port was just added today. And I guess we may also support setters in the = future (if possible) my thought is: - I think the getter optimization is useful since getter methods are heavil= y used in a lot of application like Drupal (like hundreds) - If we could produce more information in compile-time, we can reduce more = runtime cost when executing the opcode handler. This way, we can reduce the= impact to the overall performance. - I found the first two bytes in zend_op_array produces a 2 bytes room on 3= 2bit machine and even more on 64bit machine because the memory alignment (n= ot sure if it could be optimzed when memory alignment optimization is not e= nabled with gcc) My first attempt was to add a new flag in op_array->type, however it's alre= ady full, all bits are used currently. I think we can either extend the op_array type to uint32 or just add a new = zend_uchar field to save the information (from the 2 bytes room). And using= cache slot to save the property offset information. This field will be not only for simple getters, but also for simple setters= and functions return const or return values that are simplified to scalar = value. Your thoughts? Cheers, Yo-An On Tue, Apr 5, 2016 at 7:29 PM, Dmitry Stogov > wrote: Hi Yo-An Lin, I spent few hours working on your idea and came to the following path. https://gist.github.com/dstogov/2221ffc21ac16311c958a4830dbcee0f I tried to keep binary compatibility, minimize run-time checks overhead and= fix related problems and leaks. BTW I'm not sure, if I like the patch even in this state. The patch significantly speed-ups getters (more than 2 times) in small cost= for all other methods, but the final effect on application may be negative= . Of course, we may add specialized opcode for INIT_METHOD_CALL without argum= ents, that would almost completely eliminate overhead. Anyway, I like to listen opinions: - if we should include such optimizations? - do you see any other applications to similar optimizations? Thanks. Dmitry. ________________________________ From: Lin Yo-An > Sent: Sunday, April 3, 2016 11:10 To: Xinchen Hui Cc: Dmitry Stogov; internals; Nikita Popov Subject: Re: Object getter method optimization I submitted the new benchmark result here: Benchmark Result Getter Method Only https://gist.github.com/8cd230a5601cbe38439661adf3caca0d Without getter optimization (3 runs): 151.0169506073ms With getter optimization (3 runs) 39.201021194458ms Template Engine Benchmark https://gist.github.com/a23cf294dfcf74683b8f02d93a47bc5b With getter optimization: 1118ms Without getter optimization: 1235ms Affect Other Microbench result: https://gist.github.com/c9s/0273ac21631562724cabf8= 6c42e86e32 On Sat, Apr 2, 2016 at 11:29 AM, Lin Yo-An > wrote: Hi Xinchen Hui, The magic get method is not being optimized. This optimization only focuses= on simple getter, which is used in a lot of OO-based appoications like Sym= fony or Drupal. Hi Dimitry, Thanks for reviewing the code, comments are helpful. :) could you explain a= little bit of how runtime_cache_slot works? I think adding the property_offset in op_array is kinda like a workaround = for POC, and I want to remove it from op_array. Cheers, Yo-An Xinchen Hui > =1B$B1w=1B(B 2016= =1B$BG/=1B(B4=1B$B7n=1B(B1=1B$BF|=1B(B =1B$B@14|8^UmF;!'=1B(B Hey: On Fri, Apr 1, 2016 at 4:35 PM, Lin Yo-An wrote: Hi Dmitry, Nikita, Andrea My implementation now is able to get the property offset and fetch object p= roperty directly without invoking zend_std_read_property and pushing new ca= ll 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 p= roperty offset in the accessor field and mark the method as a "getter". I am not sure if I understand you correctly, but.. have you consider this c= ase? a; } else { return $this->b; } } } $a =3D new A(); echo $a->nomeaning; echo $a->nomeaning; ?> thanks 3. When Zend Engine second time invoke the getter method, it checks the acc= essor field and try to read the property value directly instead a "method c= all" 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_MET= HOD_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 st= ore 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 wrote: Hi Yo-An Lin, This "run-time inlining" approach may work. PHP compiler (or optimizer) may mark functions and methods suitable for "ru= n-time" inlining (e.g. methods without arguments and FETCH_OBJ_R UNUSED, CO= NST -> TMP; RETURN TMP). Then INIT_METHOD_CALL may check this flag and execute "optimized code seque= nce" instead of pushing stack frame and real call. However, I'm not sure what kind of performance impact this may make, becaus= e we will have to make additional check on each INIT_METHOD_CALL execution. Thanks. Dmitry. ________________________________ From: Lin Yo-An 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 =3D $worker->getStatus(); } inside ma= in.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 w= e 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 ju= st 2 op codes (FETCH_OBJ_R and RETURN), we then denote the method is a "get= ter method" And the next time, when we execute the same method, we found the "getter me= thod" flag, we simply execute FETCH_OBJ_R on that object and return the val= ue 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 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 cach= es. Thanks. Dmitry. ________________________________________ From: Lin Yo-An 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 -- Xinchen Hui @Laruence http://www.laruence.com/ -- Sent from Gmail Mobile -- Best Regards, Yo-An Lin -- Best Regards, Yo-An Lin --_000_BY2PR0201MB17840923D3AF209A4ADD914DBF9E0BY2PR0201MB1784_--