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:ruby-core-request / ruby-lang.org?subject=3Dunsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-core>