Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:92075 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 87459 invoked from network); 3 Apr 2016 08:10:23 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 3 Apr 2016 08:10:23 -0000 Authentication-Results: pb1.pair.com smtp.mail=cornelius.howl@gmail.com; spf=pass; sender-id=pass Authentication-Results: pb1.pair.com header.from=cornelius.howl@gmail.com; sender-id=pass Received-SPF: pass (pb1.pair.com: domain gmail.com designates 209.85.214.181 as permitted sender) X-PHP-List-Original-Sender: cornelius.howl@gmail.com X-Host-Fingerprint: 209.85.214.181 mail-ob0-f181.google.com Received: from [209.85.214.181] ([209.85.214.181:35662] helo=mail-ob0-f181.google.com) by pb1.pair.com (ecelerity 2.1.1.9-wez r(12769M)) with ESMTP id C4/27-29546-6EFC0075 for ; Sun, 03 Apr 2016 04:10:14 -0400 Received: by mail-ob0-f181.google.com with SMTP id fp4so77094614obb.2 for ; Sun, 03 Apr 2016 01:10:14 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=mime-version:in-reply-to:references:date:message-id:subject:from:to :cc; bh=yc34cgEaxx4JwF10qWMCTF2Pg5GBfBANsM3DtWDAKlI=; b=eTPDBmUwDFlv2HLqXvFM65fpe1PJaUI8MHuCwLNwMdz/ZKsEMpzGiSygl8YMEtgLW/ 1t1Mq7eKFx7BHz1bxevg2+9cJyDPPxrAUIJ6S2I6rkYoMhzybTjiFLl4gpOawFqR/sM9 oeyeKvXZ5L78NWJYzVoTj0V6S6czwj6fVwHWKESheX+2zgYY2NyOqYGESEnAt+MqJ0U1 Ors5HAwyToWxkLHRH4tvqvtlAlAeNW88rCWiDajsY+6NDZnhFsG2M1ULELT4j8TBMxQr bQ3BzFZQ3Fd65O0FtqyaHt6u04KixGn+poBUuFxWLjOTQylmQ/TFTL9GFqygU9fDgJHW Gzqg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:in-reply-to:references:date :message-id:subject:from:to:cc; bh=yc34cgEaxx4JwF10qWMCTF2Pg5GBfBANsM3DtWDAKlI=; b=IoCfoBi86ukNW8hBHpFHyyMuyHyKCA3eF6OzwQpfLQGGut1gZtverFHSjwbzABkV/7 UvJsXlCs5C+NhiLK0pyXTHCqmgfaTN7NNsnrcnRMLqu5ggQ5/UB0Z5nSyE2goBVPL5uy mi9w2maVpJqvYci/tNPhNQcPwgiZrZCkJeK3le9zrw2dT/2aRfPXXywCVnKBShZX0O9i Ovd814vT/ZX6NAiUQkZORPhrkOqHxiox3VEFxdrNlsKqYh7P8tJmJxnB2IhoY3qU8e9g qvlV0Msmsg+DmcnH8bqagmAJBfVPpiK1kwKhuUHxmdF/mu+sBlagu0+QDXEuTHKeudDK uySg== X-Gm-Message-State: AD7BkJIO8b5uv5DYWGg7o/gG4m9E/Cc7vzSsp2OC+xxJmvkjD2/EwdX4utpw1W2/jlyK1Ql/+0/UFfFfxaEjfA== MIME-Version: 1.0 X-Received: by 10.182.158.42 with SMTP id wr10mr265535obb.37.1459671011376; Sun, 03 Apr 2016 01:10:11 -0700 (PDT) Received: by 10.157.7.194 with HTTP; Sun, 3 Apr 2016 01:10:11 -0700 (PDT) In-Reply-To: References: Date: Sun, 3 Apr 2016 16:10:11 +0800 Message-ID: To: Xinchen Hui Cc: Dmitry Stogov , internals , Nikita Popov Content-Type: multipart/alternative; boundary=089e01537ea21f46c5052f90240f Subject: Re: Object getter method optimization From: cornelius.howl@gmail.com (Lin Yo-An) --089e01537ea21f46c5052f90240f Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: quoted-printable I submitted the new benchmark result here: Benchmark ResultGetter 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/0273ac21631562724cabf86c42e86e32 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 Symfony 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 workaroun= d > for POC, and I want to remove it from op_array. > > > Cheers, Yo-An > > > Xinchen Hui =E6=96=BC 2016=E5=B9=B44=E6=9C=881=E6=97= =A5 =E6=98=9F=E6=9C=9F=E4=BA=94=E5=AF=AB=E9=81=93=EF=BC=9A > > 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 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 "get= ter". >>> >> I am not sure if I understand you correctly, but.. have you consider thi= s >> case? >> >> > class A { >> private $a =3D 1; >> private $b =3D 2; >> public function __get($name) { >> static $is_first =3D 1; >> if ($is_first) { >> $is_first =3D 0; >> return $this->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 >>> 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 offse= t. >>> >>> 3. Added op code check in zend_compile (The pass_two() function) to mar= k >>> 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 ca= n >>> 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 wrote: >>> >>>> Hi Yo-An Lin, >>>> >>>> >>>> This "run-time inlining" approach may work. >>>> >>>> >>>> PHP compiler (or optimizer) may mark functions and methods suitable fo= r >>>> "run-time" inlining (e.g. methods without arguments and FETCH_OBJ_R UN= USED, >>>> 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 >>>> *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(); } insi= de >>>> 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 $wor= ker >>>> CV unless we know we have to compile worker.php before main.php and ad= d 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 metho= d 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 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 inlin= e >>>>> caches. >>>>> >>>>> 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 > --=20 Best Regards, Yo-An Lin --089e01537ea21f46c5052f90240f--