[ruby-core:95870] [Ruby master Bug#16351] Why do Keyword arguments to initialize allocate a Hash, but not for other methods?
From:
mame@...
Date:
2019-11-17 16:49:28 UTC
List:
ruby-core #95870
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: <mailto:[email protected]?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-core>