[#99115] [Ruby master Bug#17023] How to prevent String memory to be relocated in ruby-ffi — larskanis@...
Issue #17023 has been reported by larskanis (Lars Kanis).
22 messages
2020/07/10
[#99375] [Ruby master Feature#17055] Allow suppressing uninitialized instance variable and method redefined verbose mode warnings — merch-redmine@...
Issue #17055 has been reported by jeremyevans0 (Jeremy Evans).
29 messages
2020/07/28
[#101207] [Ruby master Feature#17055] Allow suppressing uninitialized instance variable and method redefined verbose mode warnings
— merch-redmine@...
2020/12/02
Issue #17055 has been updated by jeremyevans0 (Jeremy Evans).
[#101231] Re: [Ruby master Feature#17055] Allow suppressing uninitialized instance variable and method redefined verbose mode warnings
— Austin Ziegler <halostatue@...>
2020/12/03
What does this mean?
[ruby-core:99400] [Ruby master Feature#17055] Allow suppressing uninitialized instance variable and method redefined verbose mode warnings
From:
headius@...
Date:
2020-07-30 18:04:33 UTC
List:
ruby-core #99400
Issue #17055 has been updated by headius (Charles Nutter).
Some JRuby perspective...
Personally, I have never been a big fan of the warning, but I don't have a =
strong opinion one way or another. I am not surprised that avoiding initial=
ization is a faster on MRI because there's quite a few cycles spent for eve=
ry instance variable assignment.
The JRuby numbers are a little misleading. The benchmark generates methods =
that contain 1000 new object creations, which goes well over the maximum si=
ze for JRuby to JIT compile that code. As a result, most of the overhead is=
still in our interpreter. Here's my numbers with the original benchmark, t=
urning on invokedynamic to reduce the other overhead of the benchmark a bit:
```
[] ~/projects/jruby $ jruby -Xcompile.invokedynamic bench_ivar_init.rb =
Warming up --------------------------------------
initialized 1.499k i/100ms
uninitialized 2.106k i/100ms
Calculating -------------------------------------
initialized 15.914k (=B1 4.2%) i/s - 79.447k in 5.003069s
uninitialized 20.717k (=B1 3.8%) i/s - 105.300k in 5.091607s
Comparison:
uninitialized: 20716.5 i/s
initialized: 15913.7 i/s - 1.30x (=B1 0.00) slower
[] ~/projects/jruby $ rvm ruby-2.7.0 do ruby bench_ivar_init.rb =
Warming up --------------------------------------
initialized 342.000 i/100ms
uninitialized 714.000 i/100ms
Calculating -------------------------------------
initialized 3.410k (=B1 2.3%) i/s - 17.100k in 5.017475s
uninitialized 6.967k (=B1 2.6%) i/s - 34.986k in 5.025282s
Comparison:
uninitialized: 6966.7 i/s
initialized: 3409.9 i/s - 2.04x (=B1 0.00) slower
```
Modifying the script to actually JIT compile (10 allocations instead of 100=
0) shows the difference between initialized and uninitialized better. When =
JIT compiled, uninitialized variable accesses amount to two memory reads (v=
ariable slot, nil in memory) and a null check, and initializing to nil amou=
nts to a memory move. The initialization can probably be eliminated if the =
allocation is eliminated, but it is harder to do otherwise.
```
[] ~/projects/jruby $ jruby -Xcompile.invokedynamic bench2.rb =
Warming up --------------------------------------
initialized 9.702k i/100ms
uninitialized 566.506k i/100ms
Calculating -------------------------------------
initialized 4.232M (=B110.4%) i/s - 20.374M in 4.977150s
uninitialized 17.564M (=B133.4%) i/s - 66.848M in 5.016887s
Comparison:
uninitialized: 17564016.6 i/s
initialized: 4231794.4 i/s - 4.15x (=B1 0.00) slower
[] ~/projects/jruby $ rvm ruby-2.7.0 do ruby bench_ivar_init.rb =
Warming up --------------------------------------
initialized 342.000 i/100ms
uninitialized 714.000 i/100ms
Calculating -------------------------------------
initialized 3.410k (=B1 2.3%) i/s - 17.100k in 5.017475s
uninitialized 6.967k (=B1 2.6%) i/s - 34.986k in 5.025282s
Comparison:
uninitialized: 6966.7 i/s
initialized: 3409.9 i/s - 2.04x (=B1 0.00) slower
```
I do wonder if nil initialization could be optimized away by MRI, though. I=
f we could detect that this was the first assignment of an instance variabl=
e in a new, untouched object, that assignment would be unnecessary. I know =
some JVMs also use read barriers to lazily initialized reference fields to =
null, avoiding the cost of zeroing that memory just to have it get overwrit=
ten moments later. There are options.
----------------------------------------
Feature #17055: Allow suppressing uninitialized instance variable and metho=
d redefined verbose mode warnings
https://bugs.ruby-lang.org/issues/17055#change-86843
* Author: jeremyevans0 (Jeremy Evans)
* Status: Open
* Priority: Normal
----------------------------------------
These two verbose mode warnings are both fairly common and have good reason=
s why you would not want to warn about them in specific cases. Not initial=
izing instance variables to nil can be much better for performance, and red=
efining methods without removing the method first is the only safe approach=
in multi-threaded code.
There are reasons that you may want to issue verbose warnings by default in=
these cases. For uninitialized instance variables, it helps catch typos. =
For method redefinition, it could alert you that a method already exists wh=
en you didn't expect it to, such as when a file is loaded multiple times wh=
en it should only be loaded once.
I propose we keep the default behavior the same, but offer the ability to o=
pt-out of these warnings by defining methods. For uninitialized instance v=
ariables in verbose mode, I propose we call `expected_uninitialized_instanc=
e_variable?(iv)` on the object. If this method doesn't exist or returns fa=
lse/nil, we issue the warning. If the method exists and returns true, we s=
uppress the warning. Similarly, for redefined methods, we call `expected_r=
edefined_method?(method_name)` on the class or module. If the method doesn=
't exist or returns false/nil, we issue the warning. If the method exists =
and returns true, we suppress the warning.
This approach allows high performance code (uninitialized instance variable=
s) and safe code (redefining methods without removing) to work without verb=
ose mode warnings.
I have implemented this support in a pull request: https://github.com/ruby/=
ruby/pull/3371
-- =
https://bugs.ruby-lang.org/
Unsubscribe: <mailto:[email protected]?subject=3Dunsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-core>