From: bruno@... Date: 2019-11-17T12:54:45+00:00 Subject: [ruby-core:95868] [Ruby master Bug#16351] Why do Keyword arguments to initialize allocate a Hash, but not for other methods? Issue #16351 has been reported by brunoe (Bruno Escherl). ---------------------------------------- Bug #16351: Why do Keyword arguments to initialize allocate a Hash, but not for other methods? https://bugs.ruby-lang.org/issues/16351 * Author: brunoe (Bruno Escherl) * Status: Open * 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. ``` 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. ``` 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_initialize.rb (837 Bytes) -- https://bugs.ruby-lang.org/ Unsubscribe: