From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on dcvr.yhbt.net X-Spam-Level: X-Spam-ASN: AS4713 221.184.0.0/13 X-Spam-Status: No, score=-2.7 required=3.0 tests=AWL,BAYES_00, DKIM_ADSP_CUSTOM_MED,FORGED_GMAIL_RCVD,FREEMAIL_FORGED_FROMDOMAIN, FREEMAIL_FROM,HEADER_FROM_DIFFERENT_DOMAINS,MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED,SPF_HELO_NONE,SPF_PASS shortcircuit=no autolearn=no autolearn_force=no version=3.4.2 Received: from neon.ruby-lang.org (neon.ruby-lang.org [221.186.184.75]) by dcvr.yhbt.net (Postfix) with ESMTP id 0B0041F463 for ; Wed, 27 Nov 2019 15:50:02 +0000 (UTC) Received: from neon.ruby-lang.org (localhost [IPv6:::1]) by neon.ruby-lang.org (Postfix) with ESMTP id D7EFA120AF8; Thu, 28 Nov 2019 00:49:42 +0900 (JST) Received: from o1678948x4.outbound-mail.sendgrid.net (o1678948x4.outbound-mail.sendgrid.net [167.89.48.4]) by neon.ruby-lang.org (Postfix) with ESMTPS id 03F9D120AF7 for ; Thu, 28 Nov 2019 00:49:40 +0900 (JST) Received: by filter0182p3mdw1.sendgrid.net with SMTP id filter0182p3mdw1-11675-5DDE9B19-21 2019-11-27 15:49:45.867548961 +0000 UTC m=+662052.749643421 Received: from herokuapp.com (unknown [3.87.7.191]) by ismtpd0046p1iad1.sendgrid.net (SG) with ESMTP id 9bZs78v0SoS9YHAlp6Odaw for ; Wed, 27 Nov 2019 15:49:45.798 +0000 (UTC) Date: Wed, 27 Nov 2019 15:49:45 +0000 (UTC) From: eregontp@gmail.com Message-ID: References: Mime-Version: 1.0 X-Redmine-MailingListIntegration-Message-Ids: 71622 X-Redmine-Project: ruby-trunk X-Redmine-Issue-Id: 16188 X-Redmine-Issue-Author: Eregon X-Redmine-Issue-Assignee: jeremyevans0 X-Redmine-Sender: Eregon X-Mailer: Redmine X-Redmine-Host: bugs.ruby-lang.org X-Redmine-Site: Ruby Issue Tracking System X-Auto-Response-Suppress: All Auto-Submitted: auto-generated X-SG-EID: =?us-ascii?Q?KippOI8ZHtTweq7XfQzW93937kJ4QNWwSBuHnaMEcr37UTQaX907APR8HmLDNR?= =?us-ascii?Q?hbvOycDUQ9zNz2ciN+DZXkp2wNbVPxo4uDMc4Xt?= =?us-ascii?Q?2OMbErDfWbN4Y40qkqTmpqrWmU9BWliLHOjnU5A?= =?us-ascii?Q?Ays0j8PdglEeiJbvIg8ZMrf3AjfTwbIbWpJgoRV?= =?us-ascii?Q?Nd5ErTmpymVM309zIwhTeUzt0pjnJLFWkeA=3D=3D?= To: ruby-core@ruby-lang.org X-ML-Name: ruby-core X-Mail-Count: 95988 Subject: [ruby-core:95988] [Ruby master Misc#16188] What are the performance implications of the new keyword arguments in 2.7 and 3.0? X-BeenThere: ruby-core@ruby-lang.org X-Mailman-Version: 2.1.15 Precedence: list Reply-To: Ruby developers List-Id: Ruby developers List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Errors-To: ruby-core-bounces@ruby-lang.org Sender: "ruby-core" Issue #16188 has been updated by Eregon (Benoit Daloze). jeremyevans0 (Jeremy Evans) wrote: > There are a ton of other changes in 2.7 that could affect performance besides `ruby2_keywords`. Any specific guess? > I don't think those references are in a case the benchmark would hit, but I could be wrong. As you mentioned in a later comment, you prepared your own diff for just removing `ruby2_keywords`. Your original diff kept quite a lot more complicated code in `setup_parameters_complex`, so I think that diff is already more precise and seems to show an higher overhead (see my previous comment). > So a 10% performance difference would be 0.1-1% difference in a real world benchmark. Still, if there are `foo(*args)` calls in a performance-sensitive part of a real world benchmark I'd expect it can be noticeable. > Well, we could guess, or you could pick an existing real world benchmark and run it and report the results for: OptCarrot might be affected, it uses `send(*DISPATCH[@opcode])` in the main loop of the CPU: https://github.com/mame/optcarrot/blob/ded9d9379324d968867d1e052dbbc811d45afd4d/lib/optcarrot/cpu.rb#L939 However the CPU is only a small part compared to the PPU in OptCarrot. > Do all non-`ruby2_keywords` tests still pass with that? If so, what are the benchmark results with the patch? I'd think so, I just manually removed dead code based on RHASH_PASS_AS_KEYWORDS never happening. > > Can you give an example the above approach (capturing the call inside the lambda) cannot handle? > > No. Certainly there is a way to always move code into the lexical scope. It is a more difficult change and it makes the resulting code harder to understand, but it is possible. I think it's only more difficult in rather rare cases, and it makes it significantly easier to understand and use than `ruby2_keywords`. ---------------------------------------- Misc #16188: What are the performance implications of the new keyword arguments in 2.7 and 3.0? https://bugs.ruby-lang.org/issues/16188#change-82821 * Author: Eregon (Benoit Daloze) * Status: Open * Priority: Normal * Assignee: jeremyevans0 (Jeremy Evans) ---------------------------------------- In #14183, keyword arguments became further separated from positional arguments. Contrary to the original design though, keyword and positional arguments are not fully separated for methods not accepting keyword arguments. Example: `foo(key: :value)` will `def foo(hash)` will pass a positional argument. This is of course better for compatibility, but I wonder what are the performance implications. The block argument is completely separate in all versions, so no need to concern ourselves about that. In Ruby <= 2.6: * The caller never needs to know about the callee's arguments, it can just take all arguments and pass them as an array. The last argument might be used to extract keyword, but this is all done at the callee side. * Splitting kwargs composed of Symbol and non-Symbol keys can be fairly expensive, but it is a rare occurrence. If inlining the callee and kwargs are all passed as a literal Hash at the call site, there shouldn't be any overhead compared to positional arguments once JIT'ed. In Ruby 2.7: * The caller needs to pass positional and keyword arguments separately, at least when calling a method accepting kwargs. But, if it calls a methods not accepting kwargs, then the "kwargs" (e.g. `foo(key: :value)`) should be treated just like a final Hash positional argument. * (If we had complete separation, then we could always pass positional and keyword arguments separately, so the caller could once again ignore the callee) How is the logic implemented in MRI for 2.7? Specializing the caller for a given callee is a well-known technique. However, it becomes more difficult if different methods are called from the same callsite (polymorphic call), especially if one accepts kwargs and another does not. In that case, I think we will see a performance cost to this approach, by having to pass arguments differently based on the method to be called. What about delegation using `ruby2_keywords`? Which checks does that add (compared to 2.6) in the merged approach with the Hash flag? -- https://bugs.ruby-lang.org/