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>
lmpx.com only provides a reader for public news (NNTP) servers. It is not
affiliated with the servers or forums shown here and is not responsible for
the content of articles, which is written by their respective authors.