From: mame@... Date: 2019-11-17T16:49:28+00:00 Subject: [ruby-core:95870] [Ruby master Bug#16351] Why do Keyword arguments to initialize allocate a Hash, but not for other methods? Issue #16351 has been updated by mame (Yusuke Endoh). nobu (Nobuyoshi Nakada) wrote: > By changing the last calling line as the following with making that `initialize` method public, you could observe the same numbers as `FooWithPlainParams`. > ```ruby > FooWithKeyword.allocate.initialize(a: 1, b: 2, c: 3) > ``` I'd like to add a note: `allocate.initialize` just demonstrates the reason for the behavior. Never do write that in your code. Currently, @ko1 is addressing this kind of issue fundamentally by a mechanism to write almost all builtin methods in Ruby. If Class#new is written in Ruby, and if a lazy allocation of keyword rest hash is introduced, the extra allocation will be removed. ---------------------------------------- Bug #16351: Why do Keyword arguments to initialize allocate a Hash, but not for other methods? https://bugs.ruby-lang.org/issues/16351#change-82705 * Author: brunoe (Bruno Escherl) * Status: Closed * Priority: Normal * Assignee: * Target version: * ruby -v: ruby 2.7.0dev (2019-11-17T04:12:06Z trunk a8e4a9f03a) [x86_64-darwin19] * Backport: 2.5: UNKNOWN, 2.6: UNKNOWN ---------------------------------------- Hello, while working on improving memory allocations in one of my apps, I stumbled upon the following behavior. I measured three different ways of passing variables to a new `Object`, using plain params, using a hash and using keyword arguments. ```ruby class FooWithPlainParams def initialize(a, b, c) @a = a @b = b @c = c end end class FooWithOptionsHash def initialize(options = {}) @a = options[:a] @b = options[:b] @c = options[:c] end end class FooWithKeyword def initialize(a:, b:, c:) @a = a @b = b @c = c end end ``` I used memory_profiler gem to measure the allocations with the attached script, calling new 100 times, using ruby 2.6.5p114 (2019-10-01 revision 67812) [x86_64-darwin19] `FooWithPlainParams` not surprisingly just reported "Total allocated: 4000 bytes (100 objects)". `FooWithOptionsHash` reported "Total allocated: 27200 bytes (200 objects)" with 100 `Hash` allocations. This makes sense, since the params are passed on as a `Hash`. `FooWithKeywordArguments` reported "Total allocated: 50400 bytes (300 objects)" with 200 `Hash` allocations, which is a bit surprising. After that I checked out ruby-head and there `FooWithKeywordArguments.new` reports only 100 `Hash` allocations as `FooWithOptionsHash`. So that part seems to be fixed. What surprised me so was, that using the same way of passing parameters in another method, resulted in no allocated Hash according to memory_profiler gem. ```ruby class FooWithKeyword def foo(d:, e:, f:) @d = d; @e = e; @f = f end end ``` Calling `foo(d: 4, e: 5, f: 6)` on a `FooWithKeyword` object, does not show any allocations. What is the difference here between `foo` and `initialize`? ---Files-------------------------------- profile_foo.rb (837 Bytes) profile_initialize.rb (847 Bytes) -- https://bugs.ruby-lang.org/ Unsubscribe: