Ruby Issue Tracking System: Issueshttps://bugs.ruby-lang.org/https://bugs.ruby-lang.org/favicon.ico?17113305112023-01-03T14:00:26ZRuby Issue Tracking System
Redmine Ruby master - Misc #19304 (Open): Kernel vs Object documentationhttps://bugs.ruby-lang.org/issues/193042023-01-03T14:00:26Zzverok (Victor Shepelev)zverok.offline@gmail.com
<p>The restating of the problems raised in <a class="issue tracker-2 status-6 priority-4 priority-default closed" title="Feature: Move public methods from Kernel to Object (Rejected)" href="https://bugs.ruby-lang.org/issues/19300">#19300</a>, from scratch.</p>
<p>I believe it is rather a topic of <strong>community significance</strong> and would be happy if it is possible to <strong>discuss on dev-meeting</strong>, even if the outcome would probably "let's change RDoc in this or that way".</p>
<p>So, the problem statement:</p>
<ol>
<li>
<code>Kernel</code> module defines two "types" of methods: private ones, that pretend to be global (like <code>puts</code>), but actually available from inside every object; and public ones (like <code>#class</code> or <code>#frozen?</code>) that are present in every object including <code>Kernel</code>.</li>
<li>Since the beginning of times, docs provided an illusion that the second type of the methods belongs to <code>Object</code> class, which is, in fact, devoid of its own definitions, just includes <code>Kernel</code>. This was handled by special RDoc hack (which, basically, forcefully <a href="https://github.com/ruby/rdoc/blob/017bb9fa496ee0e0959facba694a053008d1ecb0/lib/rdoc/parser/c.rb#L477" class="external">reattached definition</a> of public methods if they are defined in <code>Kernel</code>, to <code>Object</code>)</li>
<li>The RDoc hack was working in C code only, so after introduction of <code>kernel.rb</code> the illusion started to crumble: methods like <code>#tap</code>, <code>#then</code>, <code>#class</code> <a href="https://docs.ruby-lang.org/en/3.2/Kernel.html" class="external">are now documented</a> as belonging to <code>Kernel</code> (breaking the tradition of public methods being documented in <code>Object</code>)</li>
<li>This is all inconsistent and confusing, and I believe, adds to friction both for newcomers and curious investigators of the language!</li>
</ol>
<p>Additionally, I believe:</p>
<ol>
<li>That the distinction of "two kinds of methods" is useful (saying from a practical experience with explaining Ruby while mentoring, writing articles, and discussing with colleagues)</li>
<li>But, considering everything, I agree with what <a class="user active user-mention" href="https://bugs.ruby-lang.org/users/772">@Eregon (Benoit Daloze)</a> and <a class="user active user-mention" href="https://bugs.ruby-lang.org/users/4">@nobu (Nobuyoshi Nakada)</a> say in <a class="issue tracker-2 status-6 priority-4 priority-default closed" title="Feature: Move public methods from Kernel to Object (Rejected)" href="https://bugs.ruby-lang.org/issues/19300">#19300</a>: pretending that methods belong not to the module they really belong to is not the optimal way to document things!</li>
</ol>
<p>So, the options I see (save for "do nothing and let things sort themselves somehow"):</p>
<ol>
<li>Change Ruby's implementation so public methods would really belong to <code>Object</code>. Actually, I don't believe anybody would agree to experiment on this scale, so just listing it here for completeness.</li>
<li>Just remove the RDoc hack; all methods would belong to <code>Kernel</code>, and maybe some introductory free-form text will instruct that they are different. <strong>Pro:</strong> Easy to do. <strong>Contra:</strong> The <code>Kernel</code> docs would be super-confusing.</li>
<li>Continue to maintain the hack in RDoc and extend it to <code>kernel.rb</code> (so methods like <code>#clone</code> and <code>#frozen?</code> would be still in <code>Object</code>). <strong>Pro:</strong> Relatively easy to do, will maintain structure many people used to. <strong>Contra:</strong> This is still a lie, methods belong to <code>Kernel</code>, not <code>Object</code>.</li>
<li>Adjust RDoc to a) be able to separately list <strong>public</strong> and <strong>private</strong> methods in two different lists, and add intro for <code>Kernel</code> explaining how to treat those. <strong>Pro:</strong> Probably the best correspondence to reality? <strong>Contra:</strong> Not sure how easy it is to change RDoc this way; and other renderers (like ruby-doc.com and rubyapi.org) would need to adjust themselves.</li>
</ol>
<p>So far, (4) looks the most reasonable (if (1) is 100% impossible, that is!)</p> Ruby master - Misc #19176 (Open): Missing insns_info for iseqs in ruby 3.2 built with debug optionshttps://bugs.ruby-lang.org/issues/191762022-12-03T13:25:59Zhurricup (Alexandr Evstigneev)hurricup@gmail.com
<p>I'm not quite sure it is a proper place to ask questions, correct me if I'm wrong.<br>
But I have a problem with ruby-3.2.0 previews. Looks like iseq is missing <code>insns_info</code>s.</p>
<p>It works fine in with pre-3.2 rubies but seems something has changed and I can't figure out - what exactly.</p>
<p>It looks like this:<br>
<img src="https://bugs.ruby-lang.org/attachments/download/9375/clipboard-202212031723-don1h.png" alt="" loading="lazy"></p>
<p>You may see that body, supposed to be a pointer to <code>iseq_insn_info_entry</code> contains some 0x7 pointing nowhere. And <code>size</code> for <code>insns_info</code> in all <code>iseq</code> I can find with iterating objspace is zero.</p> Ruby master - Misc #19142 (Open): Run test suites against 'install', based on ENV variable?https://bugs.ruby-lang.org/issues/191422022-11-22T22:39:07ZMSP-Greg (Greg L)
<p>Some time ago I believe there was discussion about:</p>
<pre><code>make
make test
make install
</code></pre>
<p>vs</p>
<pre><code>make
make install
make test
</code></pre>
<p>Some people preferred to not have to run install before test (disk space, time, etc).</p>
<p>Might an environment variable like <code>RUBY_TEST_FROM_INSTALL</code> or <code>RUBY_TEST_FROM_PATH</code> be<br>
added that would trigger the test suite to test against the Ruby install folder or the<br>
Ruby in PATH?</p>
<p>I believe a handful of files in the test system would need changes, as they load files<br>
using <code>require_relative</code>...</p>
<p>I think spec/mspec is already setup to do so.</p> Ruby master - Misc #19131 (Open): MatchData#values_at(): addressing with Range and Integer index ...https://bugs.ruby-lang.org/issues/191312022-11-15T15:33:18Zandrykonchin (Andrew Konchin)
<p>I've noticed a strange nuance and not sure whether it's intentional or not. In case it's intentional - it seems to me inconsistent.</p>
<p>I will illustrate it with the following example:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="sr">/(.)(.)(.)(.)/</span><span class="p">.</span><span class="nf">match</span><span class="p">(</span><span class="s2">"abcde"</span><span class="p">).</span><span class="nf">values_at</span><span class="p">(</span><span class="o">-</span><span class="mi">5</span><span class="o">..-</span><span class="mi">1</span><span class="p">)</span> <span class="c1"># => ["abcd", "a", "b", "c", "d"]</span>
<span class="sr">/(.)(.)(.)(.)/</span><span class="p">.</span><span class="nf">match</span><span class="p">(</span><span class="s2">"abcde"</span><span class="p">).</span><span class="nf">values_at</span><span class="p">(</span><span class="o">-</span><span class="mi">5</span><span class="p">)</span> <span class="c1"># => [nil]</span>
</code></pre>
<p>So with a negative index we can address the whole matched string (<code>0</code> element) with a Range argument but cannot with an Integer index.</p>
<p>We can index with negative values only captured values:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="sr">/(.)(.)(.)(.)/</span><span class="p">.</span><span class="nf">match</span><span class="p">(</span><span class="s2">"abcde"</span><span class="p">).</span><span class="nf">values_at</span><span class="p">(</span><span class="o">-</span><span class="mi">4</span><span class="p">)</span> <span class="c1"># => ["a"]</span>
<span class="sr">/(.)(.)(.)(.)/</span><span class="p">.</span><span class="nf">match</span><span class="p">(</span><span class="s2">"abcde"</span><span class="p">).</span><span class="nf">values_at</span><span class="p">(</span><span class="o">-</span><span class="mi">3</span><span class="p">)</span> <span class="c1"># => ["b"]</span>
<span class="sr">/(.)(.)(.)(.)/</span><span class="p">.</span><span class="nf">match</span><span class="p">(</span><span class="s2">"abcde"</span><span class="p">).</span><span class="nf">values_at</span><span class="p">(</span><span class="o">-</span><span class="mi">2</span><span class="p">)</span> <span class="c1"># => ["c"]</span>
<span class="c1"># ...</span>
</code></pre>
<p>I would expect <code>Range</code> and <code>Integer</code> arguments are handled consistently and either both allow to address the first element with negative index or both disallow it.</p>
<hr>
<pre><code>ruby -v
ruby 3.1.2p20 (2022-04-12 revision 4491bb740a) [x86_64-darwin21]
</code></pre> Ruby master - Misc #19123 (Open): Error handling of Struct#values_at and Array#values_at is sligh...https://bugs.ruby-lang.org/issues/191232022-11-11T17:29:41Zandrykonchin (Andrew Konchin)
<p><code>Struct#values_at</code> and `Array#values_at look pretty similar and handle all the complex cases of arguments (integer Ranges, list of Integers and mixing Ranges and Integers) in the same way.</p>
<p>Error handling is similar as well. In case of invalid Range argument they behave identically:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="n">clazz</span> <span class="o">=</span> <span class="no">Struct</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="ss">:name</span><span class="p">,</span> <span class="ss">:director</span><span class="p">,</span> <span class="ss">:year</span><span class="p">)</span>
<span class="n">movie</span> <span class="o">=</span> <span class="n">clazz</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="s1">'Sympathy for Mr. Vengeance'</span><span class="p">,</span> <span class="s1">'Chan-wook Park'</span><span class="p">,</span> <span class="mi">2002</span><span class="p">)</span>
<span class="n">array</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">]</span>
<span class="c1"># end is out of range </span>
<span class="n">movie</span><span class="p">.</span><span class="nf">values_at</span><span class="p">(</span><span class="mi">0</span><span class="o">..</span><span class="mi">4</span><span class="p">)</span> <span class="c1"># => ["Sympathy for Mr. Vengeance", "Chan-wook Park", 2002, nil, nil]</span>
<span class="n">array</span><span class="p">.</span><span class="nf">values_at</span><span class="p">(</span><span class="mi">0</span><span class="o">..</span><span class="mi">4</span><span class="p">)</span> <span class="c1"># => [0, 1, 2, nil, nil]</span>
<span class="c1"># beginning is out of range</span>
<span class="n">movie</span><span class="p">.</span><span class="nf">values_at</span><span class="p">(</span><span class="o">-</span><span class="mi">5</span><span class="o">..</span><span class="mi">4</span><span class="p">)</span> <span class="c1"># -5..4 out of range (RangeError)</span>
<span class="n">array</span><span class="p">.</span><span class="nf">values_at</span><span class="p">(</span><span class="o">-</span><span class="mi">5</span><span class="o">..</span><span class="mi">4</span><span class="p">)</span> <span class="c1"># -5..4 out of range (RangeError)</span>
</code></pre>
<p>But when Integer argument is passed - they handle out of range cases differently:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="c1"># end is out of range </span>
<span class="n">movie</span><span class="p">.</span><span class="nf">values_at</span><span class="p">(</span><span class="mi">4</span><span class="p">)</span> <span class="c1"># => offset 4 too large for struct(size:3) (IndexError)</span>
<span class="n">array</span><span class="p">.</span><span class="nf">values_at</span><span class="p">(</span><span class="mi">4</span><span class="p">)</span> <span class="c1"># => [nil]</span>
<span class="c1"># beginning is out of range</span>
<span class="n">movie</span><span class="p">.</span><span class="nf">values_at</span><span class="p">(</span><span class="o">-</span><span class="mi">5</span><span class="p">)</span> <span class="c1"># => offset -5 too small for struct(size:3) (IndexError)</span>
<span class="n">array</span><span class="p">.</span><span class="nf">values_at</span><span class="p">(</span><span class="o">-</span><span class="mi">5</span><span class="p">)</span> <span class="c1"># => [nil]</span>
</code></pre>
<p>So I am wondering what is the reason of such inconvenience. I suppose there may be a reason of this difference. But I see some benefits in consistent error handling.</p> Ruby master - Misc #19122 (Open): Use MADV_DONTNEED instead of MADV_FREE when freeing a Fiber's s...https://bugs.ruby-lang.org/issues/191222022-11-11T16:06:08Zsmcgivern (Sean McGivern)
<p>I'd like to propose that Ruby stops using MADV_FREE when freeing a Fiber's stack, and switches to using MADV_DONTNEED even when MADV_FREE is supported.</p>
<p>MADV_FREE is used in one place in the Ruby codebase, when freeing the stack of a freed Fiber: <a href="https://git.ruby-lang.org/ruby.git/tree/cont.c#n683" class="external">https://git.ruby-lang.org/ruby.git/tree/cont.c#n683</a></p>
<p>The comment for <code>fiber_pool_stack_free</code> says:</p>
<pre><code class="c syntaxhl" data-language="c"><span class="c1">// We advise the operating system that the stack memory pages are no longer being used.</span>
<span class="c1">// This introduce some performance overhead but allows system to relaim memory when there is pressure.</span>
</code></pre>
<p>Where possible (i.e. on Linux 4.5 and later), <code>fiber_pool_stack_free</code> uses <code>MADV_FREE</code> over <code>MADV_DONTNEED</code>. This has the side effect that memory statistics such as RSS will not reduce until and unless the OS actually reclaims that memory. If that doesn't happen, then the reported memory usage via RSS will be much higher than the 'real' memory usage.</p>
<p>If this was pervasive throughtout the Ruby codebase then that would be one thing, but currently this is just for Fiber. This means that:</p>
<ol>
<li>A program that doesn't use Fiber will have somewhat reliable RSS statistics on recent Linux.</li>
<li>A program that heavily uses Fiber (such as something using Async::HTTP) will see an inflated RSS statistic.</li>
</ol>
<p>Go made a similar change to the one I'm proposing here for similar reasons: <a href="https://github.com/golang/go/issues/42330" class="external">https://github.com/golang/go/issues/42330</a></p>
<blockquote>
<p>While <code>MADV_FREE</code> is somewhat faster than <code>MADV_DONTNEED</code>, it doesn't affect many of the statistics that <code>MADV_DONTNEED</code> does until the memory is actually reclaimed. This generally leads to poor user experience, like confusing stats in <code>top</code> and other monitoring tools; and bad integration with management systems that respond to memory usage.<br>
[...]<br>
I propose we change the default to prefer <code>MADV_DONTNEED</code> over <code>MADV_FREE</code>, to favor user-friendliness and minimal surprise over performance. I think it's become clear that Linux's implementation of <code>MADV_FREE</code> ultimately doesn't meet our needs.</p>
</blockquote>
<p>As an aside, MADV_FREE was not used in Ruby 3.1 (<a href="https://bugs.ruby-lang.org/issues/19101" class="external">https://bugs.ruby-lang.org/issues/19101</a>), and I haven't found any bugs filed about this behaviour other than that one.</p> Ruby master - Misc #19121 (Open): Time: utc offset argument's formats "+/-HH", "+/-HHMM", "+/-HHM...https://bugs.ruby-lang.org/issues/191212022-11-11T14:50:11Zandrykonchin (Andrew Konchin)
<p>I've noticed a strange difference between Ruby versions 2.7, 3.0 and 3.1.</p>
<p>The mentioned above formats are supported in Ruby 2.7 and Ruby 3.1 but aren't supported in Ruby 3.0.</p>
<p>So I am wondering whether supporting these formats is expected behaviour or a bug. In any case I would expect consistent behaviour in all the supported Ruby versions.</p>
<p>Ruby 2.7.4</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="no">Time</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="mi">2000</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="s2">"+05"</span><span class="p">)</span> <span class="c1"># => 2000-01-01 00:00:00 +0500</span>
<span class="no">Time</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="mi">2000</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="s2">"+0530"</span><span class="p">)</span> <span class="c1"># => 2000-01-01 00:00:00 +0530</span>
<span class="no">Time</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="mi">2000</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="s2">"+053037"</span><span class="p">)</span> <span class="c1"># => 2000-01-01 00:00:00 +0530</span>
</code></pre>
<p>Ruby 3.0.4</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="no">Time</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="mi">2000</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="s2">"+05"</span><span class="p">)</span>
<span class="c1">#(irb):1:in `initialize': "+HH:MM", "-HH:MM", "UTC" or "A".."I","K".."Z" expected for utc_offset (ArgumentError)</span>
<span class="no">Time</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="mi">2000</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="s2">"+0530"</span><span class="p">)</span>
<span class="c1">#(irb):2:in `initialize': "+HH:MM", "-HH:MM", "UTC" or "A".."I","K".."Z" expected for utc_offset (ArgumentError)</span>
<span class="no">Time</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="mi">2000</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="s2">"+053037"</span><span class="p">)</span>
<span class="c1">#(irb):3:in `initialize': "+HH:MM", "-HH:MM", "UTC" or "A".."I","K".."Z" expected for utc_offset (ArgumentError)</span>
</code></pre>
<p>Ruby 3.1.2</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="no">Time</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="mi">2000</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="s2">"+05"</span><span class="p">)</span> <span class="c1"># => 2000-01-01 00:00:00 +0500</span>
<span class="no">Time</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="mi">2000</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="s2">"+0530"</span><span class="p">)</span> <span class="c1"># => 2000-01-01 00:00:00 +0530</span>
<span class="no">Time</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="mi">2000</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="s2">"+053037"</span><span class="p">)</span> <span class="c1"># => 2000-01-01 00:00:00 +053037</span>
</code></pre> Ruby master - Misc #19098 (Open): Time#strftime: %z and widthhttps://bugs.ruby-lang.org/issues/190982022-11-01T17:49:20Zandrykonchin (Andrew Konchin)
<p>It seems <code>%z</code> behaves in some surprising way when it is combined with a width - sign <code>+</code> is placed at the beginning of the result string:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="no">Time</span><span class="p">.</span><span class="nf">now</span><span class="p">.</span><span class="nf">strftime</span><span class="p">(</span><span class="s2">"%10z"</span><span class="p">)</span>
<span class="o">=></span> <span class="s2">"+000000200"</span>
<span class="no">Time</span><span class="p">.</span><span class="nf">now</span><span class="p">.</span><span class="nf">strftime</span><span class="p">(</span><span class="s2">"%_10z"</span><span class="p">)</span>
<span class="o">=></span> <span class="s2">" +200"</span>
</code></pre>
<p>It seems a time zone offset is treated as a number. It probably makes sense with default format but it looks strange with <code>:</code> separators:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="no">Time</span><span class="p">.</span><span class="nf">now</span><span class="p">.</span><span class="nf">strftime</span><span class="p">(</span><span class="s2">"%10::z"</span><span class="p">)</span>
<span class="c1"># => "+002:00:00"</span>
</code></pre>
<p>So I would expect that <code>%z</code> directive output to be treated as a non-numerical and padded by default with spaces.</p> Ruby master - Misc #19052 (Open): Increased memory usage (RSS) for Ruby when compiled by gcchttps://bugs.ruby-lang.org/issues/190522022-10-14T00:16:31Zbosh-ecosystem-vmware (BOSH Ecosystem Team @ VMware)
<p>Hello! We have seen a large increase in memory usage as measured by resident set size (RSS) in our Ruby 3.1.2 programs when testing on Ubuntu Jammy (22.04). After further testing, we have narrowed down the problem as starting with Ubuntu Eoan (19.10). We first noticed this increase coming from a gem called <code>eventmachine v1.2.7</code>, which is a concurrency library that uses threads internally. That led us to try threads directly, and we came up with a simple Ruby program that reproduces the memory usage issue by spawning multiple threads through <code>Thread.new</code>.</p>
<p>We are unsure whether the problem extends beyond just <code>Thread.new</code>; it was the easiest problem to spot within our applications.</p>
<p>We are building Ruby from source using <code>ruby-install</code>, though have seen the problem in versions installed via <code>apt</code>.</p>
<p>We are seeking to understand the underlying cause of this memory bloat, and what we can do to prevent it.</p>
<p>Generally, we've been seeing similar total virtual memory allocated, only a difference in RSS usage.</p>
<p>On Ubuntu Disco (19.04) and prior, we see a relatively small increase in RSS upon spawning the threads, on the order of 20 kilobytes per thread. On Ubuntu Eoan and later, we see that RSS increases by 1 megabyte per thread.</p>
<p>When Ruby is compiled using <code>clang</code> instead of <code>gcc</code> on Ubuntu Eoan and later, the memory usage is comparable to older versions of Ubuntu.</p>
<p>We do not believe it is related to gcc version <em>by itself</em>, as we tried compiling Ruby using gcc 9 on Ubuntu Disco, and did not encounter the memory problem. On the theory that it may be a memory fragmentation issue, we tried both using the <code>MALLOC_ARENA_MAX</code> runtime environment variable, and compiling Ruby against <code>jemalloc</code>. Neither of these reduced RSS usage.</p>
<p>Here are the memory differences when simply calling <code>Thread.new</code> 10 times:</p>
<table>
<thead>
<tr>
<th>Configuration</th>
<th>RSS before spawning threads</th>
<th>RSS after spawning threads</th>
<th>Diff</th>
</tr>
</thead>
<tbody>
<tr>
<td>Disco + gcc 8</td>
<td>13596 kB</td>
<td>13800 kB</td>
<td>204 kB</td>
</tr>
<tr>
<td>Disco + gcc 9</td>
<td>13880 kB</td>
<td>14088 kB</td>
<td>208 kB</td>
</tr>
<tr>
<td>Eoan + gcc 9</td>
<td>22268 kB</td>
<td>32672 kB</td>
<td>10404 kB</td>
</tr>
<tr>
<td>Eoan + clang</td>
<td>13976 kB</td>
<td>14180 kB</td>
<td>204 kB</td>
</tr>
<tr>
<td>Jammy + gcc 11</td>
<td>22208 kB</td>
<td>32608 kB</td>
<td>10400 kB</td>
</tr>
<tr>
<td>Jammy + clang</td>
<td>13668 kB</td>
<td>13872 kB</td>
<td>204 kB</td>
</tr>
<tr>
<td>Jammy + jemalloc</td>
<td>24212 kB</td>
<td>35216 kB</td>
<td>11004 kB</td>
</tr>
<tr>
<td>Jammy + apt</td>
<td>21308 kB</td>
<td>31712 kB</td>
<td>10404 kB</td>
</tr>
</tbody>
</table>
<p>We have attached the program and a series of Dockerfiles that replicate the test environments. While the reproduction is using Docker files, we have seen this same behavior on actual VMs. To run a particular Docker config, use <code>./run.sh <DIRECTORY></code>, e.g. <code>./run.sh jammy-clang</code>.</p>
<p>Does anyone understand why there is an increase in resident set size (RSS) when Ruby is compiled with gcc vs clang?<br>
Is there additional configuration (flags, etc) that could be sent to gcc to get equivalent memory usage on Jammy that is seen when using Disco or clang?</p> Ruby master - Misc #18984 (Open): Doc for Range#size for Float/Rational does not make sensehttps://bugs.ruby-lang.org/issues/189842022-08-29T14:39:13Zmasasakano (Masa Sakano)
<p>When <code>Range</code> consists of any Numeric, according to <a href="https://ruby-doc.org/core-3.1.2/Range.html#method-i-size" class="external">Official docs for Ruby-3.1.2</a>, <code>Range#size</code> should,</p>
<blockquote>
<p>Returns the count of elements in self if both begin and end values are numeric;</p>
</blockquote>
<p>Indeed, when <code>Range</code> consists of only <code>Integer</code>, this makes sense.<br>
However, when the begin value of <code>Range</code> is a <code>Float</code> or <code>Rational</code>, "<em>the count of elements</em>" does not make sense. Such Ranges are not iteratable, suggesting there are no such things as "elements":</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="p">(</span><span class="mf">0.51</span><span class="o">..</span><span class="mi">5</span><span class="p">.</span><span class="nf">quo</span><span class="p">(</span><span class="mi">2</span><span class="p">)).</span><span class="nf">each</span><span class="p">{}</span> <span class="c1"># => TypeError</span>
</code></pre>
<p>Yet, <code>Range#size</code> of such Ranges returns an Integer</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="p">(</span><span class="mf">0.51</span><span class="o">..</span><span class="mi">5</span><span class="p">.</span><span class="nf">quo</span><span class="p">(</span><span class="mi">2</span><span class="p">)).</span><span class="nf">size</span> <span class="c1"># => 2</span>
</code></pre>
<p>It seems both begin and end values of a Range are rounded (<code>Numeric#round</code>) to the nearest Integer before <code>Range#size</code> is calculated.</p>
<p>If this is the specification, I suggest it should be clearly stated in the <a href="https://ruby-doc.org/core-3.1.2/Range.html#method-i-size" class="external">Official docs</a>, avoiding the confusing expression "the count of elements", because "elements" are not unambiguously defined for Range of Float/Rational.</p> Ruby master - Misc #18924 (Open): lstrlen and lstrcat still in usehttps://bugs.ruby-lang.org/issues/189242022-07-17T20:42:52Ztest35965@gmail.com (Alexander Riccio)
<p>In practice, as-used, this is probably benign, but is a Terrible Idea.</p>
<p>There are several places where someone's still using lstrcat and lstrlen in ruby.</p>
<p>lstrcat catches and <em><strong>suppresses</strong></em> access violations. I have been burned by this in the wild as a user of other software, corrupting data and causing mysterious crashes. There's no good reason to use these functions. IIRC, they may even date back to before the standard library was standard (on windows?)?</p>
<p>Swapping them for standard functions like strcpy is not great, but can only break code that was incorrect and memory-corrupting already.</p> Ruby master - Misc #18921 (Open): Remove workaround for some fixed bug (llvm.4898 & 38095)?https://bugs.ruby-lang.org/issues/189212022-07-16T15:52:40ZChandler (Chandler Hen)
<p>I notice a workaround for llvm.4898 in constant_p.h:<br>
<a href="https://github.com/ruby/ruby/blob/master/include/ruby/internal/constant_p.h" class="external">https://github.com/ruby/ruby/blob/master/include/ruby/internal/constant_p.h</a></p>
<pre><code class="c syntaxhl" data-language="c"><span class="o">*</span> <span class="n">Note</span> <span class="n">that</span> <span class="n">__builtin_constant_p</span> <span class="n">can</span> <span class="n">be</span> <span class="n">applicable</span> <span class="n">inside</span> <span class="n">of</span> <span class="kr">inline</span> <span class="n">functions</span><span class="p">,</span>
<span class="o">*</span> <span class="n">according</span> <span class="n">to</span> <span class="n">GCC</span> <span class="n">manual</span><span class="p">.</span> <span class="n">Clang</span> <span class="n">lacks</span> <span class="n">that</span> <span class="n">feature</span><span class="p">,</span> <span class="n">though</span><span class="p">.</span>
<span class="o">*</span>
<span class="o">*</span> <span class="err">@</span><span class="n">see</span> <span class="n">https</span><span class="o">:</span><span class="c1">//bugs.llvm.org/show_bug.cgi?id=4898</span>
<span class="o">*</span> <span class="err">@</span><span class="n">see</span> <span class="n">https</span><span class="o">:</span><span class="c1">//gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html</span>
<span class="err">*/</span>
<span class="cp">#include</span> <span class="cpf">"ruby/internal/has/builtin.h"</span><span class="cp">
</span>
<span class="cm">/** Wraps (or simulates) `__builtin_constant_p` */</span>
<span class="cp">#if RBIMPL_HAS_BUILTIN(__builtin_constant_p)
# define RBIMPL_CONSTANT_P(expr) __builtin_constant_p(expr)
#else
# define RBIMPL_CONSTANT_P(expr) 0
#endif
</span>
<span class="cp">#endif </span><span class="cm">/* RBIMPL_CONSTANT_P_H */</span><span class="cp">
</span></code></pre>
<p>and a workaround for llvm.38095 in scan_args.h:<br>
<a href="https://github.com/ruby/ruby/blob/master/include/ruby/internal/scan_args.h" class="external">https://github.com/ruby/ruby/blob/master/include/ruby/internal/scan_args.h</a></p>
<pre><code class="c syntaxhl" data-language="c"><span class="cm">/* NOTE: Use `char *fmt` instead of `const char *fmt` because of clang's bug*/</span>
<span class="cm">/* https://bugs.llvm.org/show_bug.cgi?id=38095 */</span>
<span class="cp"># define rb_scan_args0(argc, argv, fmt, varc, vars) \
rb_scan_args_set(RB_SCAN_ARGS_PASS_CALLED_KEYWORDS, argc, argv, \
rb_scan_args_n_lead(fmt), \
rb_scan_args_n_opt(fmt), \
rb_scan_args_n_trail(fmt), \
rb_scan_args_f_var(fmt), \
rb_scan_args_f_hash(fmt), \
rb_scan_args_f_block(fmt), \
(rb_scan_args_verify(fmt, varc), vars), (char *)fmt, varc)
</span><span class="p">...</span>
</code></pre>
<p>These bugs are already marked as fixed:<br>
bugs.llvm.org/show_bug.cgi?id=4898<br>
bugs.llvm.org/show_bug.cgi?id=38095<br>
Shall they be removed?</p> Ruby master - Misc #18840 (Open): Top-level #using and other methods docshttps://bugs.ruby-lang.org/issues/188402022-06-18T19:12:56Zzverok (Victor Shepelev)zverok.offline@gmail.com
<p>I was looking into some docs problems, and the question I have is that we don't have any place where <code>main</code>'s methods documentation is rendered?</p>
<p>The <code>#using</code>, for example, is <a href="https://github.com/ruby/ruby/blob/ruby_3_1/eval.c#L1960" class="external">defined</a> on <code>main</code>'s singleton class (if I am reading the code correctly), and it has <a href="https://github.com/ruby/ruby/blob/ruby_3_1/eval.c#L1687" class="external">RDoc defined</a> in <code>*.c</code>, but for all I can tell it is rendered nowhere.</p>
<p>Theoretically, it would've been nice to have a place where <code>main</code> object's concept would be explained and the methods available in it, listed, right?..</p>
<p>Or am I missing something obvious?</p> Ruby master - Misc #18761 (Open): provide an example wasm projecthttps://bugs.ruby-lang.org/issues/187612022-04-30T19:25:46Zgrosser (Michael Grosser)michael@grosser.it
<p>Neither the release notes nor the wasm/README.md include any runnable examples.<br>
Please provide a docker image that can be used to generate a wasm binary (even if it's just "hello world"),<br>
to show how this is supposed to work.</p> Ruby master - Misc #18725 (Open): IO#write and IO#wait_writable block for write pipe if read pipe...https://bugs.ruby-lang.org/issues/187252022-04-13T23:20:52Zjeremyevans0 (Jeremy Evans)merch-redmine@jeremyevans.net
<p>I'm not sure whether this is a Ruby issue, an OpenBSD issue, or something else, but <a class="user active user-mention" href="https://bugs.ruby-lang.org/users/3344">@ioquatix (Samuel Williams)</a> asked me to post this here. The following program hangs on OpenBSD:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="nb">require</span> <span class="s1">'io/wait'</span>
<span class="n">rd</span><span class="p">,</span> <span class="n">wr</span> <span class="o">=</span> <span class="no">IO</span><span class="p">.</span><span class="nf">pipe</span>
<span class="n">thread_pass</span> <span class="o">=</span> <span class="no">ARGV</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">==</span> <span class="s1">'pass'</span>
<span class="n">write</span> <span class="o">=</span> <span class="no">ARGV</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">==</span> <span class="s1">'write'</span>
<span class="n">thread</span> <span class="o">=</span> <span class="no">Thread</span><span class="p">.</span><span class="nf">new</span> <span class="k">do</span>
<span class="n">longer</span> <span class="o">=</span> <span class="s2">"0"</span> <span class="o">*</span> <span class="mi">1024</span> <span class="o">*</span> <span class="mi">1024</span>
<span class="p">(</span><span class="mi">1024</span> <span class="o">*</span> <span class="mi">4</span><span class="p">).</span><span class="nf">times</span> <span class="k">do</span>
<span class="k">if</span> <span class="n">write</span>
<span class="n">wr</span><span class="p">.</span><span class="nf">write</span><span class="p">(</span><span class="n">longer</span><span class="p">)</span>
<span class="k">else</span>
<span class="k">while</span> <span class="n">wr</span><span class="p">.</span><span class="nf">write_nonblock</span><span class="p">(</span><span class="n">longer</span><span class="p">,</span> <span class="ss">:exception</span><span class="o">=></span><span class="kp">false</span><span class="p">)</span> <span class="o">==</span> <span class="ss">:wait_writable</span>
<span class="n">thread_pass</span> <span class="p">?</span> <span class="no">Thread</span><span class="p">.</span><span class="nf">pass</span> <span class="p">:</span> <span class="n">wr</span><span class="p">.</span><span class="nf">wait_writable</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="ss">:finished</span>
<span class="k">rescue</span> <span class="o">=></span> <span class="n">e</span>
<span class="n">e</span>
<span class="k">end</span>
<span class="nb">sleep</span> <span class="mi">1</span>
<span class="n">rd</span><span class="p">.</span><span class="nf">close</span>
<span class="nb">puts</span> <span class="ss">:rd_close</span>
<span class="nb">puts</span> <span class="n">thread</span><span class="p">.</span><span class="nf">value</span>
</code></pre>
<p>This program will also hang if <code>write</code> is given as the argument, using <code>wr.write</code> instead of <code>wr.write_nonblock</code>/<code>wr.wait_writable</code>. However, if <code>pass</code> is given as the argument, using <code>Thread.pass</code> instead of <code>wr.wait_writable</code>, the program will not hang.</p>
<p>From testing, the hang when called without an argument is in <code>wait_writable</code>, and the hang with a <code>write</code> argument is in <code>write</code>.</p>
<p>Is Ruby supposed to guarantee that a closing the read end of a pipe in one thread causes a raise of EPIPE to the write end of the pipe in a different thread if already inside <code>IO#write</code>/<code>IO#wait_writable</code>? Or is this platform-specific behavior?</p>
<p>This example was extracted from one of Rack's tests, which was causing non-deterministic hangs on OpenBSD.</p> Ruby master - Misc #18587 (Open): What was the reason behind Ruby choosing SipHash for Hash?https://bugs.ruby-lang.org/issues/185872022-02-16T15:42:48Zmidnight (Sarun R)
<p>Hello</p>
<p>I am digging into the history behind Ruby using SipHash for its Hash.<br>
I found that in 2012 there were CVE-2012-5371 showing up;<br>
the Ruby maintainers went with the decision to switch algorithms, probably, because we wanted something quick to implement at the time.<br>
The change went live in late 2012.</p>
<p>Fast forward with the Ruby 3x3 initiative, we now seem to care about the performance again.<br>
And hash DoSing does not seem to be an urgent threat now; we have time to be deliberate about Hash again.</p>
<p>I can't find the old discussion related to Ruby's SipHash decision.<br>
I just found that SipHash is not the only solution to prevent hashtable DoSing.<br>
There is an interesting discussion on golang side in late 2015:<br>
<a href="https://github.com/golang/go/issues/9365" class="external">https://github.com/golang/go/issues/9365</a></p>
<p>Just to recap, Go's authors argue that:</p>
<ul>
<li>Cryptographic hash is not needed to construct a DoS-resistant hashtable.</li>
<li>If the random seed is per-hashtable bases, the attack vector exploitable from a remote adversary seems unlikely.</li>
<li>If we want to be extra careful about it, and since the collision is unlikely, when collision actually does occur despite the per-hashtable seed, we can handle that as a special case where we can rerandom the seed and rehash the key.</li>
<li>The way random seeds are folded into the hash does matter, for example, CityHash does f(g(msg), seed); in such case, collision in g will cause a collision in f because the output of g is independent of the seed.</li>
<li>Slowing down hashtable for everyone to prevent hard-to-exploit DoS doesn't seem to be a good trade-off.</li>
</ul>
<p>On the actual implementation, they use AES-NI to achieve good pseudo-random functions' properties. And use some fallback non-cryptographic hashing function on the platform without AES-NI.</p>
<p>Now, I read the rationale on golang side, I want to understand the rationale on the Ruby side too.<br>
I am not there 10-years-ago, and I can't find records or discussions at the time. There might be some Ruby limitations that the approach described by go's authors does not apply.</p>
<p>So, I asked in the hope of someone still remembering what was happening, the situation we are in 10 years ago, or the limitation of Ruby that prevents per-Hash seeds.</p> Ruby master - Misc #18420 (Open): Question about how to handle IO.pipe reader and writer when for...https://bugs.ruby-lang.org/issues/184202021-12-22T00:04:00Zestolfo (Emily S)
<p>I don't think this is a bug but I'm not sure. It could be just a limitation of forking with a IO.pipe reader and writer.</p>
<p>I work on the Elastic Ruby APM agent (<a href="https://github.com/elastic/apm-agent-ruby" class="external">https://github.com/elastic/apm-agent-ruby</a>). The Ruby agent is a singleton and uses a IO.pipe to send data to the APM server. The writer we wrap in a GzipWriter. When the parent process is forked, the child inherits the readers and (gzip)writers. I detect the forking by comparing PIDs when an event is created and create new readers and writers in the child process so that I don't interfere with the parent's streams.<br>
When the fork exits, I close the child's readers and writers but I see the follow error</p>
<p>zlib(finalizer): Zlib::GzipWriter object must be closed explicitly.<br>
zlib(finalizer): the stream was freed prematurely.</p>
<p>because the parent's writer is still considered living in the child process.<br>
One option to address this error is to create a finalizer on the writer that closes it. But then I get intermittent errors from the APM server saying the gzipped data's header is invalid. I'm assuming this is because the parent's writer is closed by the child before the compression is complete in the parent.</p>
<p>Is there a proper way to handle forking when the parent is using a pipe? Both options I have to handle the writer result in an error/warning: I can't close the GzipWriter in the child because of the corrupted data issue but if I don't close it, I get the "Zlib::GzipWriter object must be closed explicitly" warning.</p>
<p>If I close the reader and writer in a "before_fork" hook run in the parent, I avoid both issues. But I don't want to recreate the reader/writer objects every time the parent is forked.</p>
<p>I've been testing with ruby 2.7.0 and Resque (<a href="https://github.com/resque/resque" class="external">https://github.com/resque/resque</a>) primarily but this issue is observed with Puma and other frameworks that use forking.</p> Ruby master - Misc #18352 (Open): What is the Hash#grep expected?https://bugs.ruby-lang.org/issues/183522021-11-20T09:50:09Zzw963 (Wei Zheng)
<p>Current ruby implement, When use Array#grep, the method name means is expected.</p>
<pre><code>[19] pry(#<App>)> [:foo1, :foo2, :bar].grep /foo/
[
:foo1,
:foo2
]
</code></pre>
<p>But when use with hash, the result is really confusing ...</p>
<pre><code class="rb syntaxhl" data-language="rb"><span class="p">[</span><span class="mi">12</span><span class="p">]</span> <span class="n">pry</span><span class="p">(</span><span class="c1">#<App>)> {foo: '100', bar: '200'}.grep /foo/ </span>
<span class="p">[]</span>
</code></pre>
<p>This result almost make Include Enumerable#grep into Hash is totally meaningless, right?</p>
<p>so, i consider if we should introduce a <code>Hash#grep</code> method instead.</p>
<p>Following is what is expected. (=== is matching on hash key, as Hash#slice)</p>
<pre><code class="rb syntaxhl" data-language="rb"><span class="p">[</span><span class="mi">20</span><span class="p">]</span> <span class="n">pry</span><span class="p">(</span><span class="c1">#<App>)> {foo1: '100', foo2: '200', bar: '200'}.grep /foo/ </span>
<span class="p">{</span>
<span class="ss">:foo1</span> <span class="o">=></span> <span class="s2">"100"</span><span class="p">,</span>
<span class="ss">:foo2</span> <span class="o">=></span> <span class="s2">"200"</span>
<span class="p">}</span>
</code></pre> Ruby master - Misc #18248 (Open): Add Feature Triaging Guidehttps://bugs.ruby-lang.org/issues/182482021-10-11T16:14:14Zjeremyevans0 (Jeremy Evans)merch-redmine@jeremyevans.net
<p>Ruby added a bug triaging guide in June 2019, and since then I've used it to reduce the number of open bugs in the tracker from over 1400 to about 300. Ruby currently has over 1200 open feature requests on the issue tracker. From a cursory review, many of these have already been implemented, and many are unlikely to be desired. I would like to add a feature triaging guide to Ruby and start triaging feature requests, with the goal of having open feature requests be features not yet implemented that the Ruby core team would like implemented or would consider patches for. By doing so, we can make it easier for potential contributors to Ruby to easily see possible contributions they could make.</p>
<p>I've added a pull request with a draft of the proposed guide: <a href="https://github.com/ruby/ruby/pull/4953" class="external">https://github.com/ruby/ruby/pull/4953</a></p> Ruby master - Misc #18150 (Open): Proposal: Deprecate leading zero syntax to declare octals, sinc...https://bugs.ruby-lang.org/issues/181502021-09-03T17:10:05ZProGM (Piero Dotti)
<p>Hi there,<br>
I'd like to open a discussion about the leading zeros syntax to declare octal numbers.</p>
<p>Let me give you a little bit of context.</p>
<p>It seems like ruby considers all integers with leading zeros as octal.<br>
For instance, if you write 012, ruby reads it as 10 in decimal.<br>
There is an alternative syntax for this, using an "o" character after the zero, i.e. 0o12</p>
<p>I've discovered this behavior by chance a couple of days ago.<br>
I was declaring a new Date object:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="no">START_DATE</span> <span class="o">=</span> <span class="no">Date</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="mi">2021</span><span class="p">,</span> <span class="mi">09</span><span class="p">,</span> <span class="mo">01</span><span class="p">)</span>
</code></pre>
<p>In my mind, I was thinking of ISO 8601 ("2021-09-01") and I wrote it in that way without even thinking about it.</p>
<p>I immediately got a weird error:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="no">SyntaxError</span> <span class="p">((</span><span class="n">irb</span><span class="p">):</span><span class="mi">2</span><span class="p">:</span> <span class="no">Invalid</span> <span class="n">octal</span> <span class="n">digit</span><span class="p">)</span>
</code></pre>
<p>That was astonishing. "What the heck does this error mean?", I thought.</p>
<p>After a brief research, I've discovered that many languages that come from C have this "weird" behavior.<br>
Javascript, Go, Java, and ruby itself all treat leading zeros like this.<br>
Rust and Elixir, instead, are parsing 00123 like 123, as math notation suggests.<br>
Finally, Python 3+ raises an error.</p>
<hr>
<p>My proposal is: throw a deprecation warning in ruby 3.x when using this syntax and treat 0011 as 11 from ruby 4+.</p>
<p>Why?</p>
<ul>
<li>Because it's extremely confusing</li>
<li>There is an alternative syntax that is much more explicit (0o11 vs 011)</li>
<li>It leads to weird behaviors (like 011 != 11)</li>
<li>Because Python 2.x was treating leading zeros numbers as octals like ruby does, but this has been changed in python 3+: <a href="https://medium.com/techmacademy/leading-zeros-in-python-a-hidden-mystery-revealed-ee3e3065634d" class="external">https://medium.com/techmacademy/leading-zeros-in-python-a-hidden-mystery-revealed-ee3e3065634d</a>
</li>
</ul>
<p>Ruby's claim is "A PROGRAMMER'S BEST FRIEND". As a programmer, I don't consider this behavior very friendly. :(</p>
<p>Let me know what you think about this!</p> Ruby master - Misc #18082 (Open): FileUtils.remove_entry_secure has inconsistent documenthttps://bugs.ruby-lang.org/issues/180822021-08-17T16:26:38Zpocke (Masataka Kuwabara)
<p><code>FileUtils.remove_entry_secure</code> and <code>FileUtils.rm_r</code> have inconsistency about the vulnerability condition the in the documentations.</p>
<p><code>remove_entry_secure</code> document:<br>
<a href="https://github.com/ruby/ruby/blob/6a9bfa4d9387b9d8f07f43f4546437be57f9e27c/lib/fileutils.rb#L660-L664" class="external">https://github.com/ruby/ruby/blob/6a9bfa4d9387b9d8f07f43f4546437be57f9e27c/lib/fileutils.rb#L660-L664</a></p>
<blockquote>
<p>#rm_r causes security hole when:</p>
<ul>
<li>Parent directory is world writable (including /tmp).</li>
<li>Removing directory tree includes world writable directory.</li>
<li>The system has symbolic link.</li>
</ul>
</blockquote>
<p><code>rm_r</code> document:<br>
<a href="https://github.com/ruby/ruby/blob/6a9bfa4d9387b9d8f07f43f4546437be57f9e27c/lib/fileutils.rb#L614-L618" class="external">https://github.com/ruby/ruby/blob/6a9bfa4d9387b9d8f07f43f4546437be57f9e27c/lib/fileutils.rb#L614-L618</a></p>
<blockquote>
<p>WARNING: This method causes local vulnerability<br>
if one of parent directories or removing directory tree are world<br>
writable (including /tmp, whose permission is 1777), and the current<br>
process has strong privilege such as Unix super user (root), and the<br>
system has symbolic link.</p>
</blockquote>
<p>The differences are following.</p>
<ul>
<li>
<code>rm_r</code> describes about strong privilege, but <code>remove_entry_secure</code> doesn't.</li>
<li>
<code>rm_r</code> describes "one of parent directories <strong>OR</strong> removing directory tree are world writable", but the conditions are just listed in <code>remove_entry_secure</code> doc, it seems <strong>AND</strong> condition.</li>
</ul>
<p>I couldn't understand the prerequisites of the vulnerability from the documents.<br>
I think both documents should describe the same prerequisites.</p>
<p>I don't know what is the right prerequisites, so I didn't make a patch.</p> Ruby master - Misc #17829 (Open): Clang/LLVM correctness of x64-mingw32 build (`shorten-64-to-32`...https://bugs.ruby-lang.org/issues/178292021-04-26T16:23:26Zxtkoba (Tee KOBAYASHI)
<p>The attached log is from <code>make miniruby</code> for x64-mingw32 with Clang/LLVM. Warnings are silenced except for <code>-Wshorten-64-to-32</code>.</p>
<p>This might not be an issue solely for Clang/LLVM, because the size of each type is the same as that in GCC.</p>
<p>I believe most of them are false positive. It would be easy to silence these warnings by explicit type casting. But before doing so, it must be checked whether each shortening is legitimate or not.</p>
<p>Version: <code>ruby 3.1.0dev (2021-04-26T13:46:51Z master 203eeeefdd) [x64-mingw32]</code></p> Ruby master - Misc #17683 (Open): Current status of beginless range (experimental or not)https://bugs.ruby-lang.org/issues/176832021-03-10T09:40:02Zjnchito (Junichi Ito)
<p>A beginless range was experimentally introduced in Ruby 2.7.0:<br>
<a href="https://github.com/ruby/ruby/blob/v2_7_0/NEWS#label-Other+miscellaneous+changes" class="external">https://github.com/ruby/ruby/blob/v2_7_0/NEWS#label-Other+miscellaneous+changes</a></p>
<p>Is it still experimental feature or not?</p> Ruby master - Misc #17637 (Open): Endless ranges with `nil` boundary weird behaviorhttps://bugs.ruby-lang.org/issues/176372021-02-17T10:49:17Zgud (gud gud)
<p>Basically it's about this <a href="https://andycroll.com/ruby/watch-out-for-nils-in-ranges/" class="external">https://andycroll.com/ruby/watch-out-for-nils-in-ranges/</a></p>
<p>Since Ruby 2.6 we have this weird syntax (0..nil) which is really really bug prone</p>
<p>e.g. we have dynamic upper boundary like</p>
<pre><code>lower = 0
upper = some_method(arg1, arg2)
(lower..upper).each do { |s| some_method2(s) }
</code></pre>
<p>We rarely do <code>nil</code> checks in Ruby so it's really easy to have Infinity loop in the end.<br>
Previous Argument error was more intuitive since it throws exception instead of silently looping forever.</p>
<ul>
<li>some additional strange behavior:</li>
</ul>
<pre><code>(0..nil).count
=> Infinity
(0..Float::INFINITY).count
=> hangs, I guess same infinity loop
</code></pre>
<p>Having explicit parameter <code>Float::INFINITY</code> (as in previous versions) looks more like a proper design instead of allowing <code>nil</code> as a valid parameter.</p>
<p>You may think of it as <strong>I would like to have a range from 0 to nothing, what is it actually ?</strong><br>
And I guess the answer is <strong>Nothing</strong>.<br>
Fixing <code>(0..Float::INFINITY).count</code> this case it also important I believe.</p>
<p>Tested on <code>ruby 2.7.1p83</code></p> Ruby master - Misc #17586 (Open): Please run Windows CI in all std-lib reposhttps://bugs.ruby-lang.org/issues/175862021-01-27T17:40:41ZMSP-Greg (Greg L)
<p>Please consider adding Windows CI to all std-lib repos.</p>
<p>Having ruby/ruby CI fail due to std-lib commits merged from their respective repos causes downstream issues, wasted time, etc.</p>
<p>See <a href="https://github.com/ruby/irb/pull/179" class="external">https://github.com/ruby/irb/pull/179</a> for an example adding Windows to Actions CI.</p>
<p>Re Actions matrix:</p>
<ol>
<li>The os change from <code>*-latest</code> to <code>*-<numeric></code> (eg, <code>macos-latest</code> to <code>macos-11.0</code>). The <code>-latest</code> designation changes, so some may prefer a <code>-<numeric></code> tag. See <a href="https://github.com/actions/virtual-environments#available-environments" class="external">https://github.com/actions/virtual-environments#available-environments</a> for available environments and their naming.</li>
<li>Using numeric versions for Ruby causes an issue with 3.0, as it’s interpreted as 3, which is only a sematic major requirement. Hence, quote all numeric versions.</li>
</ol> Ruby master - Misc #17569 (Open): `uri` lib maintainershiphttps://bugs.ruby-lang.org/issues/175692021-01-22T15:48:33Zmarcandre (Marc-Andre Lafortune)marcandre-ruby-core@marc-andre.ca
<p>I’d like to merge <a href="https://github.com/ruby/uri/pull/15" class="external">https://github.com/ruby/uri/pull/15</a> but it is an API change. I would release v1.0.0. <a class="user active user-mention" href="https://bugs.ruby-lang.org/users/271">@akr (Akira Tanaka)</a> is the official maintainer of <code>uri</code>… Is he still interested in this role? Otherwise we could put “Ruby core team” in the listing…</p> Ruby master - Misc #17565 (Open): Prefer use of access(2) in rb_file_load_ok() to check for exist...https://bugs.ruby-lang.org/issues/175652021-01-20T20:05:56Zleehambley (Lee Hambley)
<p>When using Ruby in Docker (2.5 in our case, but the code is unchanged in 15 years across all versions) with a large $LOAD_PATH some millions of calls are made to <code>open(2)</code> with a mean cost of 130µsec per call, where a call to <code>access(2)</code> has a cost around 5× lower (something around 28µsec).</p>
<p>With a Rails 5 app, without Zeitwerk, the load path is searched iteratively looking for a file to define a constant, this causes something like 2,000,000 calls to <code>open(2)</code> of which 97.5% are failing with <code>ENOENT</code>.</p>
<p>I believe that the cost of two syscalls (<code>open(2)</code> only after successful <code>access(2)</code>) would, in our case, at least because we would shave-off something like 1,900,000×90µsec (2.85 minutes) from the three minute boot time for our application.</p>
<p>I prepared a very naïve patch with a simple early-return in <code>rb_file_load_ok</code>:</p>
<pre><code>diff --git a/file.c b/file.c
index 3bf092c05c..c7a7635125 100644
--- a/file.c
+++ b/file.c
@@ -5986,6 +5986,16 @@ rb_file_load_ok(const char *path)
O_NDELAY |
#endif
0);
+ if (access(path, R_OK) == -1) return 0;
int fd = rb_cloexec_open(path, mode, 0);
if (fd == -1) return 0;
rb_update_max_fd(fd);
</code></pre>
<p>This hasn't been exhaustively tested as I simply haven't had time yet, but at least it compiled and passed <code>make check</code>.</p>
<p>I spoke with Aaron Patterson on Twitter, who suggested maybe a wiser approach would be a heuristic approach one level higher (<code>rb_find_file</code>?) which switches the strategy based on the length of the LOAD_PATH.</p>
<p>Alternatively, maybe the patch could be conditional, guarded somehow, and conditionally compiled only into the Rubies built for Docker, in a way that is portable to the common Ruby version managers.</p>
<p>I am opening this ticket to track my own work, as much as anything, with no expectation that someone implement this on my behalf. I am eager to contribute to Ruby for all the benefit I have seen from it in my career.</p>
<p>If someone knows hints why this may be an unsuccessful adventure, I gratefully receive any and all feedback.</p> Ruby master - Misc #17502 (Open): C vs Rubyhttps://bugs.ruby-lang.org/issues/175022021-01-02T20:25:28Zmarcandre (Marc-Andre Lafortune)marcandre-ruby-core@marc-andre.ca
<p>Some features are coded in a mix of Ruby and C (e.g. ractor.rb).</p>
<p>External gems don't have access to this. The C-API to deal with keyword parameters is also very verbose the parsing and the engine does not know it.</p>
<p>Moreover, some optimization PRs are simply rewriting C-code into Ruby using pseudo C code.</p>
<p>I understand the intentions are great, but changes like <a href="https://github.com/ruby/ruby/pull/4018/files" class="external">https://github.com/ruby/ruby/pull/4018/files</a> seem a symptom that something needs to be improved with the C api.</p>
<pre><code class="diff syntaxhl" data-language="diff"><span class="gd">-static VALUE
- flo_zero_p(VALUE num)
- {
- return flo_iszero(num) ? Qtrue : Qfalse;
- }
</span># in different file:
<span class="gi">+ def zero?
+ Primitive.attr! 'inline'
+ Primitive.cexpr! 'flo_iszero(self) ? Qtrue : Qfalse'
+ end
</span></code></pre>
<p>It seems to me that this is a way to circumvent a deeper issue. Is this the right direction?</p>
<p>Is there a plan for an API that would:</p>
<ol>
<li>be accessible to C extensions</li>
<li>can't be re-written any faster in pseuso-C in Ruby</li>
<li>has an easy way to define keyword parameters?</li>
</ol>
<p>I realize that RBS may give perfect signatures, but ideally <code>parameters</code> would be more informative for C-functions too.</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="no">Ractor</span><span class="p">.</span><span class="nf">method</span><span class="p">(</span><span class="ss">:yield</span><span class="p">).</span><span class="nf">parameters</span>
<span class="c1"># => [[:req, :obj], [:key, :move]] # good!</span>
<span class="no">Fiber</span><span class="p">.</span><span class="nf">method</span><span class="p">(</span><span class="ss">:initialize</span><span class="p">).</span><span class="nf">parameters</span>
<span class="c1"># => [[:rest]] # not good, should be [[:key, :blocking]]</span>
</code></pre> Ruby master - Misc #17337 (Open): Don't embed Ruby build-time configuration in Rubyhttps://bugs.ruby-lang.org/issues/173372020-11-20T09:49:55Zvo.x (Vit Ondruch)v.ondruch@tiscali.cz
<p>When Ruby 3.0 is built without C++ compiler available, subsequent builds of Eventmachine extensions (or any other gems that require C++ compiler) fail:</p>
<pre><code>... snip ...
"make \"DESTDIR=\""
I. -I/usr/include -I/usr/include/ruby/backward -I/usr/include -I. -DHAVE_OPENSSL_SSL_H -DHAVE_OPENSSL_ERR_H -DWITH_SSL -DBUILD_FOR_RUBY -DHAVE_RB_THREAD_CALL_WITHOUT_GVL -DHAVE_RB_THREAD_FD_SELECT -DHAVE_TYPE_RB_FDSET_T -DHAVE_RB_WAIT_FOR_SINGLE_FD -DHAVE_RB_TIME_NEW -DHAVE_INOTIFY_INIT -DHAVE_INOTIFY -DHAVE_WRITEV -DHAVE_PIPE2 -DHAVE_ACCEPT4 -DHAVE_CONST_SOCK_CLOEXEC -DOS_UNIX -DHAVE_EPOLL_CREATE -DHAVE_EPOLL -DHAVE_CLOCK_GETTIME -DHAVE_CONST_CLOCK_MONOTONIC_RAW -DHAVE_CONST_CLOCK_MONOTONIC -fPIC -O2 -flto=auto -ffat-lto-objects -fexceptions -g -grecord-gcc-switches -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -fstack-protector-strong -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -m64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -m64 -o binder.o -c binder.cpp
make: I.: No such file or directory
make: [Makefile:237: binder.o] Error 127 (ignored)
</code></pre>
<p>This happens since <a href="https://github.com/ruby/ruby/commit/50b18e81295ad2d45975e4d8ea1e0c7e85140b97" class="external">1</a>.</p>
<p>I would like to question not just the commit, but the whole principle. Availability of C++ compiler during build of Ruby does not have anything to do with availability of C++ compiler during build of whatever Ruby extension.</p>
<p>Moreover, the machine where Ruby is built might be different from the machine where Ruby is used and the extension is installed. Typical examples are binary Linux distributions. RVM also uses precompiled Ruby binaries if I am not mistaken.</p>
<p>Therefore, I would appreciate if we reconsider embedding Ruby build-time configuration in Ruby and reusing it for Ruby extension build. This would solve the issue of Eventmachine I started with, and also issues such as <a class="issue tracker-1 status-5 priority-4 priority-default closed" title="Bug: Ruby configuration options should not be reused for gem builds (Closed)" href="https://bugs.ruby-lang.org/issues/14422">#14422</a></p>
<p>Just FTR, to avoid this kind of issues, as a Ruby maintainer on Red Hat platforms, I am considering to ship rbconfig.rb in vendorlib, which would dynamically fix these issues. E.g. set the <code>CONFIG['CXX']</code> based on C++ compiler availability during extension build. But I'd like to avoid it, at least as a downstream modification.</p> Ruby master - Misc #17309 (Open): URI.escape being deprecated, yet there is no replacementhttps://bugs.ruby-lang.org/issues/173092020-11-07T01:26:10Zchucke (Tiago Cardoso)
<p>I'm on ruby 2.7.2 . The moment I do</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="n">uri</span> <span class="o">=</span> <span class="s2">"http://bücher.ch"</span>
<span class="no">URI</span><span class="p">.</span><span class="nf">escape</span> <span class="n">uri</span>
<span class="p">(</span><span class="n">irb</span><span class="p">):</span><span class="mi">5</span><span class="p">:</span> <span class="ss">warning: </span><span class="no">URI</span><span class="p">.</span><span class="nf">escape</span>
<span class="s2">"http://b%C3%BCcher.ch"</span>
</code></pre>
<p>I get that warning. Rubocop also tells me:</p>
<p>"""<br>
URI.escape method is obsolete and should not be used. Instead, use CGI.escape, URI.encode_www_form or URI.encode_www_form_component depending on your specific use case.<br>
"""</p>
<p>However, none of the suggestions does the same as <code>URI.escape</code>.</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="no">CGI</span><span class="p">.</span><span class="nf">escape</span> <span class="n">uri</span>
<span class="o">=></span> <span class="s2">"http%3A%2F%2Fb%C3%BCcher.ch"</span>
<span class="no">URI</span><span class="p">.</span><span class="nf">encode_www_form_component</span> <span class="n">uri</span>
<span class="o">=></span> <span class="s2">"http%3A%2F%2Fb%C3%BCcher.ch"</span>
<span class="no">URI</span><span class="p">.</span><span class="nf">encode_www_form</span> <span class="n">uri</span>
<span class="no">Traceback</span> <span class="p">(</span><span class="n">most</span> <span class="n">recent</span> <span class="n">call</span> <span class="n">last</span><span class="p">):</span>
<span class="no">NoMethodError</span> <span class="p">(</span><span class="n">undefined</span> <span class="nb">method</span> <span class="sb">`map' for "http://bücher.ch":String)
Did you mean? tap
</span></code></pre>
<p>So my question is: why is this being deprecated? And if there's still reason, what to exactly replace it for, so I can keep the exact same behaviour?</p> Ruby master - Misc #17199 (Open): id outputed by inspect and to_s output does not allow to find a...https://bugs.ruby-lang.org/issues/171992020-09-28T11:40:39ZAnnih (Baptiste Courtois)
<p>Hello, here is my first ruby issue sorry in advance if it is incorrectly filled.</p>
<a name="Issue"></a>
<h1 >Issue<a href="#Issue" class="wiki-anchor">¶</a></h1>
<p>The value returned by <code>#object_id</code> is not aligned anymore with displayed info in <code>#inspect</code> and <code>#to_s</code> methods.</p>
<a name="with-ruby-lt-27"></a>
<h2 >with ruby < 2.7<a href="#with-ruby-lt-27" class="wiki-anchor">¶</a></h2>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="no">Object</span><span class="p">.</span><span class="nf">new</span><span class="p">.</span><span class="nf">tap</span> <span class="p">{</span> <span class="o">|</span><span class="n">o</span><span class="o">|</span> <span class="nb">p</span> <span class="s2">"#to_s=</span><span class="si">#{</span><span class="n">o</span><span class="p">.</span><span class="nf">to_s</span><span class="si">}</span><span class="s2">, #inspect=</span><span class="si">#{</span><span class="n">o</span><span class="p">.</span><span class="nf">inspect</span><span class="si">}</span><span class="s2">, #__id__=</span><span class="si">#{</span><span class="n">o</span><span class="p">.</span><span class="nf">__id__</span><span class="si">}</span><span class="s2">, shifted_id=</span><span class="si">#{</span><span class="p">(</span><span class="n">o</span><span class="p">.</span><span class="nf">__id__</span> <span class="o"><<</span> <span class="mi">1</span><span class="p">).</span><span class="nf">to_s</span><span class="p">(</span><span class="mi">16</span><span class="p">)</span><span class="si">}</span><span class="s2">"</span> <span class="p">}</span>
<span class="s2">"#to_s=#<Object:0x0000000000d202a8>, #inspect=#<Object:0x0000000000d202a8>, #__id__=6881620, shifted_id=d202a8"</span>
</code></pre>
<a name="with-ruby-gt-27"></a>
<h2 >with ruby >= 2.7<a href="#with-ruby-gt-27" class="wiki-anchor">¶</a></h2>
<pre><code class="ruby syntaxhl" data-language="ruby"> <span class="no">Object</span><span class="p">.</span><span class="nf">new</span><span class="p">.</span><span class="nf">tap</span> <span class="p">{</span> <span class="o">|</span><span class="n">o</span><span class="o">|</span> <span class="nb">p</span> <span class="s2">"#to_s=</span><span class="si">#{</span><span class="n">o</span><span class="p">.</span><span class="nf">to_s</span><span class="si">}</span><span class="s2">, #inspect=</span><span class="si">#{</span><span class="n">o</span><span class="p">.</span><span class="nf">inspect</span><span class="si">}</span><span class="s2">, #__id__=</span><span class="si">#{</span><span class="n">o</span><span class="p">.</span><span class="nf">__id__</span><span class="si">}</span><span class="s2">, shifted_id=</span><span class="si">#{</span><span class="p">(</span><span class="n">o</span><span class="p">.</span><span class="nf">__id__</span> <span class="o"><<</span> <span class="mi">1</span><span class="p">).</span><span class="nf">to</span>
<span class="n">s</span><span class="p">(</span><span class="mi">16</span><span class="p">)</span><span class="si">}</span><span class="s2">"</span> <span class="p">}</span>
<span class="s2">"#to_s=#<Object:0x0000555dc8640b88>, #inspect=#<Object:0x0000555dc8640b88>, #__id__=220, shifted_id=1b8"</span>
</code></pre>
<a name="Consequences"></a>
<h1 >Consequences<a href="#Consequences" class="wiki-anchor">¶</a></h1>
<p>It makes harder:</p>
<ul>
<li>to implement a clean override of the <code>#inspect</code> method. i.e. How to keep the same output without ability to compute to the same "object_id" value.</li>
<li>to debug the object using the inspect output. i.e. <code>ObjectSpace._id2ref(id_from_inspect >> 1)</code> used to work, now it doesn't (<code>RangeError: <xXx> is not id value</code>).</li>
</ul>
<a name="Suggestion"></a>
<h1 >Suggestion<a href="#Suggestion" class="wiki-anchor">¶</a></h1>
<p>IMHO either:</p>
<ul>
<li>the <code>#to_s</code> and <code>#inspect</code> documentation are obsolete <code>The default [...] [shows|prints] [...] an encoding of the object id</code> and the change could have been a bit more advertised</li>
<li>they should use the result of <code>#object_id</code> instead of displaying the object pointer address</li>
</ul>
<p>Another solution could be to provide a method to get access to the address, but I'm not sure you want that.</p>
<p>P.S. While debugging my problem I found <a href="https://www.ruby-forum.com/t/understanding-object-id-in-ruby-2-7/260268/4" class="external">this ruby-forum thread</a> where people dived a bit more than me into ruby's code.</p> Ruby master - Misc #17180 (Open): Ractor and constant referencinghttps://bugs.ruby-lang.org/issues/171802020-09-19T21:24:45Zkirs (Kir Shatrov)shatrov@me.com
<p>Hey there.</p>
<p>From a high level, this bug report is describing my experience building something simple with Ractor without any shared state. I hope this is helpful as a feedback for the stable Ractor implementation in Ruby 3.0.</p>
<p>I've been iterating on a simple web server that utilizes Ractor. One of the things that a web server does is parsing HTTP headers. Thankfully, there's code in Ruby's standard library that can do that, so I decided to leverage <code>WEBrick::HTTPRequest</code>.</p>
<p>Here's my example:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="nb">require</span> <span class="s1">'webrick'</span>
<span class="nb">require</span> <span class="s1">'stringio'</span>
<span class="n">parser</span> <span class="o">=</span> <span class="no">Ractor</span><span class="p">.</span><span class="nf">new</span> <span class="k">do</span>
<span class="n">s</span> <span class="o">=</span> <span class="no">StringIO</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="s2">"GET / HTTP/1.1</span><span class="se">\n</span><span class="s2">"</span><span class="p">\</span>
<span class="s2">"Host: example.com</span><span class="se">\n</span><span class="s2">"</span><span class="p">\</span>
<span class="s2">"User-Agent: curl/7.64.1</span><span class="se">\n</span><span class="s2">"</span><span class="p">\</span>
<span class="s2">"Accept: */*"</span><span class="p">)</span>
<span class="n">req</span> <span class="o">=</span> <span class="no">WEBrick</span><span class="o">::</span><span class="no">HTTPRequest</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="no">WEBrick</span><span class="o">::</span><span class="no">Config</span><span class="o">::</span><span class="no">HTTP</span><span class="p">)</span>
<span class="n">req</span><span class="p">.</span><span class="nf">parse</span><span class="p">(</span><span class="n">s</span><span class="p">)</span>
<span class="k">end</span>
<span class="no">Ractor</span><span class="p">.</span><span class="nf">select</span><span class="p">(</span><span class="n">parser</span><span class="p">)</span>
</code></pre>
<p>This fails with <code>can not access non-sharable objects in constant WEBrick::Config::HTTP by non-main Ractor. (NameError)</code>.</p>
<p>Let's try to copy that constant and pass it to the Ractor:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="nb">require</span> <span class="s1">'webrick'</span>
<span class="nb">require</span> <span class="s1">'stringio'</span>
<span class="n">parser</span> <span class="o">=</span> <span class="no">Ractor</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="no">WEBrick</span><span class="o">::</span><span class="no">Config</span><span class="o">::</span><span class="no">HTTP</span><span class="p">)</span> <span class="k">do</span> <span class="o">|</span><span class="n">config</span><span class="o">|</span>
<span class="n">s</span> <span class="o">=</span> <span class="no">StringIO</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="s2">"GET / HTTP/1.1</span><span class="se">\n</span><span class="s2">"</span><span class="p">\</span>
<span class="s2">"Host: example.com</span><span class="se">\n</span><span class="s2">"</span><span class="p">\</span>
<span class="s2">"User-Agent: curl/7.64.1</span><span class="se">\n</span><span class="s2">"</span><span class="p">\</span>
<span class="s2">"Accept: */*"</span><span class="p">)</span>
<span class="n">req</span> <span class="o">=</span> <span class="no">WEBrick</span><span class="o">::</span><span class="no">HTTPRequest</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="n">config</span><span class="p">)</span>
<span class="n">req</span><span class="p">.</span><span class="nf">parse</span><span class="p">(</span><span class="n">s</span><span class="p">)</span>
<span class="k">end</span>
<span class="no">Ractor</span><span class="p">.</span><span class="nf">select</span><span class="p">(</span><span class="n">parser</span><span class="p">)</span>
</code></pre>
<p>This failed with <code>can't dump hash with default proc</code>. I've guessed that maybe <code>WEBrick::Config::HTTP</code> has a default proc? Let's try to work around:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="nb">require</span> <span class="s1">'webrick'</span>
<span class="nb">require</span> <span class="s1">'stringio'</span>
<span class="n">http_c</span> <span class="o">=</span> <span class="no">WEBrick</span><span class="o">::</span><span class="no">Config</span><span class="o">::</span><span class="no">HTTP</span>
<span class="n">http_c</span><span class="p">.</span><span class="nf">default</span> <span class="o">=</span> <span class="kp">nil</span>
<span class="n">parser</span> <span class="o">=</span> <span class="no">Ractor</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="n">http_c</span><span class="p">)</span> <span class="k">do</span> <span class="o">|</span><span class="n">config</span><span class="o">|</span>
<span class="n">s</span> <span class="o">=</span> <span class="no">StringIO</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="s2">"GET / HTTP/1.1</span><span class="se">\n</span><span class="s2">"</span><span class="p">\</span>
<span class="s2">"Host: example.com</span><span class="se">\n</span><span class="s2">"</span><span class="p">\</span>
<span class="s2">"User-Agent: curl/7.64.1</span><span class="se">\n</span><span class="s2">"</span><span class="p">\</span>
<span class="s2">"Accept: */*"</span><span class="p">)</span>
<span class="n">req</span><span class="p">.</span><span class="nf">parse</span><span class="p">(</span><span class="n">s</span><span class="p">)</span>
<span class="k">end</span>
<span class="no">Ractor</span><span class="p">.</span><span class="nf">select</span><span class="p">(</span><span class="n">parser</span><span class="p">)</span>
</code></pre>
<p>It failed with:</p>
<pre><code>/Users/kir/src/github.com/ruby/ruby/lib/webrick/httprequest.rb:570:in `read_line': can not access non-sharable objects in constant WEBrick::LF by non-main ractor. (NameError)
</code></pre>
<p>I went ahead and made WEBrick freeze strings:</p>
<pre><code class="diff syntaxhl" data-language="diff"><span class="gh">diff --git a/lib/webrick/httputils.rb b/lib/webrick/httputils.rb
index 76d4bd0dc7..273c596368 100644
</span><span class="gd">--- a/lib/webrick/httputils.rb
</span><span class="gi">+++ b/lib/webrick/httputils.rb
</span><span class="p">@@ -13,9 +13,9 @@</span>
require 'tempfile'
<span class="err">
</span> module WEBrick
<span class="gd">- CR = "\x0d" # :nodoc:
- LF = "\x0a" # :nodoc:
- CRLF = "\x0d\x0a" # :nodoc:
</span><span class="gi">+ CR = "\x0d".freeze # :nodoc:
+ LF = "\x0a".freeze # :nodoc:
+ CRLF = "\x0d\x0a".freeze # :nodoc:
</span><span class="err">
</span></code></pre>
<p>Now it's failing with:</p>
<pre><code>/Users/kir/src/github.com/ruby/ruby/lib/singleton.rb:124:in `instance': can not access instance variables of classes/modules from non-main Ractors (RuntimeError)
from /Users/kir/src/github.com/ruby/ruby/lib/webrick/utils.rb:132:in `register'
from /Users/kir/src/github.com/ruby/ruby/lib/webrick/utils.rb:256:in `timeout'
from /Users/kir/src/github.com/ruby/ruby/lib/webrick/httprequest.rb:559:in `_read_data'
from /Users/kir/src/github.com/ruby/ruby/lib/webrick/httprequest.rb:570:in `read_line'
from /Users/kir/src/github.com/ruby/ruby/lib/webrick/httprequest.rb:447:in `read_request_line'
from /Users/kir/src/github.com/ruby/ruby/lib/webrick/httprequest.rb:201:in `parse'
from ./test.rb:16:in `block in <main>'
</code></pre>
<p>because WEBrick is manipulating with a class variable.</p>
<p>I've commented out some of that code in WEBrick for the sake of experiment and it started to fail with:</p>
<pre><code>/Users/kir/src/github.com/ruby/ruby/lib/uri/common.rb:171:in `parse': can not access non-sharable objects in constant URI::RFC3986_PARSER by non-main ractor. (NameError)
from /Users/kir/src/github.com/ruby/ruby/lib/webrick/httprequest.rb:484:in `parse_uri'
from /Users/kir/src/github.com/ruby/ruby/lib/webrick/httprequest.rb:217:in `parse'
</code></pre>
<p>This can be easily reproduced with a smaller piece of code:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="n">parser</span> <span class="o">=</span> <span class="no">Ractor</span><span class="p">.</span><span class="nf">new</span> <span class="k">do</span>
<span class="no">URI</span><span class="o">::</span><span class="n">parse</span><span class="p">(</span><span class="s2">"http://example.com"</span><span class="p">)</span>
<span class="k">end</span>
<span class="no">Ractor</span><span class="p">.</span><span class="nf">select</span><span class="p">(</span><span class="n">parser</span><span class="p">)</span>
</code></pre>
<hr>
<p>IMO, something as tiny and safe as <code>URI::parse</code> should be allowrd to be called from a Ractor. We're either being too strict to the developer in terms of what constants they can reference from inside a Ractor, or we're missing a bunch of <code>freeze</code> in the standard library. It's likely the latter, but in that case we'll need to push for <code>freeze</code> as much as we can to make Ractor friendly to developers.</p>
<p>I'm very excited to see this happening in Ruby 3.0 and I'd like to help as much as I can to make it a great feature of Ruby.</p> Ruby master - Misc #17154 (Open): Update Pathname Documentation to Clarify Expected Behaviorhttps://bugs.ruby-lang.org/issues/171542020-09-05T02:29:29Zresperat (Ralph Esperat)
<p>I would like to suggest adding a sentence to the documentation for <a href="https://ruby-doc.org/stdlib-2.7.1/libdoc/pathname/rdoc/Pathname.html" class="external">Pathname</a> to make clear the unusual behavior of <code>Pathname#+</code> when an absolute path is included in the arguments. In such a situation, <code>Pathname#+</code> drops the paths prior to the last absolute path which I understand to be the intended behavior, but it is not obviously intended, only showing up tangentially as an example in the documentation.</p>
<pre><code>p3 = p1 + "/etc/passwd" # Pathname:/etc/passwd
</code></pre>
<p>The Pathname documentation states that " <strong>All functionality</strong> from File, FileTest, and some from Dir and FileUtils is included, <strong>in an unsurprising way</strong> ..." and later when referring to core methods such as <code>Pathname#+</code> "These methods are <strong>effectively manipulating a String</strong> , because that's all a path is." However, similar uses of both <a href="https://ruby-doc.org/core-2.7.1/File.html" class="external">File</a> and <a href="https://ruby-doc.org/core-2.7.1/String.html" class="external">String</a> would produce the expected result of including all of the arguments:</p>
<pre><code>s1 = "/usr"
s2 = s1 + "/etc/passwd" # "/usr/etc/passwd"
f1 = File.new("/usr" + "/etc/passwd") # (No such file or directory @ rb_sysopen - /usr/etc/passwd)
</code></pre>
<p>A bug report was previously filed to "fix" this functionality (<a class="issue tracker-1 status-6 priority-4 priority-default closed" title="Status: Rejected" href="https://bugs.ruby-lang.org/issues/15564">Bug #15564: Pathname#+(pathpart) returns pathpart when pathpart is absolute</a>), not understanding it to be intentional. Other common help websites such as <a href="https://stackoverflow.com/questions/12464361/concatenating-absolute-paths-with-the-pathname-class" class="external">Stack Overflow</a> also show users who do not expect this behavior from this method. Adding a statement to the documentation for the <a href="https://ruby-doc.org/stdlib-2.7.1/libdoc/pathname/rdoc/Pathname.html#method-i-2B" class="external">Pathname#+</a> method will make it clear to users exactly what to expect and that this is the intended behavior. I would suggest simply the following, the first sentence of which is already present:</p>
<p><code>Appends a pathname fragment to self to produce a new Pathname object. If an absolute path is provided as any of the arguments, discards all arguments prior to the last absolute path provided.</code></p>
<p>I appreciate your consideration of this request.</p>
<p>ruby -v: ruby 2.7.1p83 (2020-03-31 revision a0c7c23c9c) [x86_64-linux]</p> Ruby master - Misc #17053 (Open): RDoc for Hash Keyshttps://bugs.ruby-lang.org/issues/170532020-07-27T15:42:50Zburdettelamar@yahoo.com (Burdette Lamar)burdettelamar@example.com
<p>marcandre <a href="https://github.com/ruby/ruby/pull/3139#issuecomment-663281047" class="external">comments</a> on my pull request regarding <a href="https://docs.ruby-lang.org/en/master/Hash.html#class-Hash-label-Hash+Keys" class="external">documentation of Hash in Rdoc</a>:</p>
<blockquote>
<p>The only thing I would change is that I would shorten the doc on the "Invalid Hash Keys". As far as I know, this is simply not a[n] important concern as nearly all Ruby objects respond_to? :hash and :eql?</p>
</blockquote>
<blockquote>
<p>I personally would recommend adding a single example in the Hash.html#class-Hash-label-Hash+Keys section and I would remove the rest, or at least remove the examples. They burden the reader with something that is of no use to them.</p>
</blockquote>
<p>I have misgivings about it:</p>
<ul>
<li>Some of the material, for example, the text and example for user-defined hash keys, is very old.</li>
<li>I consolidated some material from earlier doc for individual methods, which now link to the relevant sections.</li>
<li>All are factual and not repeated elsewhere in the page.</li>
</ul>
<p>This is an API reference documentation. Ruby should have a <em>reference documentation</em>, and therefore should not omit anything.</p>
<p>If such material is to be included, I see three possibilities:</p>
<ul>
<li>Include inline, as is now.</li>
<li>Link to a footnote on the same page, with a back link.</li>
<li>Link to another rdoc page in <code>doc/</code> dir.</li>
</ul>
<p>I'd love to hear some opinions on this.</p> Ruby master - Misc #16895 (Open): Request for cooperation: Try your applications/libraries with m...https://bugs.ruby-lang.org/issues/168952020-05-15T09:13:23Zko1 (Koichi Sasada)
<a name="Summary"></a>
<h2 >Summary<a href="#Summary" class="wiki-anchor">¶</a></h2>
<p>If you maintain a Ruby application or library, please consider testing with the Ruby <code>master</code> branch, including the <em>debug</em> build. This should be in addition to testing with all supported stable releases of Ruby.</p>
<p>To make this easier, we are providing Docker images and GitHub actions, as outlined below.</p>
<a name="Details"></a>
<h2 >Details<a href="#Details" class="wiki-anchor">¶</a></h2>
<p>The rapid pace of Ruby development sometimes introduces bugs, such as incorrect behaviour or unexpected incompatibilities. Despite our best efforts and testing, without your feedback, we cannot catch every issue.</p>
<p>Understanding how our changes impact downstream code is important feedback for the Ruby core developers. We want to know how your applications work on master.</p>
<p>If you encounter an error when testing with the <code>master</code> branch (e.g. <code>[BUG] ...</code> in output log), <a href="https://bugs.ruby-lang.org" class="external">please report it</a>. It will be very helpful.</p>
<h3>Testing With <code>master</code>
</h3>
<p>Testing using the <code>master</code> branch (sometimes referred to as <code>ruby-head</code>) will make your Ruby scripts ready for the next Ruby version. It also helps us catch incompatibilities as we change and evolve Ruby's public interface.</p>
<a name="Testing-With-Debug-Build"></a>
<h3 >Testing With Debug Build<a href="#Testing-With-Debug-Build" class="wiki-anchor">¶</a></h3>
<p>Testing with the master branch debug build enables many assertions within the Ruby interpreter.</p>
<p>These assertions can detect incorrect usage of the C extensions, and also bugs in the interpreter when running your program.</p>
<p>These assertions have an impact on the performance of the interpreter.</p>
<p>To compile a debug build, refer the later section titled "Building With Debug Mode".</p>
<h2>Continuous Integration With <code>master</code>
</h2>
<p>Building Ruby for your own testing environment can be difficult, so we are providing two convenient ways to use the master branch in your existing testing pipeline:</p>
<ul>
<li>Docker Images</li>
<li>Github Action</li>
</ul>
<a name="Docker-Images"></a>
<h3 >Docker Images<a href="#Docker-Images" class="wiki-anchor">¶</a></h3>
<p>The <a href="https://hub.docker.com/r/rubylang/ruby" class="external">rubylang docker repository</a> provides images for various Ruby versions, including nightly builds of master with and without debug assertions"</p>
<ul>
<li>Nightly built master: <code>rubylang/ruby:master-nightly-bionic</code>
</li>
<li>Nightly debug built master: <code>rubylang/ruby:master-debug-nightly-bionic</code>
</li>
</ul>
<p>Here is an example <code>Dockerfile</code>:</p>
<pre><code class="dockerfile syntaxhl" data-language="dockerfile"><span class="k">FROM</span><span class="s"> rubylang/ruby:master-nightly-bionic</span>
</code></pre>
<p>Then to build:</p>
<pre><code class="shell syntaxhl" data-language="shell"><span class="nv">$ </span>docker build <span class="nb">.</span>
Sending build context to Docker daemon 2.048kB
Step 1/1 : FROM rubylang/ruby:master-nightly-bionic
master-nightly-bionic: Pulling from rubylang/ruby
...
Status: Downloaded newer image <span class="k">for </span>rubylang/ruby:master-nightly-bionic
<span class="nt">---</span><span class="o">></span> 059d367a8fbd
Successfully built 059d367a8fbd
</code></pre>
<a name="GitHub-Action"></a>
<h3 >GitHub Action<a href="#GitHub-Action" class="wiki-anchor">¶</a></h3>
<p>The <a href="https://github.com/ruby/setup-ruby" class="external">GitHub Action to setup Ruby</a> provides both <code>ruby-head</code> and <code>ruby-debug</code> builds.</p>
<p>Here is an example workflow to test on all Ruby stable releases, including <code>ruby-head</code> and <code>ruby-debug</code>:</p>
<pre><code class="yaml syntaxhl" data-language="yaml"><span class="na">name</span><span class="pi">:</span> <span class="s">Development</span>
<span class="na">on</span><span class="pi">:</span> <span class="pi">[</span><span class="nv">push</span><span class="pi">]</span>
<span class="na">jobs</span><span class="pi">:</span>
<span class="na">test</span><span class="pi">:</span>
<span class="na">strategy</span><span class="pi">:</span>
<span class="na">fail-fast</span><span class="pi">:</span> <span class="kc">false</span>
<span class="na">matrix</span><span class="pi">:</span>
<span class="na">os</span><span class="pi">:</span> <span class="pi">[</span><span class="nv">ubuntu</span><span class="pi">]</span>
<span class="na">ruby</span><span class="pi">:</span> <span class="pi">[</span><span class="nv">2.5</span><span class="pi">,</span> <span class="nv">2.6</span><span class="pi">,</span> <span class="nv">2.7</span><span class="pi">,</span> <span class="nv">head</span><span class="pi">,</span> <span class="nv">debug</span><span class="pi">]</span>
<span class="na">runs-on</span><span class="pi">:</span> <span class="s">${{ matrix.os }}-latest</span>
<span class="na">continue-on-error</span><span class="pi">:</span> <span class="s">${{ matrix.ruby == 'head' || matrix.ruby == 'debug' }}</span>
<span class="na">steps</span><span class="pi">:</span>
<span class="pi">-</span> <span class="na">uses</span><span class="pi">:</span> <span class="s">actions/checkout@v2</span>
<span class="pi">-</span> <span class="na">uses</span><span class="pi">:</span> <span class="s">ruby/setup-ruby@v1</span>
<span class="na">with</span><span class="pi">:</span>
<span class="na">ruby-version</span><span class="pi">:</span> <span class="s">${{ matrix.ruby }}</span>
<span class="pi">-</span> <span class="na">run</span><span class="pi">:</span> <span class="s">bundle install</span>
<span class="pi">-</span> <span class="na">run</span><span class="pi">:</span> <span class="s">bundle exec rake</span>
</code></pre>
<p>See the <a href="https://github.com/marketplace/actions/setup-ruby-jruby-and-truffleruby" class="external">documentation</a> for more details on how to use this action.</p>
<a name="Building-With-Debug-Mode"></a>
<h2 >Building With Debug Mode<a href="#Building-With-Debug-Mode" class="wiki-anchor">¶</a></h2>
<p>To create a debug build of Ruby, execute the following commands:</p>
<pre><code>$ git clone https://github.com/ruby/ruby.git
$ cd ruby
$ autoconf
$ cppflags=-DRUBY_DEBUG=1 ./configure --prefix=$HOME/.rubies/ruby-debug
$ make install
</code></pre>
<p>If you are using <code>chruby</code>, you can switch to the above build:</p>
<pre><code>$ chruby ruby-debug
</code></pre>
<p>You can find more details to build Ruby master in the <a href="https://github.com/ruby/ruby/blob/master/README.md#how-to-compile-and-install" class="external">README</a>.</p>
<a name="Acknowledgement"></a>
<h2 >Acknowledgement<a href="#Acknowledgement" class="wiki-anchor">¶</a></h2>
<p>We thank <a class="user active user-mention" href="https://bugs.ruby-lang.org/users/482">@mrkn (Kenta Murata)</a> for the Docker image, <a class="user active user-mention" href="https://bugs.ruby-lang.org/users/772">@Eregon (Benoit Daloze)</a> for the GitHub Action, and <a class="user active user-mention" href="https://bugs.ruby-lang.org/users/3344">@ioquatix (Samuel Williams)</a> for reviewing this announcement.</p> Ruby master - Misc #16803 (Open): Discussion: those internal macros reside in public API headershttps://bugs.ruby-lang.org/issues/168032020-04-21T07:45:49Zshyouhei (Shyouhei Urabe)shyouhei@ruby-lang.org
<p>A while ago I merged <a href="https://github.com/ruby/ruby/pull/2991" class="external">https://github.com/ruby/ruby/pull/2991</a> ("Split ruby.h"). This seems working. But the changeset raised several questions.</p>
<p>The biggest one relates to those newly publicised macros and inline functions. For instance <code>RUBY3_STATIC_ASSERT</code> is a macro that expands to either <code>_Static_assert</code> (for C) or <code>static_assert</code> (for C++). A similar mechanism has been implemented inside of our repository for a while. The pull request moved the definition around to be visible outside.</p>
<a name="Discussion-1"></a>
<h4 >Discussion #1<a href="#Discussion-1" class="wiki-anchor">¶</a></h4>
<p>Is it a good idea or a bad idea, to make them visible worldwide?</p>
<a name="Discussion-2"></a>
<h4 >Discussion #2<a href="#Discussion-2" class="wiki-anchor">¶</a></h4>
<p>Why not publicise everything? For instance debuggers could benefit from ruby internal symbols.</p>
<a name="Discussion-3"></a>
<h4 >Discussion #3<a href="#Discussion-3" class="wiki-anchor">¶</a></h4>
<p>It is relatively hard for us to change public APIs (doing so could break 3rd party gems). We don't want that happen for internal APIs. How do we achieve future flexibility?</p> Ruby master - Misc #16750 (Open): Change typedef of VALUE for better type checkinghttps://bugs.ruby-lang.org/issues/167502020-04-01T18:22:10ZDan0042 (Daniel DeLorme)
<p>VALUE is currently defined as <code>typedef unsigned long VALUE</code>, but as we all know that only creates an <em>alias</em>, not an actual <em>type</em>. Since the compiler gives no warnings when comparing with other integer values, it's easy to have bugs such as <code>v == 42</code> which should have been <code>v == INT2FIX(42)</code>. Actually not so long ago I saw nobu fixing a bug of that kind where an ID had been mixed up with a VALUE.</p>
<p>So in order to prevent these kinds of bugs I propose changing VALUE to a non-scalar type such as:</p>
<pre><code class="c syntaxhl" data-language="c"><span class="c1">//example for 64-bit system</span>
<span class="k">typedef</span> <span class="k">union</span> <span class="n">VALUE</span> <span class="p">{</span>
<span class="k">struct</span> <span class="n">RBasic</span><span class="o">*</span> <span class="n">as_basic</span><span class="p">;</span> <span class="c1">//easy access to obj.as_basic->klass and obj.as_basic->flags</span>
<span class="kt">void</span><span class="o">*</span> <span class="n">as_ptr</span><span class="p">;</span> <span class="c1">//can assign ptr = obj.as_ptr without a cast</span>
<span class="kt">unsigned</span> <span class="kt">long</span> <span class="n">i</span><span class="p">;</span> <span class="c1">//raw int value for bitwise operations</span>
<span class="kt">int</span> <span class="n">immediate</span> <span class="o">:</span> <span class="mi">3</span><span class="p">;</span> <span class="c1">//obj.immediate != 0 if obj is immediate type such as fixnum, flonum, static symbol</span>
<span class="kt">int</span> <span class="n">is_fixnum</span> <span class="o">:</span> <span class="mi">1</span><span class="p">;</span> <span class="c1">//obj.is_fixnum == 1 if obj is fixnum</span>
<span class="k">struct</span> <span class="p">{</span>
<span class="kt">int</span> <span class="n">flag</span> <span class="o">:</span> <span class="mi">2</span><span class="p">;</span> <span class="c1">//obj.flonum.flag == 2 if obj is flonum</span>
<span class="kt">int</span> <span class="n">bits</span> <span class="o">:</span> <span class="mi">62</span><span class="p">;</span>
<span class="p">}</span> <span class="n">flonum</span><span class="p">;</span>
<span class="k">struct</span> <span class="p">{</span>
<span class="kt">int</span> <span class="n">flag</span> <span class="o">:</span> <span class="mi">8</span><span class="p">;</span> <span class="c1">//obj.symbol.flag == 0x0c if obj is a static symbol</span>
<span class="kt">int</span> <span class="n">id</span> <span class="o">:</span> <span class="mi">56</span><span class="p">;</span> <span class="c1">//-> obj.symbol.id == STATIC_SYM2ID(obj)</span>
<span class="p">}</span> <span class="n">symbol</span><span class="p">;</span>
<span class="p">}</span> <span class="n">VALUE</span><span class="p">;</span>
</code></pre>
<p>This will allow proper type-checking via the compiler.</p>
<p>A little-known fact, structs and unions can be passed (and returned) by value to functions; this 64-bit union has the same performance as a 64-bit int. This approach also allows to simplify code like <code>((struct RBasic*)obj)->flags</code> into the much more readable <code>obj.as_basic->flags</code>, and <code>FIXNUM_P(obj)</code> can be expressed directly as <code>obj.is_fixnum</code>. The only downside is that direct comparison of union variables is not possible, so you would need to use for example <code>obj.i == Qfalse.i</code></p>
<p>To summarize, stricter type-checking would eliminate an entire class of bugs, and I estimate this change would require modifications to <strong>no more than 14%</strong> of the codebase (62,213 lines). Very much worth it I believe.</p> Ruby master - Misc #16678 (Open): Array#values_at has unintuitive behavior when supplied a range ...https://bugs.ruby-lang.org/issues/166782020-03-07T06:21:48Zprajjwal (Prajjwal Singh)
<p>Consider the following:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="c1"># frozen_string_literal: true</span>
<span class="n">a</span> <span class="o">=</span> <span class="p">(</span><span class="mi">1</span><span class="o">..</span><span class="mi">5</span><span class="p">).</span><span class="nf">to_a</span>
<span class="nb">p</span> <span class="n">a</span><span class="p">.</span><span class="nf">values_at</span><span class="p">(</span><span class="mi">3</span><span class="o">..</span><span class="mi">5</span><span class="p">)</span> <span class="c1"># => [4, 5, nil]</span>
<span class="nb">p</span> <span class="n">a</span><span class="p">.</span><span class="nf">values_at</span><span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="o">..</span><span class="mi">3</span><span class="p">)</span> <span class="c1"># => []</span>
</code></pre>
<p>When the range begins with a negative <code>(-1, 0, 1, 2, 3)</code>, it returns an empty array, which surprised me because I was expecting <code>[1, 2, 3, 4]</code>.</p>
<p>The argument for this is that it cold be confusing to allow this because the index <code>-1</code> could refer to the last argument and it would be unintuitive to return an array <code>[5, 1, 2, 3, 4]</code> with jumbled values.</p>
<p>The argument against it is that it makes perfect sense to account for this case and return <code>[nil, 1, 2, 3, 4]</code>.</p>
<p>Opening a dialog to see what others think of this.</p> Ruby master - Misc #16659 (Open): Documentation on Regexp missing for absence pattern (?~pat)https://bugs.ruby-lang.org/issues/166592020-02-27T16:16:20Zsvoop (Sven Schwyn)svoop_he38hj327c@delirium.ch
<p>The absence pattern <code>(?~pat)</code> available since Ruby 2.4.1 is <a href="https://git.ruby-lang.org/ruby.git/tree/doc/regexp.rdoc" class="external">not yet documented on <code>Regexp</code></a> as of today.</p>
<p>(Found it by coincidence reading <a href="https://medium.com/rubyinside/the-new-absent-operator-in-ruby-s-regular-expressions-7c3ef6cd0b99" class="external">this article by Peter Cooper</a>.</p> Ruby master - Misc #16507 (Open): =~ vs include? or match?https://bugs.ruby-lang.org/issues/165072020-01-12T23:27:07ZMSP-Greg (Greg L)
<p>While working on getting the mswin build working on Actions, I thought adding mswin? and ci? methods to Minitest::Unit::Guard in tool/lib/minitest/unit.rb would be helpful.</p>
<p>Currently some tests are failing that are guarded/skipped based on ENV['APPVEYOR']. For ci?, I'd combine Travis, AppVeyor, & Actions.</p>
<p>There are quite a few instances where =~ is used for a boolean return. Would it be considered appropriate to replace those calls with include? or match?</p> Ruby master - Misc #16487 (Open): Potential for SIMD usage in ruby-corehttps://bugs.ruby-lang.org/issues/164872020-01-08T09:48:29Zbyroot (Jean Boussier)byroot@ruby-lang.org
<a name="Context"></a>
<h3 >Context<a href="#Context" class="wiki-anchor">¶</a></h3>
<p>There are several ruby core methods that could be optimized with the use of SIMD instructions.</p>
<p>I experimented a bit on <code>coderange_scan</code> <a href="https://github.com/Shopify/ruby/pull/2" class="external">https://github.com/Shopify/ruby/pull/2</a>, and Pavel Rosický experimented on <code>String#strip</code> <a href="https://github.com/ruby/ruby/pull/2815" class="external">https://github.com/ruby/ruby/pull/2815</a>.</p>
<a name="Problem"></a>
<h3 >Problem<a href="#Problem" class="wiki-anchor">¶</a></h3>
<p>The downside of SIMD instructions is that they are not universally available.<br>
So it means maintaining several versions of the same code, and switching them either statically or dynamically.</p>
<p>And since most Ruby users use precompiled binaries from repositories and such, it would need to be dynamic if we want most users to benefit from it.</p>
<p>So it's not exactly "free speed", as it means a complexified codebase.</p>
<a name="Question"></a>
<h3 >Question<a href="#Question" class="wiki-anchor">¶</a></h3>
<p>So the question is to know wether ruby-core is open to patches using SIMD instructions ? And if so under which conditions.</p>
<p>cc <a class="user active user-mention" href="https://bugs.ruby-lang.org/users/10">@shyouhei (Shyouhei Urabe)</a></p> Ruby master - Misc #16436 (Open): hash missing #last method, make it not so consistent (it has #f...https://bugs.ruby-lang.org/issues/164362019-12-19T16:21:35Zzw963 (Wei Zheng)
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="p">(</span><span class="n">pry</span><span class="p">)</span><span class="ss">:main</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span><span class="o">></span> <span class="n">h</span> <span class="o">=</span> <span class="p">{</span><span class="n">x</span><span class="p">:</span><span class="mi">1</span><span class="p">,</span> <span class="n">y</span><span class="p">:</span><span class="mi">2</span><span class="p">,</span> <span class="n">z</span><span class="p">:</span><span class="mi">3</span><span class="p">}</span>
<span class="p">{</span>
<span class="ss">:x</span> <span class="o">=></span> <span class="mi">1</span><span class="p">,</span>
<span class="ss">:y</span> <span class="o">=></span> <span class="mi">2</span><span class="p">,</span>
<span class="ss">:z</span> <span class="o">=></span> <span class="mi">3</span>
<span class="p">}</span>
<span class="p">(</span><span class="n">pry</span><span class="p">)</span><span class="ss">:main</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span><span class="o">></span> <span class="n">h</span><span class="p">.</span><span class="nf">first</span>
<span class="p">[</span>
<span class="ss">:x</span><span class="p">,</span>
<span class="mi">1</span>
<span class="p">]</span>
<span class="p">(</span><span class="n">pry</span><span class="p">)</span><span class="ss">:main</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span><span class="o">></span> <span class="n">h</span><span class="p">.</span><span class="nf">first</span><span class="p">.</span><span class="nf">first</span>
<span class="ss">:x</span>
<span class="p">(</span><span class="n">pry</span><span class="p">)</span><span class="ss">:main</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span><span class="o">></span> <span class="n">h</span><span class="p">.</span><span class="nf">first</span><span class="p">.</span><span class="nf">last</span>
<span class="mi">1</span>
</code></pre>
<p>last method not exist.</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="p">(</span><span class="n">pry</span><span class="p">)</span><span class="ss">:main</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span><span class="o">></span> <span class="n">h</span><span class="p">.</span><span class="nf">last</span>
<span class="no">Exception</span><span class="p">:</span> <span class="no">NoMethodError</span><span class="p">:</span> <span class="n">undefined</span> <span class="nb">method</span> <span class="sb">`last' for {:x=>1, :y=>2, :z=>3}:Hash
</span></code></pre>
<p>We have to use #to_a to make last working.</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="p">(</span><span class="n">pry</span><span class="p">)</span><span class="ss">:main</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span><span class="o">></span> <span class="n">h</span><span class="p">.</span><span class="nf">to_a</span><span class="p">.</span><span class="nf">last</span>
<span class="p">[</span>
<span class="ss">:z</span><span class="p">,</span>
<span class="mi">3</span>
<span class="p">]</span>
<span class="p">(</span><span class="n">pry</span><span class="p">)</span><span class="ss">:main</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span><span class="o">></span> <span class="n">h</span><span class="p">.</span><span class="nf">to_a</span><span class="p">.</span><span class="nf">last</span><span class="p">.</span><span class="nf">first</span>
<span class="ss">:z</span>
<span class="p">(</span><span class="n">pry</span><span class="p">)</span><span class="ss">:main</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span><span class="o">></span> <span class="n">h</span><span class="p">.</span><span class="nf">to_a</span><span class="p">.</span><span class="nf">last</span><span class="p">.</span><span class="nf">last</span>
<span class="mi">3</span>
</code></pre> Ruby master - Misc #16408 (Open): Ruby docs list incorrect method signatures for PTY::getpty/PTY:...https://bugs.ruby-lang.org/issues/164082019-12-08T18:30:18Zyarmiganosca (Chris Hoffman)
<p>Ruby documentation says the method signature for <code>PTY::getpty</code>/<code>PTY::spawn</code> is</p>
<pre><code> * PTY.spawn(command_line) { |r, w, pid| ... }
* PTY.spawn(command_line) => [r, w, pid]
* PTY.spawn(command, arguments, ...) { |r, w, pid| ... }
* PTY.spawn(command, arguments, ...) => [r, w, pid]
</code></pre>
<p>However, running the following command with any Ruby since at least 2.1.9 (and based on git history, I believe since 2.0.0) will demonstrate that these method signatures are incorrect:</p>
<pre><code>ruby -rpty -e 'r, w, pid = PTY.spawn({"GREETING" => "hello"}, "echo $GREETING world"); puts r.gets(11); r.close; w.close'
</code></pre>
<p>(it will output <code>hello world</code>)</p>
<p>Further testing confirms that, aside from the block, <code>PTY::spawn</code> has the same method signature as <code>Kernel#exec</code>, <code>Kernel#system</code>, <code>Kernel#spawn</code>, and <code>Process::spawn</code>. This makes sense given that their C implementations all call the C method <code>rb_execarg_new</code> to handle the complex argument possibilities they all have to deal with.</p>
<p>I have a branch with tests that verify this: <a href="https://github.com/yarmiganosca/ruby/tree/fix-PTY-getpty-and-spawn-docs-and-tests" class="external">https://github.com/yarmiganosca/ruby/tree/fix-PTY-getpty-and-spawn-docs-and-tests</a></p>
<p>Travis isn't running CI on this branch, but I'm assuming that's account related and not an issue with my code, especially since the UI just informs me that I'm not allowed to.</p>
<p>I'm happy to also change the docs for <code>PTY::spawn</code> in this branch, but I wasn't sure which docs to emulate. The docs for this "family" of methods are inconsistent in how they explain the complicated options available to users:</p>
<ul>
<li>
<code>Kernel#spawn</code> explains in full the argument possibilities.</li>
<li>
<code>Kernel#exec</code> and <code>Kernel#system</code> both link to the docs for <code>Kernel#spawn</code>.</li>
<li>
<code>Process::spawn</code> explains in full (I think it might be a copy-paste job from the <code>Kernel#spawn</code> docs).</li>
<li>The docs for <code>IO::popen</code> (another method that uses the "execargs signature" with some modifications) list, but don't explain all the argument possibilities. They also don't do all that great a job at explaining where the other arguments from <code>IO::popen</code>'s signature fit alongside the "execargs signature".</li>
</ul>
<p>So it seems that there isn't consensus on the best way to explain this complex method signature (and modifications of it) to readers of the docs. Like I said, I'm happy to fix the <code>PTY::spawn</code> docs in this branch, but I was hoping for some guidance on which of the above documentation approaches to emulate.</p> Ruby master - Misc #16396 (Open): What is the reason for this behaviour of Find.find?https://bugs.ruby-lang.org/issues/163962019-12-03T13:03:26Zstiuna (Juan Gregorio)cart4for1@mail.com
<p>When I have a script at <code>D:\Downloads\Ruby 2.5.3\rbL\comp\codeShort.rb</code> with few other files in the same folder, the following searches only the folder where the <code>.rb</code> script is located:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="no">Find</span><span class="p">.</span><span class="nf">find</span><span class="p">(</span><span class="s1">'D:'</span><span class="p">)</span>
</code></pre>
<p>When I have a script at <code>D:\Downloads\Ruby 2.5.3\rbL\codeShort.rb</code> with many other files in the same folder, the same code as above searches the entire disk D.</p>
<p>To search the entire disk D in the first case, I did this:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="no">Find</span><span class="p">.</span><span class="nf">find</span><span class="p">(</span><span class="s1">'D:/'</span><span class="p">)</span>
</code></pre>
<p>But I don't understand why the two cases behave differently with the same instruction just because they script are in different directories.</p> Ruby master - Misc #16346 (Open): Confusing macro name: RUBY_MARK_NO_PIN_UNLESS_NULLhttps://bugs.ruby-lang.org/issues/163462019-11-13T07:39:44Zy_kojima (Yohei Kojima)
<p>function <code>rb_gc_mark_no_pin</code> is renamed to <code>rb_gc_mark_movable</code> in the commit <code>aac4d9d6c7e6b6b0742f3941b574f6006ccb5672</code>.<br>
But macro <code>RUBY_MARK_NO_PIN_UNLESS_NULL</code> is not renamed then.</p>
<p>Now, <code>RUBY_MARK_NO_PIN_UNLESS_NULL</code> calls <code>rb_gc_mark_movable</code>; this is a bit confusing.<br>
So I suggest renaming <code>RUBY_MARK_NO_PIN_UNLESS_NULL</code> to <code>RUBY_MARK_MOVABLE_UNLESS_NULL</code> like this patch.</p> Ruby master - Misc #16267 (Open): MinGW CI - add to Actions ?https://bugs.ruby-lang.org/issues/162672019-10-21T01:10:18ZMSP-Greg (Greg L)
<p>Actions has three embedded MSYS2 installs, as they currently install the three Windows Rubies with 'DevKits'. So, MinGW could be built/tested on Actions.</p>
<p>I have a GH action at <a href="https://github.com/MSP-Greg/msys2-action" class="external">https://github.com/MSP-Greg/msys2-action</a> that's used in Puma's CI, it allows updating the 'toolchain' and additional packages (typically things like ragel, openssl, etc).</p>
<p>JFYI...</p> Ruby master - Misc #16235 (Open): ENV.assoc spec test does not test invalid namehttps://bugs.ruby-lang.org/issues/162352019-10-03T21:05:12Zburdettelamar@yahoo.com (Burdette Lamar)burdettelamar@example.com
<p>The most important thing here is an added test for an invalid name argument to ENV.assoc, which should raise TypeError.</p>
<p>I've also added to spec_helper.rb:</p>
<ul>
<li>Methods :reserve_names and :release_names, to reserve and release names used in the test.</li>
<li>Method :mock_to_str, to return a mock object that responds to :to_str.</li>
</ul>
<p>The updated assoc_spec.rb uses all of these, as will many other spec tests for ENV, as I get to them.</p>
<p>It's known that some of the ENV spec tests do not test a method's return value, and that some do not test error conditions (as above), so more to come. All in good time.</p> Ruby master - Misc #16188 (Open): What are the performance implications of the new keyword argume...https://bugs.ruby-lang.org/issues/161882019-09-29T18:27:43ZEregon (Benoit Daloze)
<p>In <a class="issue tracker-2 status-5 priority-4 priority-default closed" title="Feature: "Real" keyword argument (Closed)" href="https://bugs.ruby-lang.org/issues/14183">#14183</a>, keyword arguments became further separated from positional arguments.</p>
<p>Contrary to the original design though, keyword and positional arguments are not fully separated for methods not accepting keyword arguments.<br>
Example: <code>foo(key: :value)</code> will <code>def foo(hash)</code> will pass a positional argument.<br>
This is of course better for compatibility, but I wonder what are the performance implications.</p>
<p>The block argument is completely separate in all versions, so no need to concern ourselves about that.</p>
<p>In Ruby <= 2.6:</p>
<ul>
<li>The caller never needs to know about the callee's arguments, it can just take all arguments and pass them as an array.<br>
The last argument might be used to extract keyword, but this is all done at the callee side.</li>
<li>Splitting kwargs composed of Symbol and non-Symbol keys can be fairly expensive, but it is a rare occurrence.<br>
If inlining the callee and kwargs are all passed as a literal Hash at the call site, there shouldn't be any overhead compared to positional arguments once JIT'ed.</li>
</ul>
<p>In Ruby 2.7:</p>
<ul>
<li>The caller needs to pass positional and keyword arguments separately, at least when calling a method accepting kwargs.<br>
But, if it calls a methods not accepting kwargs, then the "kwargs" (e.g. <code>foo(key: :value)</code>) should be treated just like a final Hash positional argument.</li>
<li>(If we had complete separation, then we could always pass positional and keyword arguments separately, so the caller could once again ignore the callee)</li>
</ul>
<p>How is the logic implemented in MRI for 2.7?</p>
<p>Specializing the caller for a given callee is a well-known technique.<br>
However, it becomes more difficult if different methods are called from the same callsite (polymorphic call), especially if one accepts kwargs and another does not.<br>
In that case, I think we will see a performance cost to this approach, by having to pass arguments differently based on the method to be called.</p>
<p>What about delegation using <code>ruby2_keywords</code>?<br>
Which checks does that add (compared to 2.6) in the merged approach with the Hash flag?</p> Ruby master - Misc #16160 (Open): Lazy init thread local storagehttps://bugs.ruby-lang.org/issues/161602019-09-09T21:36:28Zmethodmissing (Lourens Naudé)lourens@bearmetal.eu
<p>References PR <a href="https://github.com/ruby/ruby/pull/2295" class="external">https://github.com/ruby/ruby/pull/2295</a></p>
<a name="Why"></a>
<h3 >Why?<a href="#Why" class="wiki-anchor">¶</a></h3>
<p>The <code>local_storage</code> member of execution context is lazy initialized and drives the <code>Thread#[]</code> and <code>Thread#[]=</code> APIs, which are Fiber local and not Thread local storage. I think the same lazy init pattern should be applied to the APIs below as well - reduces one <code>Hash</code> alloc per thread created that does not use thread locals.</p>
<a name="Lazy-allocates-thread-local-storage-for-the-following-APIs"></a>
<h3 >Lazy allocates thread local storage for the following APIs<a href="#Lazy-allocates-thread-local-storage-for-the-following-APIs" class="wiki-anchor">¶</a></h3>
<ul>
<li>
<code>Thread#thread_variable_get</code> - early returns <code>nil</code> on locals Hash not initialised</li>
<li>
<code>Thread#thread_variable_set</code> - forces allocation of the locals Hash if not initilalised</li>
<li>
<code>Thread#thread_variables</code> - early returns the empty array AND saves on Hash iteration if locals Hash not initialised</li>
<li>
<code>Thread#thread_variable?</code> - early returns <code>false</code> on locals Hash not initialised</li>
</ul>
<a name="Other-notes"></a>
<h3 >Other notes<a href="#Other-notes" class="wiki-anchor">¶</a></h3>
<ul>
<li>Moved initial implementation from <code>internal.h</code> to <code>thread.c</code> local to call sites.</li>
<li>Preferred <code>defs/id.def</code> for the <code>locals</code> ID (seeing this pattern used more often, but not sure if that is preferred to inline <code>rb_intern</code> yet. Either way there's quite a few different conventions around IDs in the codebase at the moment and happy to help converging to a standard instead.</li>
<li>Maybe a flag is overkill and <code>NIL_P</code> on <code>locals</code> ivar could also work ...</li>
</ul>
<p>Thoughts?</p> Ruby master - Misc #16157 (Open): What is the correct and *portable* way to do generic delegation?https://bugs.ruby-lang.org/issues/161572019-09-09T14:10:42ZDan0042 (Daniel DeLorme)
<p>With the keyword argument changes in 2.7 we must now specify keyword arguments explicitly when doing generic delegation. But this change is not compatible with 2.6, where it adds an empty hash to the argument list of methods that do not need/accept keyword arguments.</p>
<p>To illustrate the problem:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">class</span> <span class="nc">ProxyWithoutKW</span> <span class="o"><</span> <span class="no">BasicObject</span>
<span class="k">def</span> <span class="nf">initialize</span><span class="p">(</span><span class="n">target</span><span class="p">)</span>
<span class="vi">@target</span> <span class="o">=</span> <span class="n">target</span>
<span class="k">end</span>
<span class="k">def</span> <span class="nf">method_missing</span><span class="p">(</span><span class="o">*</span><span class="n">a</span><span class="p">,</span> <span class="o">&</span><span class="n">b</span><span class="p">)</span>
<span class="vi">@target</span><span class="p">.</span><span class="nf">send</span><span class="p">(</span><span class="o">*</span><span class="n">a</span><span class="p">,</span> <span class="o">&</span><span class="n">b</span><span class="p">)</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="k">class</span> <span class="nc">ProxyWithKW</span> <span class="o"><</span> <span class="no">BasicObject</span>
<span class="k">def</span> <span class="nf">initialize</span><span class="p">(</span><span class="n">target</span><span class="p">)</span>
<span class="vi">@target</span> <span class="o">=</span> <span class="n">target</span>
<span class="k">end</span>
<span class="k">def</span> <span class="nf">method_missing</span><span class="p">(</span><span class="o">*</span><span class="n">a</span><span class="p">,</span> <span class="o">**</span><span class="n">o</span><span class="p">,</span> <span class="o">&</span><span class="n">b</span><span class="p">)</span>
<span class="vi">@target</span><span class="p">.</span><span class="nf">send</span><span class="p">(</span><span class="o">*</span><span class="n">a</span><span class="p">,</span> <span class="o">**</span><span class="n">o</span><span class="p">,</span> <span class="o">&</span><span class="n">b</span><span class="p">)</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="k">class</span> <span class="nc">Test</span>
<span class="k">def</span> <span class="nf">args</span><span class="p">(</span><span class="o">*</span><span class="n">a</span><span class="p">)</span> <span class="n">a</span> <span class="k">end</span>
<span class="k">def</span> <span class="nf">arg</span><span class="p">(</span><span class="n">a</span><span class="p">)</span> <span class="n">a</span> <span class="k">end</span>
<span class="k">def</span> <span class="nf">opts</span><span class="p">(</span><span class="o">**</span><span class="n">o</span><span class="p">)</span> <span class="n">o</span> <span class="k">end</span>
<span class="k">end</span>
<span class="c1"># 2.6 2.7 3.0</span>
<span class="no">ProxyWithoutKW</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="no">Test</span><span class="p">.</span><span class="nf">new</span><span class="p">).</span><span class="nf">args</span><span class="p">(</span><span class="mi">42</span><span class="p">)</span> <span class="c1"># [42] [42] [42] ok</span>
<span class="no">ProxyWithoutKW</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="no">Test</span><span class="p">.</span><span class="nf">new</span><span class="p">).</span><span class="nf">arg</span><span class="p">(</span><span class="mi">42</span><span class="p">)</span> <span class="c1"># 42 42 42 ok</span>
<span class="no">ProxyWithoutKW</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="no">Test</span><span class="p">.</span><span class="nf">new</span><span class="p">).</span><span class="nf">opts</span><span class="p">(</span><span class="ss">k: </span><span class="mi">42</span><span class="p">)</span> <span class="c1"># {:k=>42} {:k=>42} +warn [{:k=>42}] incompatible with >= 2.7</span>
<span class="no">ProxyWithKW</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="no">Test</span><span class="p">.</span><span class="nf">new</span><span class="p">).</span><span class="nf">args</span><span class="p">(</span><span class="mi">42</span><span class="p">)</span> <span class="c1"># [42, {}] [42] [42] incompatible with <= 2.6</span>
<span class="no">ProxyWithKW</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="no">Test</span><span class="p">.</span><span class="nf">new</span><span class="p">).</span><span class="nf">arg</span><span class="p">(</span><span class="mi">42</span><span class="p">)</span> <span class="c1"># error 42 42 incompatible with <= 2.6</span>
<span class="no">ProxyWithKW</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="no">Test</span><span class="p">.</span><span class="nf">new</span><span class="p">).</span><span class="nf">opts</span><span class="p">(</span><span class="ss">k: </span><span class="mi">42</span><span class="p">)</span> <span class="c1"># {:k=>42} {:k=>42} +warn {:k=>42} must ignore warning? cannot use pass_positional_hash in 2.6</span>
</code></pre>
<p>I don't know how to solve this, so I'm asking for the <strong>official</strong> correct way to write portable delegation code. And by <strong>portable</strong> I mean code that can be used in gems that target ruby 2.6 and above.</p> Ruby master - Misc #16130 (Open): [Discussion / Ideas] Finding a good name for the concept of/beh...https://bugs.ruby-lang.org/issues/161302019-08-27T11:59:08Zshevegen (Robert A. Heiler)shevegen@gmail.com
<p>In recent presentions this year, and perhaps prior to that as well if I<br>
remember correctly, matz mentioned that the core team (and matz) may be<br>
looking for a good name to the concept of/behind guilds.</p>
<p>The thread here, this issue, is PRIMARILY confined with this, the name -<br>
if you have any good suggestion for names in this context, or discussions<br>
that may relate to this secondarily, please feel free to chime in and<br>
comment. This is primarily meant to give some ideas, possibly.</p>
<p>Since koichi is also heavily involved here (matz pointed out that koichi<br>
likes the name guilds, and came up with the idea/proposal/implementation),<br>
I think this should be considered too. And of course how ruby users may<br>
want to use/view the concept behind guilds, and actually use them in<br>
their own code - the best idea is not great if nobody is using the<br>
concept. Like with refinements ... great idea but I found the API<br>
somewhat strange. :D (May also be because subclassing is so easy with<br>
"Foo < Bar"; ideally we could have something like this with refinements<br>
too, but this is for another proposal or discussion - this here is<br>
about the name for the concept behind guilds.)</p>
<p>Anyway.</p>
<p>I'll give my opinion too, on the names, but I will decouple this from<br>
the initial suggestion here, and reply to my own issue.</p>
<p>Note that this here really is primarily concerned with finding a good<br>
NAME, which is not trivial, since names may have different meanings<br>
in different contexts.</p>
<p>Furthermore, some links for those who may be curious - some of which<br>
are old, and I really just randomly linked these in:</p>
<p><a href="http://www.atdot.net/~ko1/activities/2016_rubykaigi.pdf" class="external">http://www.atdot.net/~ko1/activities/2016_rubykaigi.pdf</a><br>
<a href="https://mensfeld.pl/2016/11/getting-ready-for-new-concurrency-in-ruby-3-with-guilds/" class="external">https://mensfeld.pl/2016/11/getting-ready-for-new-concurrency-in-ruby-3-with-guilds/</a><br>
<a href="https://olivierlacan.com/posts/concurrency-in-ruby-3-with-guilds/" class="external">https://olivierlacan.com/posts/concurrency-in-ruby-3-with-guilds/</a></p> Ruby master - Misc #16114 (Open): Naming of "beginless range"https://bugs.ruby-lang.org/issues/161142019-08-21T23:34:44Zpwim (Paul McMahon)paul@doorkeeper.jp
<p><a class="issue tracker-2 status-5 priority-4 priority-default closed" title="Feature: Startless range (Closed)" href="https://bugs.ruby-lang.org/issues/14799">#14799</a> introduces a "beginless range" to complement the already existing "endless range". However, "beginless" isn't an existing word in English. Since the term for something without a beginning is "beginingless", I'd propose renaming "beginless range" to "beginningless range".</p> Ruby master - Misc #15802 (Open): Reduce the minimum string buffer size from 127 to 63 byteshttps://bugs.ruby-lang.org/issues/158022019-04-27T16:40:14Zmethodmissing (Lourens Naudé)lourens@bearmetal.eu
<p>References Github PR <a href="https://github.com/ruby/ruby/pull/2151" class="external">https://github.com/ruby/ruby/pull/2151</a> - another small change, but posting here for further discussion.</p>
<p>While having a look through <code>String</code> specific allocation paths with <a href="http://valgrind.org/docs/manual/dh-manual.html#dh-manual.overview" class="external">dhat</a> on redmine I noticed many string buffer use cases actually need way less than the current <code>128</code> byte minimum size (127 current minimum size + sentinel).</p>
<p>These auxiliary buffers are malloc heap specific as the <code>String</code> type is not supported by the transient heap due to complexity.</p>
<a name="How-to-interpret-the-DHAT-output"></a>
<h4 >How to interpret the DHAT output<a href="#How-to-interpret-the-DHAT-output" class="wiki-anchor">¶</a></h4>
<p>From the example output below, we can draw the following conclusions for the specific allocation site leading up to <code>rb_str_buf_new</code>:</p>
<ul>
<li>Total allocated size of <code>434944</code> bytes with a very low read and write access ratio under 25%</li>
<li>The buffer is thus 75% larger than it should be for this particular site (more examples further down below)</li>
<li>Short lived as expected from a buffer use case, but did occupy non-insignificant heap space still for a fair amount of time</li>
<li>The <code>0</code>s at the tail end of the output represent memory never accessed (rows are byte offsets)</li>
<li>As an aside, this particular string's first few characters are <code>hot</code> (accessed more frequently than the tail end)</li>
</ul>
<pre><code>==26579== -------------------- 95 of 300 --------------------
==26579== max-live: 330,368 in 2,581 blocks
==26579== tot-alloc: 434,944 in 3,398 blocks (avg size 128.00)
==26579== deaths: 3,347, at avg age 368,102,626 (2.64% of prog lifetime)
==26579== acc-ratios: 0.22 rd, 0.25 wr (97,275 b-read, 110,341 b-written)
==26579== at 0x4C2DECF: malloc (in /usr/lib/valgrind/vgpreload_exp-dhat-amd64-linux.so)
==26579== by 0x1521D3: objspace_xmalloc0 (gc.c:9407)
==26579== by 0x284A9B: rb_str_buf_new (string.c:1331)
==26579== by 0x31B9F7: rb_ary_join (array.c:2331)
==26579== by 0x2E5B4E: vm_call_cfunc_with_frame (vm_insnhelper.c:2207)
==26579== by 0x2E5B4E: vm_call_cfunc (vm_insnhelper.c:2225)
==26579== by 0x2F7C7C: vm_sendish (vm_insnhelper.c:3623)
==26579== by 0x2F7C7C: vm_exec_core (insns.def:789)
==26579== by 0x2EE34D: rb_vm_exec (vm.c:1892)
==26579== by 0x2EEEED: invoke_iseq_block_from_c (vm.c:1104)
==26579== by 0x2EEEED: invoke_block_from_c_bh (vm.c:1122)
==26579== by 0x2EEEED: vm_yield (vm.c:1167)
==26579== by 0x2EEEED: rb_yield_0 (vm_eval.c:980)
==26579== by 0x2EEEED: rb_yield_1 (vm_eval.c:986)
==26579== by 0x2EEEED: rb_yield (vm_eval.c:996)
==26579== by 0x31153B: rb_ary_each (array.c:2087)
==26579== by 0x2E5B4E: vm_call_cfunc_with_frame (vm_insnhelper.c:2207)
==26579== by 0x2E5B4E: vm_call_cfunc (vm_insnhelper.c:2225)
==26579== by 0x2F7D2B: vm_sendish (vm_insnhelper.c:3623)
==26579== by 0x2F7D2B: vm_exec_core (insns.def:771)
==26579== by 0x2EE34D: rb_vm_exec (vm.c:1892)
==26579==
==26579== Aggregated access counts by offset:
==26579==
==26579== [ 0] 11407 8731 9660 11112 11171 11724 13165 13609 10826 10998 11436 11420 11405 10295 9710 9316
==26579== [ 16] 5664 4959 3874 3607 2965 2395 1908 1509 1285 967 597 261 149 141 140 124
==26579== [ 32] 73 57 56 55 55 55 54 52 51 51 51 51 51 51 51 51
==26579== [ 48] 34 34 34 34 34 34 17 0 0 0 0 0 0 0 0 0
==26579== [ 64] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
==26579== [ 80] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
==26579== [ 96] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
==26579== [ 112] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
</code></pre>
<a name="Why-lower-is-better"></a>
<h4 >Why lower is better<a href="#Why-lower-is-better" class="wiki-anchor">¶</a></h4>
<p>The easiest reproducible case from the benchmark suite is the <code>require</code> benchmark (the allocation site below is from Rails though - DHAT is very slow and doesn't make sense in context of a benchmark):</p>
<pre><code>==28383== -------------------- 572 of 600 --------------------
==28383== max-live: 36,992 in 289 blocks
==28383== tot-alloc: 91,520 in 715 blocks (avg size 128.00)
==28383== deaths: 553, at avg age 908,212,488 (8.68% of prog lifetime)
==28383== acc-ratios: 6.15 rd, 0.41 wr (563,074 b-read, 37,525 b-written)
==28383== at 0x4C2DECF: malloc (in /usr/lib/valgrind/vgpreload_exp-dhat-amd64-linux.so)
==28383== by 0x1521D3: objspace_xmalloc0 (gc.c:9407)
==28383== by 0x284A9B: rb_str_buf_new (string.c:1331)
==28383== by 0x290D56: str_gsub (string.c:5163)
==28383== by 0x2E5B4E: vm_call_cfunc_with_frame (vm_insnhelper.c:2207)
==28383== by 0x2E5B4E: vm_call_cfunc (vm_insnhelper.c:2225)
==28383== by 0x2F7C7C: vm_sendish (vm_insnhelper.c:3623)
==28383== by 0x2F7C7C: vm_exec_core (insns.def:789)
==28383== by 0x2EE34D: rb_vm_exec (vm.c:1892)
==28383== by 0x18B336: rb_load_internal0 (load.c:612)
==28383== by 0x18E1B0: rb_require_internal (load.c:1028)
==28383== by 0x18E3B2: rb_require_safe (load.c:1074)
==28383== by 0x18E3B2: rb_f_require (load.c:821)
==28383== by 0x2E5B4E: vm_call_cfunc_with_frame (vm_insnhelper.c:2207)
==28383== by 0x2E5B4E: vm_call_cfunc (vm_insnhelper.c:2225)
==28383== by 0x2F1F42: vm_call_method (vm_insnhelper.c:2712)
==28383==
==28383== Aggregated access counts by offset:
==28383==
==28383== [ 0] 17936 15574 14945 15051 14538 15487 15599 15077 14658 14483 14826 14849 15232 15238 15522 15310
==28383== [ 16] 15055 15020 15143 15156 15271 14807 14656 14271 14051 13761 13365 13156 12756 12530 12302 12002
==28383== [ 32] 7652 7427 7106 6807 6594 6315 6044 5932 5750 5606 5520 5439 5347 5237 5174 5095
==28383== [ 48] 2252 2211 2158 2128 2117 2088 2075 2045 2034 2018 2006 1992 1974 1973 1964 1964
==28383== [ 64] 183 183 183 183 183 183 183 183 183 183 183 183 183 183 183 183
==28383== [ 80] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
==28383== [ 96] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
==28383== [ 112] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
</code></pre>
<pre><code>lourens@CarbonX1:~/src/ruby/ruby$ /usr/local/bin/ruby --disable=gems -rrubygems -I./benchmark/lib ./benchmark/benchmark-driver/exe/benchmark-driver --executables="compare-ruby::~/src/ruby/trunk/ruby --disable=gems -I.ext/common --disable-gem" --executables="built-ruby::./miniruby -I./lib -I. -I.ext/common -r./prelude --disable-gem" -v --repeat-count=24 -r ips $(ls ./benchmark/*require.{yml,rb} 2>/dev/null)
compare-ruby: ruby 2.7.0dev (2019-04-25 trunk 9bfc185a0d) [x86_64-linux]
built-ruby: ruby 2.7.0dev (2019-04-25 lower-str-buf-.. 9bfc185a0d) [x86_64-linux]
Calculating -------------------------------------
compare-ruby built-ruby
require 1.870 2.408 i/s - 1.000 times in 0.534865s 0.415268s
Comparison:
require
built-ruby: 2.4 i/s
compare-ruby: 1.9 i/s - 1.29x slower
lourens@CarbonX1:~/src/ruby/ruby$ /usr/local/bin/ruby --disable=gems -rrubygems -I./benchmark/lib ./benchmark/benchmark-driver/exe/benchmark-driver --executables="compare-ruby::~/src/ruby/trunk/ruby --disable=gems -I.ext/common --disable-gem" --executables="built-ruby::./miniruby -I./lib -I. -I.ext/common -r./prelude --disable-gem" -v --repeat-count=24 -r memory $(ls ./benchmark/*require.{yml,rb} 2>/dev/null)
compare-ruby: ruby 2.7.0dev (2019-04-25 trunk 9bfc185a0d) [x86_64-linux]
built-ruby: ruby 2.7.0dev (2019-04-25 lower-str-buf-.. 9bfc185a0d) [x86_64-linux]
Calculating -------------------------------------
compare-ruby built-ruby
require 28.128M 26.932M bytes - 1.000 times
Comparison:
require
built-ruby: 26932000.0 bytes
compare-ruby: 28128000.0 bytes - 1.04x larger
</code></pre>
<p>Also the <code>hash_aref_dsym_long</code> benchmark has significant memory reduction:</p>
<pre><code>lourens@CarbonX1:~/src/ruby/ruby$ /usr/local/bin/ruby --disable=gems -rrubygems -I./benchmark/lib ./benchmark/benchmark-driver/exe/benchmark-driver --executables="compare-ruby::~/src/ruby/trunk/ruby --disable=gems -I.ext/common --disable-gem" --executables="built-ruby::./miniruby -I./lib -I. -I.ext/common -r./prelude --disable-gem" -v --repeat-count=6 -r memory $(ls ./benchmark/hash_aref_dsym_long.{yml,rb} 2>/dev/null)
compare-ruby: ruby 2.7.0dev (2019-04-26 trunk 5689c46457) [x86_64-linux]
built-ruby: ruby 2.7.0dev (2019-04-26 lower-str-buf-.. 9abd605533) [x86_64-linux]
last_commit=Reduce the minimum string buffer size from 127 to 63 bytes
Calculating -------------------------------------
compare-ruby built-ruby
hash_aref_dsym_long 117.580M 104.984M bytes - 1.000 times
Comparison:
hash_aref_dsym_long
built-ruby: 104984000.0 bytes
compare-ruby: 117580000.0 bytes - 1.12x larger
</code></pre>
<a name="Other-allocation-sites-of-note"></a>
<h4 >Other allocation sites of note<a href="#Other-allocation-sites-of-note" class="wiki-anchor">¶</a></h4>
<pre><code>==26579== -------------------- 98 of 300 --------------------
==26579== max-live: 323,456 in 2,527 blocks
==26579== tot-alloc: 402,816 in 3,147 blocks (avg size 128.00)
==26579== deaths: 3,147, at avg age 377,614,197 (2.71% of prog lifetime)
==26579== acc-ratios: 0.21 rd, 0.16 wr (87,620 b-read, 64,622 b-written)
==26579== at 0x4C2DECF: malloc (in /usr/lib/valgrind/vgpreload_exp-dhat-amd64-linux.so)
==26579== by 0x1521D3: objspace_xmalloc0 (gc.c:9407)
==26579== by 0x284A9B: rb_str_buf_new (string.c:1331)
==26579== by 0x294584: rb_str_inspect (string.c:5911)
==26579== by 0x2F33F8: vm_call0_cfunc_with_frame (vm_eval.c:86)
==26579== by 0x2F33F8: vm_call0_cfunc (vm_eval.c:100)
==26579== by 0x2F33F8: vm_call0_body.constprop.410 (vm_eval.c:132)
==26579== by 0x2FE4CE: rb_vm_call0 (vm_eval.c:60)
==26579== by 0x2FE4CE: rb_call0 (vm_eval.c:309)
==26579== by 0x2FE4CE: rb_call (vm_eval.c:603)
==26579== by 0x2FE4CE: rb_funcall_with_block (vm_eval.c:857)
==26579== by 0x2EEFBE: vm_yield_with_symbol (vm_insnhelper.c:2869)
==26579== by 0x2EEFBE: invoke_block_from_c_bh (vm.c:1131)
==26579== by 0x2EEFBE: vm_yield (vm.c:1167)
==26579== by 0x2EEFBE: rb_yield_0 (vm_eval.c:980)
==26579== by 0x2EEFBE: rb_yield_1 (vm_eval.c:986)
==26579== by 0x2EEFBE: rb_yield (vm_eval.c:996)
==26579== by 0x317627: rb_ary_collect_bang (array.c:3052)
==26579== by 0x2E5B4E: vm_call_cfunc_with_frame (vm_insnhelper.c:2207)
==26579== by 0x2E5B4E: vm_call_cfunc (vm_insnhelper.c:2225)
==26579== by 0x2F7D2B: vm_sendish (vm_insnhelper.c:3623)
==26579== by 0x2F7D2B: vm_exec_core (insns.def:771)
==26579== by 0x2EE34D: rb_vm_exec (vm.c:1892)
==26579== by 0x2EEEED: invoke_iseq_block_from_c (vm.c:1104)
==26579== by 0x2EEEED: invoke_block_from_c_bh (vm.c:1122)
==26579== by 0x2EEEED: vm_yield (vm.c:1167)
==26579== by 0x2EEEED: rb_yield_0 (vm_eval.c:980)
==26579== by 0x2EEEED: rb_yield_1 (vm_eval.c:986)
==26579== by 0x2EEEED: rb_yield (vm_eval.c:996)
==26579==
==26579== Aggregated access counts by offset:
==26579==
==26579== [ 0] 13063 14338 12631 14007 13323 12720 11984 11344 9232 7280 6288 5776 4256 3856 3584 2976
==26579== [ 16] 1968 1216 1296 720 160 48 48 48 64 16 0 0 0 0 0 0
==26579== [ 32] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
==26579== [ 48] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
==26579== [ 64] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
==26579== [ 80] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
==26579== [ 96] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
==26579== [ 112] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
</code></pre>
<pre><code>==26579== -------------------- 186 of 300 --------------------
==26579== max-live: 155,136 in 1,212 blocks
==26579== tot-alloc: 155,136 in 1,212 blocks (avg size 128.00)
==26579== deaths: 651, at avg age 245,150,551 (1.75% of prog lifetime)
==26579== acc-ratios: 1.63 rd, 0.33 wr (253,660 b-read, 51,700 b-written)
==26579== at 0x4C2DECF: malloc (in /usr/lib/valgrind/vgpreload_exp-dhat-amd64-linux.so)
==26579== by 0x1521D3: objspace_xmalloc0 (gc.c:9407)
==26579== by 0x284A9B: rb_str_buf_new (string.c:1331)
==26579== by 0x13AA2E: rb_file_join (file.c:4732)
==26579== by 0x2E5B4E: vm_call_cfunc_with_frame (vm_insnhelper.c:2207)
==26579== by 0x2E5B4E: vm_call_cfunc (vm_insnhelper.c:2225)
==26579== by 0x2F7C7C: vm_sendish (vm_insnhelper.c:3623)
==26579== by 0x2F7C7C: vm_exec_core (insns.def:789)
==26579== by 0x2EE34D: rb_vm_exec (vm.c:1892)
==26579== by 0x2EEEED: invoke_iseq_block_from_c (vm.c:1104)
==26579== by 0x2EEEED: invoke_block_from_c_bh (vm.c:1122)
==26579== by 0x2EEEED: vm_yield (vm.c:1167)
==26579== by 0x2EEEED: rb_yield_0 (vm_eval.c:980)
==26579== by 0x2EEEED: rb_yield_1 (vm_eval.c:986)
==26579== by 0x2EEEED: rb_yield (vm_eval.c:996)
==26579== by 0x374412: dir_yield (dir.c:803)
==26579== by 0x374412: dir_each_entry (dir.c:860)
==26579== by 0x374412: dir_each (dir.c:830)
==26579== by 0x1355D2: rb_ensure (eval.c:1076)
==26579== by 0x373447: dir_foreach (dir.c:2955)
==26579== by 0x2E5B4E: vm_call_cfunc_with_frame (vm_insnhelper.c:2207)
==26579== by 0x2E5B4E: vm_call_cfunc (vm_insnhelper.c:2225)
==26579==
==26579== Aggregated access counts by offset:
==26579==
==26579== [ 0] 17075 17890 16143 17188 15855 18234 17616 19067 13136 11474 10379 11350 10094 9420 8556 7614
==26579== [ 16] 5325 5125 5030 4865 3582 2982 3010 3018 2997 3011 3056 3104 2695 2748 2696 2680
==26579== [ 32] 1741 1726 1664 1612 1285 1191 1138 1067 1043 1008 984 983 971 985 972 970
==26579== [ 48] 565 562 568 559 560 557 557 557 557 557 557 557 557 557 557 557
==26579== [ 64] 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4
==26579== [ 80] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
==26579== [ 96] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
==26579== [ 112] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
</code></pre>
<pre><code>==28716== -------------------- 64 of 300 --------------------
==28716== max-live: 273,280 in 2,135 blocks
==28716== tot-alloc: 446,464 in 3,488 blocks (avg size 128.00)
==28716== deaths: 2,277, at avg age 365,758,007 (3.44% of prog lifetime)
==28716== acc-ratios: 0.21 rd, 0.15 wr (96,380 b-read, 71,208 b-written)
==28716== at 0x4C2DECF: malloc (in /usr/lib/valgrind/vgpreload_exp-dhat-amd64-linux.so)
==28716== by 0x1521D3: objspace_xmalloc0 (gc.c:9407)
==28716== by 0x284A9B: rb_str_buf_new (string.c:1331)
==28716== by 0x294584: rb_str_inspect (string.c:5911)
==28716==
==28716== Aggregated access counts by offset:
==28716==
==28716== [ 0] 14382 15824 13909 15391 14767 14067 13241 12472 10180 7932 6842 6270 4714 4213 3909 3280
==28716== [ 16] 2173 1349 1386 810 216 63 54 55 68 20 1 0 0 0 0 0
==28716== [ 32] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
==28716== [ 48] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
==28716== [ 64] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
==28716== [ 80] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
==28716== [ 96] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
==28716== [ 112] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
</code></pre>
<pre><code>==28716== -------------------- 276 of 300 --------------------
==28716== max-live: 19,712 in 154 blocks
==28716== tot-alloc: 146,432 in 1,144 blocks (avg size 128.00)
==28716== deaths: 1,115, at avg age 150,688,929 (1.41% of prog lifetime)
==28716== acc-ratios: 0.06 rd, 0.08 wr (9,024 b-read, 12,049 b-written)
==28716== at 0x4C2DECF: malloc (in /usr/lib/valgrind/vgpreload_exp-dhat-amd64-linux.so)
==28716== by 0x1521D3: objspace_xmalloc0 (gc.c:9407)
==28716== by 0x284A9B: rb_str_buf_new (string.c:1331)
==28716== by 0x23B70C: rb_reg_regsub (re.c:3820)
==28716==
==28716== Aggregated access counts by offset:
==28716==
==28716== [ 0] 3569 4271 3304 1590 670 640 673 692 537 526 525 518 502 482 465 443
==28716== [ 16] 223 203 182 153 127 113 101 85 71 63 57 52 49 48 44 38
==28716== [ 32] 14 9 7 6 5 4 4 4 3 1 0 0 0 0 0 0
==28716== [ 48] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
==28716== [ 64] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
==28716== [ 80] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
==28716== [ 96] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
==28716== [ 112] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
</code></pre>
<pre><code>==29686== -------------------- 391 of 600 --------------------
==29686== max-live: 8,192 in 64 blocks
==29686== tot-alloc: 9,472 in 74 blocks (avg size 128.00)
==29686== deaths: 74, at avg age 207,459,973 (1.96% of prog lifetime)
==29686== acc-ratios: 0.21 rd, 0.17 wr (1,998 b-read, 1,628 b-written)
==29686== at 0x4C2DECF: malloc (in /usr/lib/valgrind/vgpreload_exp-dhat-amd64-linux.so)
==29686== by 0x1521D3: objspace_xmalloc0 (gc.c:9407)
==29686== by 0x284A9B: rb_str_buf_new (string.c:1331)
==29686== by 0x30BB8A: inspect_ary (array.c:2379)
==29686==
==29686== Aggregated access counts by offset:
==29686==
==29686== [ 0] 296 296 296 370 370 370 370 370 296 222 296 74 0 0 0 0
==29686== [ 16] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
==29686== [ 32] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
==29686== [ 48] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
==29686== [ 64] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
==29686== [ 80] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
==29686== [ 96] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
==29686== [ 112] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
</code></pre>
<a name="Rails-specific-redmine-boot"></a>
<h4 >Rails specific - redmine boot<a href="#Rails-specific-redmine-boot" class="wiki-anchor">¶</a></h4>
<p>Booting redmine only, no real work done otherwise - about <code>101720</code> bytes different in current malloc sizes. I understand <code>GC.malloc_allocated_size</code> to reflect the current delta between <code>xmalloc</code> and <code>xfree</code>, but may be wrong. And that value is not representative of total malloc heap churn, judging by the much higher total allocated values coming back from <a href="https://github.com/ruby/ruby/pull/2151#issuecomment-487300456" class="external">valgrind</a>.</p>
<pre><code>lourens@CarbonX1:~/src/redmine$ bundle exec rails c -e production
/home/lourens/src/redmine/vendor/bundle/ruby/2.7.0/gems/activerecord-5.2.1.1/lib/active_record/associations/builder/collection_association.rb:26: warning: Capturing the given block using Proc.new is deprecated; use `&block` instead
Loading production environment (Rails 5.2.1.1)
irb(main):001:0> RUBY_DESCRIPTION
=> "ruby 2.7.0dev (2019-04-26 trunk 5689c46457) [x86_64-linux]"
irb(main):002:0> GC.start
=> nil
irb(main):003:0> GC.malloc_allocated_size
=> 74907128
</code></pre>
<pre><code>lourens@CarbonX1:~/src/redmine$ bundle exec rails c -e production
/home/lourens/src/redmine/vendor/bundle/ruby/2.7.0/gems/activerecord-5.2.1.1/lib/active_record/associations/builder/collection_association.rb:26: warning: Capturing the given block using Proc.new is deprecated; use `&block` instead
Loading production environment (Rails 5.2.1.1)
irb(main):001:0> RUBY_DESCRIPTION
=> "ruby 2.7.0dev (2019-04-26 lower-str-buf-.. 9abd605533) [x86_64-linux]"
irb(main):002:0> GC.start
=> nil
irb(main):003:0> GC.malloc_allocated_size
=> 74805408
</code></pre>
<a name="Rails-specific-some-requests-workload"></a>
<h4 >Rails specific - some requests / workload<a href="#Rails-specific-some-requests-workload" class="wiki-anchor">¶</a></h4>
<p>Same sequence of redmine requests - 6 for this branch and trunk respectively using this as a simple initializer for reporting on exit, a <code>228600</code> bytes difference.</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">if</span> <span class="no">GC</span><span class="p">.</span><span class="nf">respond_to?</span><span class="p">(</span><span class="ss">:malloc_allocated_size</span><span class="p">)</span>
<span class="nb">at_exit</span> <span class="k">do</span>
<span class="nb">p</span> <span class="s2">"</span><span class="si">#{</span><span class="no">RUBY_DESCRIPTION</span><span class="si">}</span><span class="s2"> GC.malloc_allocated_size: </span><span class="si">#{</span><span class="no">GC</span><span class="p">.</span><span class="nf">malloc_allocated_size</span><span class="si">}</span><span class="s2">"</span>
<span class="k">end</span>
<span class="k">end</span>
</code></pre>
<pre><code>[2019-04-25 23:42:43] INFO WEBrick 1.4.2
[2019-04-25 23:42:43] INFO ruby 2.7.0 (2019-04-26) [x86_64-linux]
[2019-04-25 23:42:43] INFO WEBrick::HTTPServer#start: pid=31335 port=3000
127.0.0.1 - - [25/Apr/2019:23:42:48 WEST] "GET / HTTP/1.1" 200 4373
http://localhost:3000/news -> /
127.0.0.1 - - [25/Apr/2019:23:42:49 WEST] "GET /projects HTTP/1.1" 200 5470
http://localhost:3000/ -> /projects
127.0.0.1 - - [25/Apr/2019:23:42:51 WEST] "GET /activity HTTP/1.1" 200 7373
http://localhost:3000/projects -> /activity
127.0.0.1 - - [25/Apr/2019:23:42:51 WEST] "GET /issues HTTP/1.1" 200 19195
http://localhost:3000/activity -> /issues
127.0.0.1 - - [25/Apr/2019:23:42:52 WEST] "GET /time_entries HTTP/1.1" 200 12508
http://localhost:3000/issues -> /time_entries
127.0.0.1 - - [25/Apr/2019:23:42:53 WEST] "GET /issues/gantt HTTP/1.1" 200 22597
http://localhost:3000/time_entries -> /issues/gantt
127.0.0.1 - - [25/Apr/2019:23:42:54 WEST] "GET /issues/calendar HTTP/1.1" 200 16712
http://localhost:3000/issues/gantt -> /issues/calendar
127.0.0.1 - - [25/Apr/2019:23:42:54 WEST] "GET /news HTTP/1.1" 200 5472
http://localhost:3000/issues/calendar -> /news
^C[2019-04-25 23:42:58] INFO going to shutdown ...
[2019-04-25 23:42:59] INFO WEBrick::HTTPServer#start done.
Exiting
"ruby 2.7.0dev (2019-04-26 trunk 5689c46457) [x86_64-linux] GC.malloc_allocated_size: 84901440"
</code></pre>
<pre><code>[2019-04-25 23:41:51] INFO WEBrick 1.4.2
[2019-04-25 23:41:51] INFO ruby 2.7.0 (2019-04-26) [x86_64-linux]
[2019-04-25 23:41:51] INFO WEBrick::HTTPServer#start: pid=31029 port=3000
127.0.0.1 - - [25/Apr/2019:23:41:59 WEST] "GET / HTTP/1.1" 200 4373
http://localhost:3000/activity -> /
127.0.0.1 - - [25/Apr/2019:23:42:02 WEST] "GET /projects HTTP/1.1" 200 5470
http://localhost:3000/ -> /projects
127.0.0.1 - - [25/Apr/2019:23:42:04 WEST] "GET /activity HTTP/1.1" 200 7373
http://localhost:3000/projects -> /activity
127.0.0.1 - - [25/Apr/2019:23:42:05 WEST] "GET /issues HTTP/1.1" 200 19195
http://localhost:3000/activity -> /issues
127.0.0.1 - - [25/Apr/2019:23:42:06 WEST] "GET /time_entries HTTP/1.1" 200 12508
http://localhost:3000/issues -> /time_entries
127.0.0.1 - - [25/Apr/2019:23:42:07 WEST] "GET /issues/gantt HTTP/1.1" 200 22597
http://localhost:3000/time_entries -> /issues/gantt
127.0.0.1 - - [25/Apr/2019:23:42:07 WEST] "GET /javascripts/raphael.js?1543965852 HTTP/1.1" 200 90648
http://localhost:3000/issues/gantt -> /javascripts/raphael.js?1543965852
127.0.0.1 - - [25/Apr/2019:23:42:08 WEST] "GET /issues/calendar HTTP/1.1" 200 16712
http://localhost:3000/issues/gantt -> /issues/calendar
127.0.0.1 - - [25/Apr/2019:23:42:09 WEST] "GET /news HTTP/1.1" 200 5472
http://localhost:3000/issues/calendar -> /news
^C[2019-04-25 23:42:14] INFO going to shutdown ...
[2019-04-25 23:42:15] INFO WEBrick::HTTPServer#start done.
Exiting
"ruby 2.7.0dev (2019-04-26 lower-str-buf-.. 9abd605533) [x86_64-linux] GC.malloc_allocated_size: 84672840"
</code></pre> Ruby master - Misc #15744 (Open): Improvement needed to documentation of 'Literals'https://bugs.ruby-lang.org/issues/157442019-04-02T17:34:46ZCaryInVictoria (Cary Swoveland)cary@swoveland.com
<p>Documentation of "Literals" for v2.6.0 is given here: <a href="https://docs.ruby-lang.org/en/2.6.0/syntax/literals_rdoc.html" class="external">https://docs.ruby-lang.org/en/2.6.0/syntax/literals_rdoc.html</a>. (I don't think it has been changed for some time.) It gives examples of literals but does not provide a definition. It is comparable to defining an array by giving a few examples. I believe a definition is needed.</p>
<p>I would like to suggest a definition, but I confess I don't know what a Ruby literal is. A definition is attempted at this Wiki for computer programming generally: <a href="https://en.wikipedia.org/wiki/Literal_(computer_programming)" class="external">https://en.wikipedia.org/wiki/Literal_(computer_programming)</a>.</p>
<p>I suspect a Ruby literal is an object whose value is in some sense "known" at compile-time. For example, I would think <code>1</code>, <code>1.0</code> and <code>{ a: [1, 'cat', ['dog', ['pig', ..10]]] }</code> are literals but <code>{ v=>1, 2=>3 }</code> in <code>h = { v=>1, 2=>3 }</code>, <code>v</code> being a variable, is not. Or is it? If the previous line of code had been <code>v=3</code>, Ruby could, at compile-time, infer that the line could be replaced with <code>h = {3=>1, 2=>3}</code>, in which case it would be "known". This example is meant to illustrate why I earlier said "in some sense".</p> Ruby master - Misc #15654 (Open): Documentation for Complex is wrong or misleadinghttps://bugs.ruby-lang.org/issues/156542019-03-11T08:43:36Zsawa (Tsuyoshi Sawada)
<p>The documentation for <code>Complex</code> <a href="https://ruby-doc.org/core-2.6/Complex.html" class="external">https://ruby-doc.org/core-2.6/Complex.html</a> says or implies that a complex can be created by literal like <code>2+1i</code>, but that is actually calling the method <code>+</code> on receiver <code>2</code> with argument <code>1i</code>. The description should be changed to make it clear that <code>2+ 1i</code> is not a literal but is applying a method.</p> Ruby master - Misc #15568 (Open): TracePoint(:raise)#parameters raises RuntimeErrorhttps://bugs.ruby-lang.org/issues/155682019-01-26T21:10:29Zbaweaver (Brandon Weaver)keystonelemur@gmail.com
<p>Currently trying to get the <code>trace.parameters</code> of a method in a <code>raise</code> event will lead to a RuntimeError. I would contend that it should not, and that it would be perfectly valid to ask for the parameters in the case of an exception.</p>
<p>The reason I do this is to see the arguments at the time of exception:</p>
<pre><code>def extract_args(trace)
trace.parameters.map(&:last).to_h do |name|
[name, trace.binding.eval(name.to_s)]
end
end
</code></pre>
<p>I've noticed that I can technically "cheat" and get these same values like this:</p>
<pre><code>def extract_args(trace)
trace.binding.eval('local_variables').to_h do |name|
[name, trace.binding.eval(name.to_s)]
end
end
</code></pre>
<p>Having the ability to get the parameters in a <code>raise</code> context would be very useful for debugging.</p>
<p>I'm tempted to also suggest <code>TracePoint#local_variables</code> as it would provide additional context in a more exposed way than <code>TracePoint#binding.eval('local_variables')</code></p> Ruby master - Misc #15514 (Open): Add documentation for implicit array decompositionhttps://bugs.ruby-lang.org/issues/155142019-01-07T10:26:51Zsos4nt (Stefan Schüßler)mail@stefanschuessler.de
<p>The documentation for <a href="http://ruby-doc.org/core/doc/syntax/assignment_rdoc.html#label-Array+Decomposition" class="external">Array Decomposition</a> says: <em>"[...] you can decompose an Array during assignment using parenthesis [sic]"</em> and gives an example:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">)</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">]</span>
<span class="nb">p</span> <span class="ss">a: </span><span class="n">a</span><span class="p">,</span> <span class="ss">b: </span><span class="n">b</span> <span class="c1"># prints {:a=>1, :b=>2}</span>
</code></pre>
<p>But – as we all know – it's also possible <em>without</em> parentheses, i.e.</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="n">a</span><span class="p">,</span> <span class="n">b</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">]</span>
<span class="nb">p</span> <span class="ss">a: </span><span class="n">a</span> <span class="p">,</span> <span class="ss">b: </span><span class="n">b</span> <span class="c1">#=> {:a=>1, :b=>2}</span>
</code></pre>
<p>This also applies to block arguments when yielding multiple values vs. yielding a single array:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">def</span> <span class="nf">foo</span>
<span class="k">yield</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">2</span>
<span class="k">end</span>
<span class="k">def</span> <span class="nf">bar</span>
<span class="k">yield</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">]</span>
<span class="k">end</span>
<span class="n">foo</span> <span class="p">{</span> <span class="o">|</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="o">|</span> <span class="nb">p</span> <span class="ss">a: </span><span class="n">a</span><span class="p">,</span> <span class="ss">b: </span><span class="n">b</span> <span class="p">}</span>
<span class="c1">#=> {:a=>1, :b=>2}</span>
<span class="n">bar</span> <span class="p">{</span> <span class="o">|</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="o">|</span> <span class="nb">p</span> <span class="ss">a: </span><span class="n">a</span><span class="p">,</span> <span class="ss">b: </span><span class="n">b</span> <span class="p">}</span>
<span class="c1">#=> {:a=>1, :b=>2}</span>
</code></pre>
<p>In both cases, parentheses are optional.</p>
<p>This implicit array decomposition could be quite surprising for newcomers. The documentation should cover it.</p> Ruby master - Misc #15510 (Open): Easter egg in Thread.handle_interrupthttps://bugs.ruby-lang.org/issues/155102019-01-05T20:42:12Zlarskanis (Lars Kanis)
<p>The docs of <code>Thread.handle_interrupt</code> are quite clear about the argument to be passed. It must be a hash of <code>ExceptionClass => :TimingSymbol</code> pairs. I never thought that anything other than a <code>Exception</code> derivation would be accepted.</p>
<p>But then I read the tests to this method and wondered: <a href="https://github.com/ruby/ruby/blob/trunk/test/ruby/test_thread.rb#L783" class="external">Some of the tests</a> set <code>Object</code> as <code>ExceptionClass</code>. Moreover the method is not covered by ruby-spec and JRuby <a href="https://github.com/jruby/jruby/blob/66d2905ae233a39e36fcbe3ade6382c2892ade8e/test/mri/excludes/TestThread.rb" class="external">excludes several failing tests</a>.</p>
<p>So I inspected the code and found some obscure behavior: There are actually <a href="https://github.com/ruby/ruby/blob/trunk/thread.c#L115-L116" class="external">two non-exceptions</a> which can be masked by <code>Thread.handle_interrupt(Integer => :TimingSymbol)</code>. It is main thread termination and <code>Thread#kill</code>. Now this <a href="https://github.com/ruby/ruby/blob/trunk/thread.c#L1891-L1894" class="external">blur sentence in the docs</a> makes some more sense:</p>
<blockquote>
<p>interrupt means asynchronous event and corresponding procedure by Thread#raise, Thread#kill, signal trap (not supported yet) and main thread termination (if main thread terminates, then all other thread will be killed).</p>
</blockquote>
<p>So they are implemented as integers internally. However IMHO <code>Thread.handle_interrupt(Integer => :TimingSymbol)</code> is ... ugly.</p>
<p>Some proposals are:</p>
<ol>
<li>Make non-exceptions an ruby implementation specific feature, adjusts current tests and optionally add tests which are tagged as implementation specific.</li>
<li>Document it officially, but choose some more meaningful class names instead of <code>Integer</code>
</li>
</ol> Ruby master - Misc #15431 (Open): Hashes and arrays should not require commas to seperate values ...https://bugs.ruby-lang.org/issues/154312018-12-18T04:14:25Znsuchy (Nathaniel Suchy)me@lunorian.is
<p>Ruby should not require commas for hash and array values if using new lines. I think the syntax would look cleaner without.</p>
<p><strong>Example</strong></p>
<pre><code>myHash = {
:key => “value”,
:anotherKey => “another value”
}
</code></pre>
<p><strong>Could be</strong></p>
<pre><code>myHash = {
:key => “value”
:anotherKey => “another value”
}
</code></pre>
<p><strong>And</strong></p>
<pre><code>myArray = [
1,
2,
3
]
</code></pre>
<p>Could be:</p>
<pre><code>myArray = [
1
2
3
]
</code></pre>
<p>The syntax looks a bit cleaner, with the new lines is there a need to require a comma? I look forward to hearing the community’s thoughts on this idea :)</p> Ruby master - Misc #15418 (Open): Date.parse('2018')https://bugs.ruby-lang.org/issues/154182018-12-15T18:43:56Zfoonlyboy (Eike Dierks)
<p>Date.parse('2018')<br>
ArgumentError: invalid date</p>
<p>I did expect that to return the same as:<br>
Date.parse('2018-1-1')<br>
=> Mon, 01 Jan 2018</p>
<p>working with dates and times is really weird and complicated,<br>
so it makes sense to be strict with parsing.</p>
<p>I watched this one:<br>
<a href="https://www.youtube.com/watch?v=-5wpm-gesOY" class="external">https://www.youtube.com/watch?v=-5wpm-gesOY</a><br>
He's really coming up with some some crazy test cases.</p>
<p>In ruby this is split between Time and DateTime,<br>
some in the core, some in in the standard lib.</p>
<hr>
<p>Im looking forward for the new version,<br>
let's freeze the strings!</p>
<p>~eike</p> Ruby master - Misc #15402 (Open): Shrinking excess retained memory of container types on promotio...https://bugs.ruby-lang.org/issues/154022018-12-11T20:43:38Zmethodmissing (Lourens Naudé)lourens@bearmetal.eu
<p>I've been toying with the idea of the viability of attempting to reclaim over provisioned memory from buffer capacity of container objects like <code>Array</code> and <code>String</code>, effectively reducing the footprint of retained memory of such objects.</p>
<p>GC at the moment covers these dominant paths:</p>
<ul>
<li>Collection of shallow memory: unreferenced object slot with values encoded on the object</li>
<li>Collection of retained memory: unreferenced object slot with off ruby object heap pointer to String buffer, Array buffer etc. (<code>heap.aux</code>)</li>
<li>Finalization hooks like reclaiming resources for <code>Tempfile</code> for example</li>
</ul>
<p>I explored in <a href="https://github.com/ruby/ruby/pull/2037" class="external">https://github.com/ruby/ruby/pull/2037</a> (more details and data points on the PR) a forth one:</p>
<ul>
<li>Shrinking over provisioned buffer capacity of <code>Array</code> (also applies to <code>String</code> and likely others) on promotion to uncollectible (<code>Also garbage collect excess retained space from types with a first class capacity and buffer on promotion to uncollectible</code>)</li>
</ul>
<p>Sharing here for feedback in case anyone has ideas for a more appropriate hook, or additional precondition for such a hook. Or if excess buffer capacity can even be considered first class garbage in a GC context.</p>
<p>I chose <code>Array</code> as a proof of concept because the type already have this optimization through <code>ary_shrink_capa</code> through <code>ary_make_shared</code> and the threshold for not encoding members on the object is quite low at 3 elements. Plausible that many framework / boot specific long lived arrays are larger than that and because the growth factor on expansion is <code>2x</code>, also likely a fair amount of over provisioned capacity.</p>
<p>Results of the changeset:</p>
<ul>
<li>Benchmark <code>so_binary_trees</code> - <code>26%</code> reduction in total memory usage</li>
<li>Also a very noticeable <code>24%</code> difference with <code>app_lc_fizzbuzz</code>
</li>
<li>General few bytes reduction for almost all core benchmarks</li>
<li>Mainline <code>redmine</code> after boot - <code>1.5%</code> or <code>45kb</code> reduction in <code>Array</code> retained memory size</li>
</ul>
<p>Implementation caveats:</p>
<ul>
<li>Promotion to uncollectible may be a bad heuristic for shrinking buffer capacity.</li>
<li>Needed to create a new <code>rb_ary_shrink_capa</code> function as <code>ary_shrink_capa</code> is private API and has several assertions (frozen and shared check) that hard fails during GC. That way shrinking responsibility and accounting remains the responsibility of <code>array.c</code> - the GC just calls it (same as with the <code>memsize</code> APIs)</li>
<li>I tried running it during GC which worked fine for benchmarks like <code>so_binary_trees</code> but failed under GC stress and larger heaps because of <code>TRY_WITH_GC</code> via <code>objspace_xrealloc</code>, which can invoke GC</li>
<li>A reasonable workaround for this was to use the postponed job API which is used by GC for object finalization, but that's one job per object space, not 1 per Array being shrinked, which may hit the 1000 item postponed job buffer for some heaps. It degrades gracefully though with fallback being the optimization simply not being applied to the excess objects in the set.</li>
<li>Have no idea about the future of the postponed job API and if this is an appropriate use case</li>
<li>
<code>RVALUE_PAGE_OLD_UNCOLLECTIBLE_SET</code> only special cases <code>Array</code> at the moment - it's easy to support other types</li>
</ul>
<p>Outliers to still evaluate:</p>
<ul>
<li>Fragmentation does not get significantly worse through <code>reallocs</code> for specific rare cases post GC (no data)</li>
<li>The effect of <code>objspace_malloc_increase</code> called by <code>objspace_xrealloc</code> on GC frequency (I think not much given the small reduction on retained usage, but have no data to prove yet)</li>
<li>How well the postponed job pattern scales to large heaps and how much of the job slots are consumed (no data)</li>
</ul>
<p>Thoughts on exploring more types or is the pattern tainted / broken to begin with?</p> Ruby master - Misc #15249 (Open): Documentation for attr_accessor and attr_reader should be corre...https://bugs.ruby-lang.org/issues/152492018-10-23T20:09:02ZCaryInVictoria (Cary Swoveland)cary@swoveland.com
<p>The documentation for <a href="http://ruby-doc.org/core-2.5.1/Module.html#method-i-attr_accessor" class="external">Module#attr_accessor</a> (v2.5.1) begins, "Defines a named attribute for this module, where the name is symbol.id2name, creating an instance variable (@name) and...". Similarly, the documentation for <a href="http://ruby-doc.org/core-2.5.1/Module.html#method-i-attr_reader" class="external">Module#attr_reader</a> states, "Creates instance variables and...". These statements do not appear to be correct:</p>
<pre><code>class C
attr_accessor :dog
attr_reader :cat
end
C.new.instance_variables #=> []
</code></pre> Ruby master - Misc #15224 (Open): [DOCs] Minor inconsistency in class Array #initialize_copy - ht...https://bugs.ruby-lang.org/issues/152242018-10-13T10:18:57Zshevegen (Robert A. Heiler)shevegen@gmail.com
<p>Today I looked at:</p>
<p><a href="https://ruby-doc.org/core-2.5.1/Array.html#method-i-initialize_copy" class="external">https://ruby-doc.org/core-2.5.1/Array.html#method-i-initialize_copy</a></p>
<p>The example to this method is this:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="n">a</span> <span class="o">=</span> <span class="p">[</span> <span class="s2">"a"</span><span class="p">,</span> <span class="s2">"b"</span><span class="p">,</span> <span class="s2">"c"</span><span class="p">,</span> <span class="s2">"d"</span><span class="p">,</span> <span class="s2">"e"</span> <span class="p">]</span>
<span class="n">a</span><span class="p">.</span><span class="nf">replace</span><span class="p">([</span> <span class="s2">"x"</span><span class="p">,</span> <span class="s2">"y"</span><span class="p">,</span> <span class="s2">"z"</span> <span class="p">])</span> <span class="c1">#=> ["x", "y", "z"]</span>
<span class="n">a</span> <span class="c1">#=> ["x", "y", "z"]</span>
</code></pre>
<p>What confused me was that I was looking at the method called <code>initialize_copy</code><br>
but the example showed <code>.replace()</code>.</p>
<p>I then looked at <code>#replace</code> there:</p>
<p><a href="https://ruby-doc.org/core-2.5.1/Array.html#method-i-replace" class="external">https://ruby-doc.org/core-2.5.1/Array.html#method-i-replace</a></p>
<p>And it was virtually identical to <code>initialize_copy</code>.</p>
<p>I assume the examples for <code>.replace()</code> are correct; and perhaps <code>initialize_copy</code><br>
is just an alias? I am not sure, but I would like to suggest to make the documentation,<br>
in particular the example, a bit more consistent.</p>
<p>When you click on "view source" to look at the C code, they show the very same<br>
content, so I believe that initialize_copy is merely an alias to replace; but I tried<br>
this and they are not fully equivalent:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="n">x</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">]</span> <span class="c1"># => [1, 2, 3]</span>
<span class="n">x</span><span class="p">.</span><span class="nf">initialize_copy</span> <span class="p">[</span><span class="mi">4</span><span class="p">,</span><span class="mi">5</span><span class="p">,</span><span class="mi">6</span><span class="p">]</span>
</code></pre>
<pre><code>Traceback (most recent call last):
2: from /System/Index/bin/irb:11:in `<main>'
1: from (irb):2
NoMethodError (private method `initialize_copy' called for [1, 2, 3]:Array)
</code></pre>
<p>Yet:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="n">x</span><span class="p">.</span><span class="nf">replace</span> <span class="p">[</span><span class="mi">4</span><span class="p">,</span><span class="mi">5</span><span class="p">,</span><span class="mi">6</span><span class="p">]</span> <span class="c1"># => [4, 5, 6]</span>
</code></pre>
<p>works. So I assume that <code>initialize_copy</code> is like <code>.replace()</code> but is a private<br>
method instead.</p>
<p>Perhaps it may help to add a sentence below the documentation of<br>
<code>replace()</code>, to explain what the use case for <code>initialize_copy</code> is. Or to perhaps<br>
mention that it is an alias.</p>
<p>At the least how it is right now is that people may read <code>initialize_copy</code>,<br>
but then see an example of <code>#replace</code>. (Perhaps an example for<br>
<code>initialize_copy</code> may help, but either way, I think the current docu-example<br>
is not ideal).</p> Ruby master - Misc #15202 (Open): Adding Coverity Scan to CI to see the result casuallyhttps://bugs.ruby-lang.org/issues/152022018-10-04T14:06:33Zjaruga (Jun Aruga)
<p>Recently I reported issues detected by code analysis tool mainly using Coverity Scan.</p>
<p>The 9 issues categorized as "important" was fixed by <a class="issue tracker-1 status-5 priority-4 priority-default closed" title="Bug: Fixing issues detected by an Analysis tool. (Closed)" href="https://bugs.ruby-lang.org/issues/15116">#15116</a>. (Thank you!)</p>
<blockquote>
<p><a href="https://bugs.ruby-lang.org/issues/15116" class="external">https://bugs.ruby-lang.org/issues/15116</a></p>
<p>However as a "not important" issues, around 1000 issues were detected by the tool for the ruby 2.5.1.<br>
I am considering how to deal with this or report those.<br>
I might open an another ticket for that.</p>
</blockquote>
<p>However there are around 1000 "not important" issues.</p>
<p>Right now I do not share the report file (840KByte) for that, because it makes people tired.<br>
If someone want to see it, I am happy to share it here as an attachment.</p>
<p>Instead of that, It looks good to me that someone could see the result of coverity scan casually anytime to fix those in long term.</p>
<p>What I want to propose is to add coverity scan test on rubyci or Travis CI.</p>
<p>I do not know how coverity scan is used on current Ruby project as a regular workflow.<br>
But I could see it is actually used from the setting [2] and some tickets. [3]</p>
<p>I found how to use Coverity Scan on Travis CI [4], and the used cases [5][6].</p>
<p>How do you think?</p>
<ul>
<li>[1] rubyci: <a href="https://www.rubyci.org/" class="external">https://www.rubyci.org/</a>
</li>
<li>[2] coverity scan ruby project: <a href="https://scan.coverity.com/projects/ruby" class="external">https://scan.coverity.com/projects/ruby</a>
</li>
<li>[3] coverity scan used tickets:
<ul>
<li><a href="https://bugs.ruby-lang.org/projects/ruby-trunk/repository/revisions/61862" class="external">https://bugs.ruby-lang.org/projects/ruby-trunk/repository/revisions/61862</a></li>
<li><a href="https://bugs.ruby-lang.org/projects/ruby-trunk/repository/revisions/55763" class="external">https://bugs.ruby-lang.org/projects/ruby-trunk/repository/revisions/55763</a></li>
<li><a href="https://bugs.ruby-lang.org/projects/ruby-trunk/repository/revisions/50734" class="external">https://bugs.ruby-lang.org/projects/ruby-trunk/repository/revisions/50734</a></li>
</ul>
</li>
<li>[4] How to use Coverity Scan on Travis CI: <a href="https://scan.coverity.com/travis_ci" class="external">https://scan.coverity.com/travis_ci</a>
</li>
<li>[5] The cases for coverity scan on Travis CI:
<ul>
<li><a href="https://github.com/nanoporetech/scrappie/blob/master/.travis.yml" class="external">https://github.com/nanoporetech/scrappie/blob/master/.travis.yml</a></li>
<li><a href="https://github.com/JanusGraph/janusgraph/blob/master/.travis.yml" class="external">https://github.com/JanusGraph/janusgraph/blob/master/.travis.yml</a></li>
</ul>
</li>
</ul> Ruby master - Misc #15136 (Open): Fix -Wparentheses warningshttps://bugs.ruby-lang.org/issues/151362018-09-18T14:43:35Zjaruga (Jun Aruga)
<p>Currently the <code>-Wno-parentheses</code> was set.<br>
I assumed if we could fix the warning, we could remove the <code>-Wno-parentheses</code>.</p>
<p>I fixed the warnings, because the warning is used as a default on Fedora Project build environment.<br>
I sent pull-request. <a href="https://github.com/ruby/ruby/pull/1958" class="external">https://github.com/ruby/ruby/pull/1958</a></p>
<p>I would show you the explanation of <code>-Wparentheses</code>.</p>
<pre><code>$ man gcc (or gcc --help --verbose)
...
-Wparentheses
Warn if parentheses are omitted in certain contexts, such as when there is an
assignment in a context where a truth value is expected, or when operators are
nested whose precedence people often get confused about.
Also warn if a comparison like "x<=y<=z" appears; this is equivalent to "(x<=y ?
1 : 0) <= z", which is a different interpretation from that of ordinary
mathematical notation.
Also warn for dangerous uses of the GNU extension to "?:" with omitted middle
operand. When the condition in the "?": operator is a boolean expression, the
omitted value is always 1. Often programmers expect it to be a value computed
inside the conditional expression instead.
For C++ this also warns for some cases of unnecessary parentheses in
declarations, which can indicate an attempt at a function call instead of a
declaration:
{
// Declares a local variable called mymutex.
std::unique_lock<std::mutex> (mymutex);
// User meant std::unique_lock<std::mutex> lock (mymutex);
}
This warning is enabled by -Wall.
...
</code></pre> Ruby master - Misc #15007 (Open): Let all Init_xxx and extension APIs frequently called from init...https://bugs.ruby-lang.org/issues/150072018-08-18T23:17:31Zmethodmissing (Lourens Naudé)lourens@bearmetal.eu
<p>References Github PR <a href="https://github.com/ruby/ruby/pull/1934" class="external">https://github.com/ruby/ruby/pull/1934</a></p>
<a name="Why"></a>
<h3 >Why?<a href="#Why" class="wiki-anchor">¶</a></h3>
<p>An incremental extraction from PR <a href="https://github.com/ruby/ruby/pull/1922" class="external">https://github.com/ruby/ruby/pull/1922</a>, specifically addressing the feedback from Yui Naruse in <a href="https://github.com/ruby/ruby/pull/1922#issuecomment-413796710" class="external">https://github.com/ruby/ruby/pull/1922#issuecomment-413796710</a></p>
<p>The <a href="https://github.com/torvalds/linux/blob/ca04b3cca11acbaf904f707f2d9ca9654d7cc226/include/linux/compiler-gcc.h#L191-L206" class="external">Linux kernel</a>, <a href="https://github.com/php/php-src/blob/2d71a28954a4f20709718ee7cb2b850d334c561c/Zend/zend_portability.h#L220" class="external">PHP 7</a> and other projects use the <code>hot</code> and <code>cold</code> function attributes to help with better code layout.</p>
<p>I noticed Ruby is very much CPU frontend bound (not feeding instructions into the CPU pipelines as fast as it maybe could) and therefore even most micro benchmarks have a high CPI (cycles per instruction) rate. This PR is part of a larger chunk of work I'd like to do around improving CPU frontend throughput and can take a stab at formally writing up those ideas if there's any interest from the community. I don't know.</p>
<a name="Implementation"></a>
<h3 >Implementation<a href="#Implementation" class="wiki-anchor">¶</a></h3>
<p>This PR has an exclusive focus on having the <code>Init_xxx</code> functions for the core classes and those bundled in <code>ext</code> being flagged to be optimized for size as they're called only once at runtime.</p>
<p>The GCC specific <a href="https://gcc.gnu.org/onlinedocs/gcc-4.6.4/gcc/Function-Attributes.html" class="external">cold</a> function attribute works in the following way (from GCC docs):</p>
<pre><code>The cold attribute is used to inform the compiler that a function is unlikely executed. The function is optimized for size rather than speed and on many targets it is placed into special subsection of the text section so all cold functions appears close together improving code locality of non-cold parts of program. The paths leading to call of cold functions within code are marked as unlikely by the branch prediction mechanism. It is thus useful to mark functions used to handle unlikely conditions, such as perror, as cold to improve optimization of hot functions that do call marked functions in rare occasions.
When profile feedback is available, via -fprofile-use, hot functions are automatically detected and this attribute is ignored.
</code></pre>
<p>By declaring a function as <code>cold</code> when defined we get the following benefits:</p>
<ul>
<li>No-op on platforms that does not support the attribute</li>
<li>Size optimization of cold functions with a smaller footprint in the instruction cache</li>
<li>Therefore CPU frontend throughput increases due to a lower ratio of instruction cache misses and a lower ITLB overhead - see <a href="https://user-images.githubusercontent.com/379/44204858-4c085100-a14c-11e8-86b8-d87fcb5e4985.png" class="external">original chunky PR</a> VS <a href="https://user-images.githubusercontent.com/379/44204870-4f9bd800-a14c-11e8-9bee-14c8ad8d3a7d.png" class="external">then trunk</a>
</li>
<li>This effect can further be amplified in future work with the <code>hot</code> attribute</li>
</ul>
<a name="Extension-APIs-flagged-as-cold"></a>
<h4 >Extension APIs flagged as cold<a href="#Extension-APIs-flagged-as-cold" class="wiki-anchor">¶</a></h4>
<p>These are and should typically only be called on extension init, and thus safe to optimize for size as well.</p>
<ul>
<li><code>void rb_define_method_id(VALUE, ID, VALUE (*)(ANYARGS), int));</code></li>
<li><code>void rb_undef(VALUE, ID));</code></li>
<li><code>void rb_define_protected_method(VALUE, const char*, VALUE (*)(ANYARGS), int));</code></li>
<li><code>void rb_define_private_method(VALUE, const char*, VALUE (*)(ANYARGS), int));</code></li>
<li><code>void rb_define_singleton_method(VALUE, const char*, VALUE(*)(ANYARGS), int));</code></li>
<li><code>void rb_define_alloc_func(VALUE, rb_alloc_func_t));</code></li>
<li><code>void rb_undef_alloc_func(VALUE));</code></li>
<li><code>VALUE rb_define_class(const char*,VALUE));</code></li>
<li><code>VALUE rb_define_module(const char*));</code></li>
<li><code>VALUE rb_define_class_under(VALUE, const char*, VALUE));</code></li>
<li><code>VALUE rb_define_module_under(VALUE, const char*));</code></li>
<li><code>void rb_define_variable(const char*,VALUE*));</code></li>
<li><code>void rb_define_virtual_variable(const char*,VALUE(*)(ANYARGS),void(*)(ANYARGS)));</code></li>
<li><code>void rb_define_hooked_variable(const char*,VALUE*,VALUE(*)(ANYARGS),void(*)(ANYARGS)));</code></li>
<li><code>void rb_define_readonly_variable(const char*,const VALUE*));</code></li>
<li><code>void rb_define_const(VALUE,const char*,VALUE));</code></li>
<li><code>void rb_define_global_const(const char*,VALUE));</code></li>
<li><code>void rb_define_method(VALUE,const char*,VALUE(*)(ANYARGS),int));</code></li>
<li><code>(void rb_define_module_function(VALUE,const char*,VALUE(*)(ANYARGS),int));</code></li>
<li><code>void rb_define_global_function(const char*,VALUE(*)(ANYARGS),int));</code></li>
<li><code>void rb_undef_method(VALUE,const char*));</code></li>
<li><code>void rb_define_alias(VALUE,const char*,const char*));</code></li>
<li><code>void rb_define_attr(VALUE,const char*,int,int));</code></li>
<li><code>void rb_global_variable(VALUE*));</code></li>
<li><code>void rb_gc_register_mark_object(VALUE));</code></li>
<li><code>void rb_gc_register_address(VALUE*));</code></li>
<li><code>void rb_gc_unregister_address(VALUE*));</code></li>
</ul>
<a name="Text-segment-reductions"></a>
<h4 >Text segment reductions<a href="#Text-segment-reductions" class="wiki-anchor">¶</a></h4>
<p>Small changes (<code>3144</code> bytes reduction of the text segment) because this is incremental groundwork and and initial low risk PR.</p>
<p>this branch:</p>
<pre><code>lourens@CarbonX1:~/src/ruby/ruby$ size ruby
text data bss dec hex filename
3462153 21056 71344 3554553 363cf9 ruby
</code></pre>
<p>trunk:</p>
<pre><code>lourens@CarbonX1:~/src/ruby/trunk$ size ruby
text data bss dec hex filename
3465297 21056 71344 3557697 364941 ruby
</code></pre>
<p>Diffs for individual object files: <a href="https://www.diffchecker.com/T0GVzX1q" class="external">https://www.diffchecker.com/T0GVzX1q</a></p>
<p>Default <code>text.unlikely</code> section where init functions are moved to:</p>
<pre><code>lourens@CarbonX1:~/src/ruby/ruby$ readelf -S vm.o
There are 34 section headers, starting at offset 0x2a04f8:
Section Headers:
[Nr] Name Type Address Offset
Size EntSize Flags Link Info Align
[ 0] NULL 0000000000000000 00000000
0000000000000000 0000000000000000 0 0 0
[ 1] .text PROGBITS 0000000000000000 00000040
000000000001c37f 0000000000000000 AX 0 0 16
[ 2] .rela.text RELA 0000000000000000 00114100
000000000000a7d0 0000000000000018 I 31 1 8
[ 3] .data PROGBITS 0000000000000000 0001c3c0
0000000000000030 0000000000000000 WA 0 0 16
[ 4] .bss NOBITS 0000000000000000 0001c400
00000000000002b0 0000000000000000 WA 0 0 32
[ 5] .rodata.str1.8 PROGBITS 0000000000000000 0001c400
0000000000000d6f 0000000000000001 AMS 0 0 8
[ 6] .text.unlikely PROGBITS 0000000000000000 0001d16f <<<<<<<<<<<<<<<
0000000000001aa9 0000000000000000 AX 0 0 1
</code></pre>
<p>The relocations for <code>vm.o</code>:</p>
<pre><code>lourens@CarbonX1:~/src/ruby/ruby$ ld -M vm.o
--- truncated ---
.text 0x0000000000400120 0x1de2f
*(.text.unlikely .text.*_unlikely .text.unlikely.*)
.text.unlikely
0x0000000000400120 0x1aa9 vm.o
0x000000000040038f rb_define_alloc_func
0x00000000004003bf rb_undef_alloc_func
0x00000000004003c5 Init_Method
0x0000000000400512 Init_vm_eval
0x00000000004007a1 Init_eval_method
0x0000000000400a54 rb_undef
0x0000000000400c1d Init_VM
0x000000000040185f Init_BareVM
0x0000000000401b16 Init_vm_objects
0x0000000000401b61 Init_top_self
*(.text.exit .text.exit.*)
*(.text.startup .text.startup.*)
*(.text.hot .text.hot.*)
*(.text .stub .text.* .gnu.linkonce.t.*)
*fill* 0x0000000000401bc9 0x7
.text 0x0000000000401bd0 0x1c37f vm.o
0x00000000004022f0 rb_f_notimplement
0x0000000000404780 rb_vm_ep_local_ep
0x00000000004047b0 rb_vm_frame_block_handler
0x00000000004047e0 rb_vm_cref_new_toplevel
0x0000000000404870 rb_vm_block_ep_update
0x0000000000404890 ruby_vm_special_exception_copy
0x0000000000406960 rb_ec_stack_overflow
0x00000000004069c0 rb_vm_push_frame
0x0000000000406b20 rb_vm_pop_frame
0x0000000000406b30 rb_error_arity
0x0000000000407180 rb_vm_frame_method_entry
0x00000000004075e0 rb_vm_rewrite_cref
0x00000000004076f0 rb_simple_iseq_p
0x0000000000407700 rb_vm_opt_struct_aref
0x0000000000407730 rb_vm_opt_struct_aset
0x0000000000407750 rb_clear_constant_cache
--- truncated ---
</code></pre>
<p>I also dabbled with the idea of an <code>INITFUNC</code> macro that also places the <code>Init_xxx</code> functions into a <code>text.init</code> section as the <a href="https://linuxgazette.net/157/amurray.html" class="external">kernel does</a> for a possible future optimization of stripping out ELF sections for setup / init specific functions. I don't think that makes sense for now and possibly only interesting for mruby or embedded.</p>
<a name="Possible-next-units-of-work"></a>
<h3 >Possible next units of work<a href="#Possible-next-units-of-work" class="wiki-anchor">¶</a></h3>
<a name="Cold-code-specific"></a>
<h4 >Cold code specific<a href="#Cold-code-specific" class="wiki-anchor">¶</a></h4>
<ul>
<li>Incrementally PR corner case error handling functions such as <code>rb_bug</code> from <a href="https://github.com/ruby/ruby/pull/1922" class="external">https://github.com/ruby/ruby/pull/1922</a>
</li>
<li>Ditto for generic error handling functions (<code>rb_raise</code> and friends) from <a href="https://github.com/ruby/ruby/pull/1922" class="external">https://github.com/ruby/ruby/pull/1922</a>
</li>
<li>Class specific error handling functions (load errors, encoding errors in the IO module, sys errors etc.) from <a href="https://github.com/ruby/ruby/pull/1922" class="external">https://github.com/ruby/ruby/pull/1922</a>
</li>
<li>GCC 5+ also supports <code>cold</code> <a href="https://gcc.gnu.org/onlinedocs/gcc/Label-Attributes.html" class="external">labels</a> , which I took a stab with in the bloated <a href="https://github.com/ruby/ruby/pull/1922" class="external">https://github.com/ruby/ruby/pull/1922</a>
</li>
</ul>
<a name="TLB-translation-lookaside-buffer-specific"></a>
<h4 >TLB (translation lookaside buffer) specific<a href="#TLB-translation-lookaside-buffer-specific" class="wiki-anchor">¶</a></h4>
<ul>
<li>Further ITLB overhead investigation</li>
<li>Ruby binaries built with O3 and debug symbols come in at just short of 18MB, or roughly 9 hugepages on linux. PHP core developers were able to squeeze a few % by remapping code to hugepages on supported systems - <a href="http://developers-club.com/posts/270685/" class="external">http://developers-club.com/posts/270685/</a> . Implementation <a href="https://github.com/php/php-src/blob/fb0389b1010de5a6459bcf286409423f69e74aaf/ext/opcache/ZendAccelerator.c#L2645-L2750" class="external">here</a>
</li>
</ul>
<a name="Bytecode-specific"></a>
<h4 >Bytecode specific<a href="#Bytecode-specific" class="wiki-anchor">¶</a></h4>
<ul>
<li>The <a href="https://software.intel.com/en-us/vtune-amplifier-help-task-api" class="external">Intel Tracing Task API</a> is very well suited for the instruction sequences YARV generates and to infer better per instruction CPU utilization and identify any stalls (frontend, backend, branches etc.) to drive further work.</li>
</ul> Ruby master - Misc #14825 (Open): When redefining `attr_xx` methods the visibility becomes `public` https://bugs.ruby-lang.org/issues/148252018-06-05T05:57:56Zy-yagi (Yuji Yaginuma)
<p>Hi.</p>
<p>If redefine <code>attr_xx</code> methods, the original visibility is lost and all visibility is public.</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="c1"># attr.rb</span>
<span class="k">module</span> <span class="nn">ClassMethods</span>
<span class="k">def</span> <span class="nf">attr_reader</span><span class="p">(</span><span class="o">*</span><span class="p">)</span>
<span class="k">super</span>
<span class="k">end</span>
<span class="k">def</span> <span class="nf">attr_writer</span><span class="p">(</span><span class="o">*</span><span class="p">)</span>
<span class="k">super</span>
<span class="k">end</span>
<span class="k">def</span> <span class="nf">attr_accessor</span><span class="p">(</span><span class="o">*</span><span class="p">)</span>
<span class="k">super</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="k">class</span> <span class="nc">Foo</span>
<span class="kp">extend</span> <span class="no">ClassMethods</span>
<span class="k">class</span> <span class="o"><<</span> <span class="nb">self</span>
<span class="k">def</span> <span class="nf">method_visibility</span><span class="p">(</span><span class="nb">method</span><span class="p">)</span>
<span class="k">case</span>
<span class="k">when</span> <span class="nb">private_method_defined?</span><span class="p">(</span><span class="nb">method</span><span class="p">)</span>
<span class="ss">:private</span>
<span class="k">when</span> <span class="nb">protected_method_defined?</span><span class="p">(</span><span class="nb">method</span><span class="p">)</span>
<span class="ss">:protected</span>
<span class="k">else</span>
<span class="ss">:public</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="nb">attr_reader</span> <span class="ss">:pub</span>
<span class="kp">protected</span>
<span class="nb">attr_reader</span> <span class="ss">:prot</span>
<span class="k">alias</span> <span class="n">protalias</span> <span class="n">prot</span>
<span class="kp">alias_method</span> <span class="ss">:protaliasmethod</span><span class="p">,</span> <span class="ss">:prot</span>
<span class="kp">private</span>
<span class="nb">attr_reader</span> <span class="ss">:priv</span>
<span class="k">alias</span> <span class="n">privalias</span> <span class="n">priv</span>
<span class="kp">alias_method</span> <span class="ss">:privaliasmethod</span><span class="p">,</span> <span class="ss">:priv</span>
<span class="k">end</span>
<span class="n">f</span> <span class="o">=</span> <span class="no">Foo</span><span class="p">.</span><span class="nf">new</span>
<span class="nb">puts</span> <span class="s2">"Public"</span>
<span class="n">f</span><span class="p">.</span><span class="nf">pub</span>
<span class="nb">puts</span>
<span class="nb">puts</span> <span class="s2">"Protected"</span>
<span class="nb">puts</span> <span class="s2">"prot: </span><span class="si">#{</span><span class="no">Foo</span><span class="p">.</span><span class="nf">method_visibility</span><span class="p">(</span><span class="ss">:prot</span><span class="p">)</span><span class="si">}</span><span class="s2">"</span>
<span class="nb">puts</span> <span class="s2">"protalias: </span><span class="si">#{</span><span class="no">Foo</span><span class="p">.</span><span class="nf">method_visibility</span><span class="p">(</span><span class="ss">:protalias</span><span class="p">)</span><span class="si">}</span><span class="s2">"</span>
<span class="nb">puts</span> <span class="s2">"protaliasmethod </span><span class="si">#{</span><span class="no">Foo</span><span class="p">.</span><span class="nf">method_visibility</span><span class="p">(</span><span class="ss">:protaliasmethod</span><span class="p">)</span><span class="si">}</span><span class="s2">"</span>
<span class="nb">puts</span>
<span class="nb">puts</span> <span class="s2">"Private"</span>
<span class="nb">puts</span> <span class="s2">"priv: </span><span class="si">#{</span><span class="no">Foo</span><span class="p">.</span><span class="nf">method_visibility</span><span class="p">(</span><span class="ss">:priv</span><span class="p">)</span><span class="si">}</span><span class="s2">"</span>
<span class="nb">puts</span> <span class="s2">"privalias: </span><span class="si">#{</span><span class="no">Foo</span><span class="p">.</span><span class="nf">method_visibility</span><span class="p">(</span><span class="ss">:privalias</span><span class="p">)</span><span class="si">}</span><span class="s2">"</span>
<span class="nb">puts</span> <span class="s2">"privaliasmethod: </span><span class="si">#{</span><span class="no">Foo</span><span class="p">.</span><span class="nf">method_visibility</span><span class="p">(</span><span class="ss">:privaliasmethod</span><span class="p">)</span><span class="si">}</span><span class="s2">"</span>
</code></pre>
<pre><code>$ ruby -v attr.rb
ruby 2.5.1p57 (2018-03-29 revision 63029) [x86_64-linux]
Public
Protected
prot: public
protalias: public
protaliasmethod public
Private
priv: public
privalias: public
privaliasmethod: public
</code></pre>
<p>Is this intentional?</p> Ruby master - Misc #14770 (Open): [META] DevelopersMeetinghttps://bugs.ruby-lang.org/issues/147702018-05-17T12:28:50Znaruse (Yui NARUSE)naruse@airemix.jp
<p>A meta ticket to organize DevelopersMeeting tickets.<br>
<a href="https://bugs.ruby-lang.org/projects/ruby/wiki#Developer-Meetings" class="external">https://bugs.ruby-lang.org/projects/ruby/wiki#Developer-Meetings</a></p> Ruby master - Misc #14768 (Open): Add documentation for || and &&https://bugs.ruby-lang.org/issues/147682018-05-17T08:41:39Zsos4nt (Stefan Schüßler)mail@stefanschuessler.de
<p>The Ruby documentation doesn't seem to cover <code>||</code> and <code>&&</code>.</p>
<p>The only references I could find are:</p>
<p><a href="http://ruby-doc.org/core-2.5.1/doc/keywords_rdoc.html" class="external">http://ruby-doc.org/core-2.5.1/doc/keywords_rdoc.html</a></p>
<blockquote>
<p><strong>and</strong> – Short-circuit Boolean and with lower precedence than <code>&&</code><br>
<strong>or</strong> – Short-circuit Boolean and with lower precedence than <code>||</code></p>
</blockquote>
<p><a href="http://ruby-doc.org/core-2.5.1/doc/syntax/assignment_rdoc.html" class="external">http://ruby-doc.org/core-2.5.1/doc/syntax/assignment_rdoc.html</a></p>
<blockquote>
<p>There are also <code>||=</code> and <code>&&=</code>. The former makes an assignment if ...</p>
</blockquote>
<p>But there's no documentation for the operators themselves.</p> Ruby master - Misc #14760 (Open): cross-thread IO#close semanticshttps://bugs.ruby-lang.org/issues/147602018-05-15T10:04:52Znormalperson (Eric Wong)normalperson@yhbt.net
<p>I wrote about cross-thread IO#close in ruby-core, but I'm not sure if it's a bug<br>
or not to have missing support for IO.select and IO.copy_stream:</p>
<p>IO.select -<br>
<a href="http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-core/86655" class="external">http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-core/86655</a><br>
<a href="https://public-inbox.org/ruby-core/20180423133946.GA6019@dcvr/" class="external">https://public-inbox.org/ruby-core/20180423133946.GA6019@dcvr/</a></p>
<p>IO.copy_stream -<br>
<a href="http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-core/87040" class="external">http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-core/87040</a><br>
<a href="https://public-inbox.org/ruby-core/20180515095315.GA15909@dcvr/" class="external">https://public-inbox.org/ruby-core/20180515095315.GA15909@dcvr/</a></p>
<p>I know the IO.select case in 1.9+ differs from 1.8, and IO.copy_stream wasn't in<br>
1.8, but I guess the current behavior is that it isn't consistent with normal IO<br>
methods. IO.copy_stream will also behave "normally" and raise IOError if it<br>
somehow hits non-optimized cases and ends up calling Ruby methods, but my<br>
example in <a href="https://blade.ruby-lang.org/ruby-core/87040">[ruby-core:87040]</a> did not hit that case.</p>
<p>On one hand, I'm not a fan of "nanny features" like deadlock detection for<br>
threading. On the other hand, I value consistency and we already went down the<br>
rabbit hole of supporting current users of rb_thread_io_blocking_region.</p>
<p>Anyways, I can implement these if desired since I have additional work planned<br>
in this area anyways (auto-fiber).</p> Ruby master - Misc #14735 (Open): thread-safe operations in a hash could be documentedhttps://bugs.ruby-lang.org/issues/147352018-05-03T18:55:46Zrosenfeld (Rodrigo Rosenfeld Rosas)rr.rosas@gmail.com
<p>Hi, sometimes I find myself fetching data from the database through multiple queries concurrently. For example, suppose the application support multiple data-types which are independent from each other and we need to perform a set of operations per data-type. Usually I'd run one method for extracting the related data per data-type and would run them concurrently. Something like this:</p>
<pre><code>require 'thread'
result = {} # assume this is thread-safe in MRI for now
data_types.map do |data_type, processor|
Thread.start{ result[data_type] = processor.call }
end.each &:join
</code></pre>
<p>This code is quite simple and seems to always work with MRI. A more explicit equivalent code that should also work on other Ruby implementations without GIL would be probably written like:</p>
<pre><code>require 'thread'
result = {}
result_semaphore = Mutex.new
data_types.map do |data_type, processor|
Thread.start do
result_for_data_type = processor.call # expensive call
result_semaphore.synchronize{ result[data_type] = result_for_data_type }
end
end.each &:join
</code></pre>
<p>As you can see, it's much more code than the previous one. As I said initially, I use such pattern every now and then, so I'd love to be able to write the first code and being confident that it would always work as expected in MRI.</p>
<p>I've tried the following in order to see if I could cause an thread-unsafe case with MRI but it always return "[ 100000, 100000, nil ]":</p>
<pre><code>require 'thread'
h = {}
(1..100000).map do |i|
Thread.start{ h[i] = i }
end.each &:join
p h.keys.uniq.size, h.values.uniq.size, h.find{|k, v| k != v }
</code></pre>
<p>Is it just by chance? Or may I assume that will always be the case. Maybe it would be interesting to document somewhere what could be assumed to be true regarding thread-safeness for many methods. For example, there could be some link in the Hash documentation such as: "If you'd like to understand how each method behave in a multi-thread environment read this document" and point to another page explaining how it works.</p>
<p>By the way, the 'concurrent' gem seems to assume Hash is thread-safe in MRI as you can see here:</p>
<p><a href="https://github.com/ruby-concurrency/concurrent-ruby/blob/master/lib/concurrent/hash.rb#L5-L16" class="external">https://github.com/ruby-concurrency/concurrent-ruby/blob/master/lib/concurrent/hash.rb#L5-L16</a></p>
<pre><code>module Concurrent
if Concurrent.on_cruby?
class Hash < ::Hash;
end
#...
end
end
</code></pre>
<p>Is this officially documented somewhere?</p> Ruby master - Misc #14692 (Open): Question: Ruby stdlib's Option Parserhttps://bugs.ruby-lang.org/issues/146922018-04-17T16:30:09Zxz0r (xz0r xz0r)
<p>Hi,</p>
<p>The documentation of OptionParser says for further I can ask questions here.</p>
<p>Is there way to disable command/option completion ? I don't want a short "-f" option defined automatically if I declare "--file-name" , I have searched the internet and couldn't find a solution.</p> Ruby master - Misc #14673 (Open): Documentation for `Array#drop` / `drop_while` unclear in regard...https://bugs.ruby-lang.org/issues/146732018-04-10T09:51:49Zsos4nt (Stefan Schüßler)mail@stefanschuessler.de
<p>The documentation for <a href="http://ruby-doc.org/core-2.5.0/Array.html#method-i-drop" class="external"><code>Array#drop</code></a> says:</p>
<blockquote>
<p>Drops first <code>n</code> elements from <code>ary</code> and returns the rest of the elements in an array.</p>
</blockquote>
<p>It's unclear if the receiver is being changed or not (it is not). The documentation should be more explicit in that regard.</p>
<p>Maybe something like <em>"Returns a new array containing all except the first <code>n</code> elements from <code>ary</code>"</em>.</p>
<p>This also applies to <code>Array#drop_while</code>.</p> Ruby master - Misc #14190 (Open): What are the semantics of $SAFE?https://bugs.ruby-lang.org/issues/141902017-12-15T16:29:10ZEregon (Benoit Daloze)
<p>$SAFE is documented in many places as thread-local, but it seems more than that.<br>
For example:</p>
<pre><code># a.rb
$SAFE=1
p $SAFE
require "#{Dir.pwd.untaint}/b.rb"
# b.rb
p [:in_b, $SAFE]
</code></pre>
<p>gives:</p>
<pre><code>$ ruby -r./a -e 'p $SAFE'
1
[:in_b, 0]
0
</code></pre>
<p>So in b and in -e, $SAFE is 0.<br>
Is it file-based somehow?</p>
<p>I was trying to understand what<br>
<a href="https://github.com/ruby/ruby/blob/7c4306e6e9c3c4a255f4ad20134c1832dbe45ba2/test/rubygems/test_gem.rb#L9-L13" class="external">https://github.com/ruby/ruby/blob/7c4306e6e9c3c4a255f4ad20134c1832dbe45ba2/test/rubygems/test_gem.rb#L9-L13</a><br>
is supposed to do.<br>
Does it make sense? What does it do?<br>
It seems the test_* methods in that file actually read $SAFE as 0, not 1.</p> Ruby master - Misc #14149 (Open): Ruby Birthday Thread - 25th years anniversaryhttps://bugs.ruby-lang.org/issues/141492017-12-02T01:07:30Zshevegen (Robert A. Heiler)shevegen@gmail.com
<p>Hello Ruby-people in general,</p>
<p>Matz recently gave a keynote presentation and he mentioned that ruby's birthday will be<br>
in 2018 (25 years; I think matz mentioned that he counts when the name was chosen but<br>
ruby itself may have already been existing before that in one way or another perhaps).</p>
<p>I suggest that in this thread here, people can give feedback, give ideas, chat about<br>
things ... the party will be in Japan though, so not everyone can participate. :D</p>
<p>However had, as this here can be a thread where people can "virtually" add/contribute<br>
anything, I thought that it may be a good idea to start a thread here.</p>
<p>In order to not have this thread be active for too long, I suggest that it should<br>
be closed some time in 2018, after the ruby birthday party. :D</p>
<p>(I think the official birthday will be around February 2018, so I suggest that<br>
this thread should perhaps "fade out" some time in June or July 2018 or so?<br>
Something like that perhaps, but do feel free to ignore this too when appropriate,<br>
it is just a suggestion.)</p>
<p>I'll start with some feedback next from my point of view, but this thread should be<br>
general, not "just" my opinion. People really should give feedback, matz said so<br>
specifically in the keynote presentation.</p> Ruby master - Misc #14037 (Open): Writing doxygen document comments to static functionshttps://bugs.ruby-lang.org/issues/140372017-10-21T07:46:19Zsonots (Naotoshi Seo)sonots@gmail.com
<p>I often feel that C API documents are lacked in C source codes, especially for <code>static</code> functions.</p>
<p>With <a href="https://bugs.ruby-lang.org/issues/904" class="external">https://bugs.ruby-lang.org/issues/904</a>, <code>make install-capi</code> target was introduced to generate c api documents using Doxygen.<br>
However, I feel that it is not utilized among C Ruby developers.</p>
<p>I propose to turn <code>EXTRACT_STATIC = YES</code> flag of Doxygen to YES, and write document comments for static functions as much as possible.</p> Ruby master - Misc #13968 (Open): [Ruby 3.x perhaps] - A (minimal?) static variant of rubyhttps://bugs.ruby-lang.org/issues/139682017-10-03T20:42:16Zshevegen (Robert A. Heiler)shevegen@gmail.com
<p>Hello ruby core team and everyone else,</p>
<p>I think this has been brought up before, in one way or the other, but<br>
just in case it was not, or not in this context, I would like to <strong>propose<br>
that ruby can be compiled statically</strong>.</p>
<p>Matz explained how this can be done for mruby:</p>
<p><a href="https://github.com/mruby/mruby/issues/3707" class="external">https://github.com/mruby/mruby/issues/3707</a></p>
<p>This is not so difficult; allow me to copy/paste the major<br>
steps for mruby (I modified it a bit):</p>
<p>Option A:</p>
<pre><code>(1) compile your.rb files into a C file via mrbc. Example: "mrbc -Binit_yourlib -o mrblib.c *.rb"
(2) your code/application has to call "init_yourlib(mrb)" after "mrb_open()"
(3) compile your code/application with the generated C file
(4) link via "libmruby.a"
(5) static link options may have to be specified to the linker
</code></pre>
<p>Option B</p>
<pre><code>(1) Create a binary "mrbgem". See mrbgems/mruby-bin-mirb for example.
</code></pre>
<p>And nobu added better support for statically linked extensions some years<br>
ago:</p>
<p><a href="https://bugs.ruby-lang.org/issues/9018" class="external">https://bugs.ruby-lang.org/issues/9018</a></p>
<p>Since time is a limited resource by the ruby core team, I understand that<br>
you have to prioritize on issues that are more important, or needed more;<br>
and a statically compiled ruby may not be of highest priority. Additionally,<br>
you may want to know the use case of people, as to why they may want to<br>
have a statically compiled variant of ruby.</p>
<p>I have a (small) use case which I think has not been explained before.</p>
<p>I often break stuff on my linux system when I compile programs. I use many<br>
ruby helper scripts to compile programs, so I need ruby. :)</p>
<p>When I have a ruby available then I can often batch-compile, batch-install<br>
and so on. This works very well so far for most programs out there.</p>
<p>Not always is there a host system available with ruby though; sometimes<br>
I may be in a confined environment, such as workspaces at university<br>
and a central server cluster to which I have no access (or rather,<br>
permission to change files/directory). So I tend to compile into the<br>
user directory there (home directory).</p>
<p>Anyway. Since I tend to break stuff, but sometimes other stuff is also<br>
broken on such environments (looking at centos ...), I made it a habit<br>
to compile some of the core utilities in a static manner into my home<br>
directory; "make" for example or "sed". Both work very well. Others<br>
are a bit misbehaving or stubborn, such as awk - I haven't managed<br>
a statically compiled variant of awk yet.</p>
<p>Of course I also use "busybox," a statically compiled busybox that is.</p>
<p>This allows me to recover from many problems or errors if things go<br>
awry (I can also use a live-DVD for recovery, at the least at home;<br>
or also download some binaries that I know will work on the target<br>
platform, so I have more ways to recover).</p>
<p>Now the thing is - most of what I do with busybox, has to do with<br>
file manipulation of some sort; setting new symlinks, removing,<br>
moving, creating files or directories.</p>
<p>Here I thought - I could use ruby rather than busybox. :)</p>
<p>But I'd want or need a statically compiled ruby, so that it does not<br>
break depending on other programs there on the system.</p>
<p>I hope I could explain my use case. And I agree, only very few<br>
people may ever want to have this perhaps.</p>
<p>I looked at my self-compiled MRI ruby, via "ldd", and these are the<br>
libraries that ruby depends on:</p>
<pre><code> linux-vdso.so.1
libpthread.so.0 => /lib64/libpthread.so.0
libgmp.so.10 => /usr/lib/libgmp.so.10
libdl.so.2 => /lib64/libdl.so.2
libcrypt.so.1 => /lib64/libcrypt.so.1
libm.so.6 => /lib64/libm.so.6
libc.so.6 => /lib64/libc.so.6
/lib64/ld-linux-x86-64.so.2
</code></pre>
<p>I guess this is not minimal; I could probably re-compile ruby<br>
from a sandbox, to reduce the amount of .so objects that are<br>
needed, but the above is only an example anyway.</p>
<p>I assume that making available a ruby that can be statically compiled,<br>
is not trivial. It is probably easier for mruby, but mruby is, as far<br>
as I understand it, more aimed towards knowledgable C/C++ hackers. I<br>
am a bit too scared to try mruby when I do not really know C.</p>
<p>I should also state that I do not need a "full" ruby by the way. I can<br>
live without the extension stuff, such as "readline" or "openssl" probably<br>
(though I'd love to have open-uri since that may help in recovery; ruby's<br>
open() functionality for remote data/websites is great).</p>
<p>I guess the core functionality I would need is, mostly, file manipulation.</p>
<p>So perhaps my request could be titled:</p>
<p>"A minimal variant of ruby - that is statically linked."</p>
<p>Now this may fit to mruby perhaps but I am a bit scared of mruby also<br>
because I do not know mruby very well; I mostly work with MRI ruby. (I<br>
did manage to compile mruby without problem and I could run ruby code<br>
too but I am not sure how much is available on mruby by default "out<br>
of the box". If I remember correctly, not every MRI ruby .rb file<br>
will work "out of the box")</p>
<p>I also thought of filing an issue request at github-mruby but then I<br>
thought that perhaps it may also fit into MRI ruby one day, which is<br>
why I prepended with the ruby 3.x label. (I suppose that it may not<br>
fit towards 2.x anymore since 2.x will probably focus on stability,<br>
bug fixing and so forth.)</p>
<p>I hope I could explain my use case. I am not sure if it is a good<br>
use case; I can probably just keep on using busybox ... but I would<br>
prefer to actually work within a "ruby environment" in general,<br>
simply because ruby is a LOT nicer to work with, in particular for<br>
batch-automated tasks (I always prefer to use ruby rather than shell<br>
scripts, for example).</p>
<p>If possible it would be nice if this issue could remain open for a<br>
bit longer, if only to see if there is anyone else who may want to<br>
have some statically compiled variant of ruby.</p>
<p>I see this sometimes in other issue requests, or similar suggestions,<br>
so perhaps if there may be a seizable amount of people who may want<br>
it, it could be put on a "long-term goal". Perhaps even past 3.x.</p>
<p>Last but not least I would like to repeat that I do not need a full<br>
featured ruby per se, a minimal may suffice - but that minimal ruby<br>
should ideally be easy to use+install. It's a bit like a mix<br>
between "MRI ruby" and "mruby" what I want, I think. :D</p>
<p>That way, I could both have a MRI ruby that uses .so, but also e. g<br>
a binary called "static-ruby" or "ruby-static" or something like<br>
that, that can be used a bit like a "recovery ruby".</p>
<p>I wrote a lot so now it's time to close without much further ado -<br>
thank you for reading!</p> Ruby master - Misc #13804 (Open): Protected methods cannot be overriddenhttps://bugs.ruby-lang.org/issues/138042017-08-10T21:41:24Zdavidarnold (David Arnold)
<p>In Ruby, the main reason you would use protected instead of private is because you want different instances of the same class lineage to be able to access the method.</p>
<p>However, the rules around protected (callable only where self of the context is the same as the [...] method definition) means that protected method effectively cannot be overridden by subclasses. The redefinition of the method resets the protected access check to the subclass, so that instances of the parent class (or other subclasses) cannot call the method anymore.</p>
<p>Is the recommendation that using protected is just bad practice and should be avoided? Or is there a way to make the protected behavior aware of the parent method that is being overridden and keep the access check at the same level in the class hierarchy?</p>
<p>Example:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">class</span> <span class="nc">Person</span>
<span class="k">def</span> <span class="nf">initialize</span><span class="p">(</span><span class="n">ssn</span><span class="p">)</span>
<span class="vi">@ssn</span> <span class="o">=</span> <span class="n">ssn</span>
<span class="k">end</span>
<span class="k">def</span> <span class="nf">same?</span><span class="p">(</span><span class="n">other</span><span class="p">)</span>
<span class="n">tax_id</span> <span class="o">==</span> <span class="n">other</span><span class="p">.</span><span class="nf">tax_id</span>
<span class="k">end</span>
<span class="kp">protected</span>
<span class="k">def</span> <span class="nf">tax_id</span>
<span class="vi">@ssn</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="k">class</span> <span class="nc">HappyPerson</span> <span class="o"><</span> <span class="no">Person</span>
<span class="k">def</span> <span class="nf">shout</span>
<span class="s1">'yay!'</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="c1"># corporations are people now</span>
<span class="k">class</span> <span class="nc">Corporation</span> <span class="o"><</span> <span class="no">Person</span>
<span class="k">def</span> <span class="nf">initialize</span><span class="p">(</span><span class="n">ein</span><span class="p">)</span>
<span class="vi">@ein</span> <span class="o">=</span> <span class="n">ein</span>
<span class="k">end</span>
<span class="kp">protected</span>
<span class="k">def</span> <span class="nf">tax_id</span>
<span class="vi">@ein</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="n">bob</span> <span class="o">=</span> <span class="no">Person</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="s1">'000-00-0001'</span><span class="p">)</span>
<span class="n">sally</span> <span class="o">=</span> <span class="no">HappyPerson</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="s1">'000-00-0002'</span><span class="p">)</span>
<span class="n">acme</span> <span class="o">=</span> <span class="no">Corporation</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="s1">'00-0000001'</span><span class="p">)</span>
<span class="nb">puts</span> <span class="n">bob</span><span class="p">.</span><span class="nf">same?</span> <span class="n">bob</span> <span class="c1"># true</span>
<span class="nb">puts</span> <span class="n">bob</span><span class="p">.</span><span class="nf">same?</span> <span class="n">sally</span> <span class="c1"># false</span>
<span class="nb">puts</span> <span class="n">sally</span><span class="p">.</span><span class="nf">same?</span> <span class="n">bob</span> <span class="c1"># false</span>
<span class="nb">puts</span> <span class="n">acme</span><span class="p">.</span><span class="nf">same?</span> <span class="n">bob</span> <span class="c1"># false</span>
<span class="nb">puts</span> <span class="n">bob</span><span class="p">.</span><span class="nf">same?</span> <span class="n">acme</span> <span class="c1">#=> protected method `tax_id' called ... (NoMethodError)</span>
</code></pre> Ruby master - Misc #13787 (Open): The path to Ruby 3.x - would it be useful to have a separate th...https://bugs.ruby-lang.org/issues/137872017-08-07T21:09:14Zshevegen (Robert A. Heiler)shevegen@gmail.com
<p>Hello everyone but especially so the whole ruby-core team,</p>
<p>This is very long, so if you just want the short gist, please<br>
jump to the:</p>
<p>TL;DR line closer to the bottom.</p>
<p>Matz gave several presentations in the last ~3 years or so (and of course<br>
before that as well; but I am mostly focusing only on the 3 recent years,<br>
in particular because due to the path towards ruby 3.x).</p>
<p>I lately watched the presentation matz gave in Singapore and he made<br>
some references to things that will, quite likely, go into ruby 3.x,<br>
while he also said that there is a ton of work ahead - JIT compile<br>
strategies; the (optional, I guess) type system; better concurrency<br>
and so on and so forth. These are probably the big ideas - while this<br>
is nice, and I agree with comments such as "nobody minds if ruby gets<br>
faster" (everyone loves when things get done instantly rather than<br>
when you must wait), I myself am actually even more interested in<br>
smaller things. Even when they are incompatible with ruby 2.x, but<br>
I think that matz said that backwards-compatibility breaking changes<br>
may happen in ruby 3.x but not in ruby 2.x. Which is both good<br>
and bad - good because people do not have to rewrite stuff to<br>
run in ruby 2.x; bad if there are some habits or anything that<br>
isn't that great when writing software in ruby.</p>
<p>Sorry for my lengthy introduction so far - I wanted to explain the<br>
angle I am coming from here.</p>
<p>Now ...</p>
<p>I have wanted to make some smaller changes and suggestions towards<br>
ruby 3.x. And matz once said that the core team (and, well, matz,<br>
since he is the boss :D ) is open to ideas. In ruby 2.x, often the<br>
core team asks for use cases, which is fine - some proposals have<br>
not been thought through and others are purely theoretical; whereas<br>
others are also originating from some real use case. For ruby 3.x,<br>
it is obviously ... difficult to get a real use case out. :)</p>
<p>But one can actually try to make the argument about this or that<br>
in ruby 2.x not working very well, or being confusing.</p>
<p>For example, some days ago, I wanted to suggest a simplified<br>
API and usage for running external programs in ruby. We have<br>
system(), backticks, IO, popen, open3 ... and I do not know<br>
what else. All of which works slightly differently and it is,<br>
at the least to me, quite confusing sometimes. So I wanted<br>
to suggest a simplification... but I realized that this is<br>
not really a good topic for the ruby 2.x branch because I think<br>
that matz wants to retain compatibility, so such a proposal<br>
probably has not a big chance to be implemented. Perhaps for<br>
some minor changes, but I'd actually also suggest to get rid<br>
of some of the duplicate ways, while retaining flexibility<br>
still (so I'd say... system and backticks remain, and then<br>
perhaps only one or two more ways for more advanced use<br>
cases, via a simpler API than this strange ... open2 open3<br>
and what not...).</p>
<p>Anyway.</p>
<p>If you think this through then it probably does not fit much<br>
into "Features" for ruby 2.x because ruby 2.x will remain<br>
backwards compatible, I think.</p>
<p>But for ruby 3.x, it may it.</p>
<p>There are many more smaller ideas like this... for example, I'd<br>
like to see the warning/error situation be improved in ruby<br>
3.x in particular.</p>
<p>I'd also like case/when objects to become full objects and be<br>
passable/convertable ad-hoc into a hash or hash-like object,<br>
and re-used in different .rb files. (The workarounds I know<br>
about are usually to use a hash, with these aliases, but I<br>
found case/when menu to be so much more readable and nicer<br>
to use, especially as you can also use regexes).</p>
<p>And many more ideas like that!</p>
<p>But they all do not really fit into the "Bug" section, neither into<br>
the "Feature" subsection... they may fit somewhat into "Misc" but<br>
it's not a good category.</p>
<p>So, without any further explanation and further ado, here is the<br>
summary and proposal:</p>
<p>TL;DR - Would it be useful to have a separate thread here at the<br>
issue tracker, for discussions and issues and ideas related to<br>
ruby 3.x?</p>
<p>This can be kept primarily as an ideas section for the time being;<br>
at a later time, when ruby 3.x becomes the official ruby one day,<br>
the subsection can be closed and archived for, say, 3 years or so<br>
as read-only, before it would then be deleted (when ruby 3.x<br>
is eventually used more frequently than ruby 2.x, which I guess<br>
may take a few years ... there is a LOT of inertia in general,<br>
we can see this in perl, python etc..).</p>
<p>The reason why I think that this would be useful is because it<br>
could potentially foster some idea discussions. Getting early<br>
ideas in may be good, because ruby 3.x, while it is still<br>
quite far away I think (2020 or beyond?), getting ideas in early<br>
may help to see that they, or a variation, is considered for<br>
inclusion. Otherwise we then may have to wait for more years<br>
because ruby 3.x may be frozen and people would have to wait<br>
for ruby 4.x - this is the primary reason why I'd like to see<br>
a separate thread.</p>
<p>I can not say if this is useful or not to anyone else, and I<br>
can not say if this leads to more ideas or discussion for ruby<br>
3.x features (aside from the big ideas matz already mentioned<br>
several times before, such as better concurrency/guilds, JIT<br>
and speed improves in general or any optional type system -<br>
that's already quite a lot to work on, and all this in addition<br>
to mruby ... but I think ideas are not bad, even if it is not<br>
possible to implement several of them due to lack of time. When<br>
matz approves of an idea, who knows, perhaps someone else may<br>
see that the approved idea will be worked on).</p>
<p>Sorry for this lengthy note - feel free to close this at<br>
any moment in time, for any reason!</p> Ruby master - Misc #13634 (Open): NilClass is lying about respond_to?(:clone)https://bugs.ruby-lang.org/issues/136342017-06-06T08:12:46Zrovf (Ronald Fischer)ynnor@mm.st
<p>I put this under "Misc", because I'm not sure, whether this is a bug, a feature request, or maybe a deliberate (but for me obscure) decision in language design:</p>
<p>NilClass (and Fixnum) do not support clone. That's fine. However,</p>
<p>nil.respons_to?(:clone) returns true.</p>
<p>This means that we <em>can</em> ask nil to clone itself (we don't get a NoMethod error), it's just trying to do so throws an exception.</p>
<p>I stumbled over this problem when I had an collection of objects of different types, and wanted to apply :clone to some of them. My code went approximately like this:</p>
<p>object = collection[key]<br>
return object.respond_to?(:clone) ? object.clone : object</p>
<p>This doesn't work, if object is nil, true, false, a Symbol or a Fixnum, because all of them claim to respond to :clone.</p>
<p>Of course, there is a trivial workaround (I just have to rescue the exception), but I find this language design not really intuitive. I think there are two possibilites, how this can be made better:</p>
<p>(1) If we decide, that nil is not clonable (because there can be only one nil), then respond_to?(:clone) should IMHO simply be false.</p>
<p>(2) However, there might be even be a reason why :clone should be applicable. Note that the usual semantics of clone is to do a shallow copy (for instance, when we 'clone' a nested array). If we want to have a deep copy, the usual approach is Marshal.load(Marshal.dump(object)). Now the odd thing is that we can not "shallowly copy" nil, i.e. nil.clone is forbidden, but we can do a deep copy, i.e. Marshal.load(Marshal.dump(nil)) works. So, an alternative would be to have nil.clone simply return the identical object.</p>
<p>Both (1) seems to me a sound solution. The solution (2) has the drawback that we can't guarantee anymore that x.clone has a different object id than x, but is probably the behaviour a programmer would intuitively expect.</p> Ruby master - Misc #13497 (Open): Docs, code samples, Ripper examplehttps://bugs.ruby-lang.org/issues/134972017-04-23T04:27:52ZMSP-Greg (Greg L)
<p>I think it's fair to say that virtually all Ruby documentation today is created by doc generation systems based either on YARD or RDoc. Code samples/examples are common. YARD uses Ripper to parse samples for highlighting, I believe RDoc uses its own parser.</p>
<p>Although I recall previous RDoc parsers to be flexible as to code highlighting, but some seem to be similar to Ripper. Hence, if it can't be pasted into an .rb file and run, it won't highlight.</p>
<p>With many samples, this isn't an issue, but with samples that display multi-line output, there are two options -</p>
<ol>
<li>
<p>Comment the whole output section - this will always work, but all lines will render in the commment color.</p>
</li>
<li>
<p>Use an assignment - this will highlight the output (if desired).</p>
</li>
</ol>
<p>Ripper Examples --</p>
<p>RDoc - <a href="http://ruby-doc.org/stdlib-trunk/libdoc/ripper/rdoc/Ripper.html" class="external">ruby-doc.org</a></p>
<p>RDoc - <a href="https://docs.ruby-lang.org/en/trunk/Ripper.html" class="external">docs.ruby-lang.org</a></p>
<p>YARD - <a href="https://msp-greg.github.io/ruby_trunk/ripper/Ripper.html" class="external">msp-greg.github.io</a></p>
<p>Notice how the first two do not highlight the code sample in the overview, or the <code>.lex</code>, <code>.sexp</code>, or <code>.sexp_raw</code> methods.</p>
<p>I edited three source files for the highlighted output, it does require some kind of line similar to 'below is output, shown as assignment to allow highlighting'. The code in the sample doc is exactly as shown. I believe the two RDoc sites will highlight the code if redone in the style shown on msp-greg.github.io. I'd be happy to submit the changes if people find the highlighting helpful.</p> Ruby master - Misc #13209 (Open): fact.rb in ruby/sample variationshttps://bugs.ruby-lang.org/issues/132092017-02-13T00:59:46Zjzakiya (Jabari Zakiya)
<p>I was looking at some of the Sample files that come with Ruby and<br>
saw the example for doing factorials. It's an old example that I<br>
thought I could make simpler/faster. Below are the results.</p>
<p>Maybe upgrading to show the difference between coding idioms can<br>
be instructive to newer Ruby programmers.</p>
<pre><code>def fact(n)
return 1 if n == 0
f = 1
n.downto(1) do |i|
f *= i
end
return f
end
def fact1(n)
return 1 if n | 1 == 1 # if n 0 or 1
f = 2
n.downto(3) do |i|
f *= i
end
return f
end
def fact2(n)
return 1 if n | 1 == 1 # if n 0 or 1
(2..n).reduce(:*)
end
require 'benchmark/ips'
Benchmark.ips do |x|
x.report("original factorial") { fact 100 }
x.report("modified factorial") { fact1 100 }
x.report("enhanced factorial") { fact2 100 }
x.compare!
end
</code></pre>
<p>Timings using ruby-2.4.0 on Linux 64-bit, on I7 cpu system.</p>
<pre><code>2.4.0 :001 > load 'factversiontest.rb'
Warming up --------------------------------------
original factorial 4.501k i/100ms
modified factorial 4.594k i/100ms
enhanced factorial 5.271k i/100ms
Calculating -------------------------------------
original factorial 44.962k (± 4.2%) i/s - 225.050k in 5.015176s
modified factorial 46.288k (± 3.2%) i/s - 234.294k in 5.066948s
enhanced factorial 53.425k (± 3.1%) i/s - 268.821k in 5.036635s
Comparison:
enhanced factorial: 53424.9 i/s
modified factorial: 46288.0 i/s - 1.15x slower
original factorial: 44961.5 i/s - 1.19x slower
=> true
2.4.0 :002 >
</code></pre> Ruby master - Misc #12911 (Open): Translate docshttps://bugs.ruby-lang.org/issues/129112016-11-08T16:04:00Zsho-h (Sho Hashimoto)sho-h@netlab.jp
<p>translate doc/*.ja.rdoc</p>
<p>c.f. <a href="https://blade.ruby-lang.org/ruby-dev/47319">[ruby-dev:47319]</a></p> Ruby master - Misc #12751 (Open): Incompatibility of Ruby 3https://bugs.ruby-lang.org/issues/127512016-09-12T06:38:38Znaruse (Yui NARUSE)naruse@airemix.jp
<p>META ticket for Ruby 3's breakages</p>
<ul>
<li>Encoding on Windows
<ul>
<li>[Feature <a class="issue tracker-2 status-5 priority-4 priority-default closed" title="Feature: On Windows use UTF-8 as filesystem encoding (Closed)" href="https://bugs.ruby-lang.org/issues/12654">#12654</a>]</li>
<li>[Feature <a class="issue tracker-2 status-5 priority-4 priority-default closed" title="Feature: Use UTF-8 encoding for ENV on Windows (Closed)" href="https://bugs.ruby-lang.org/issues/12650">#12650</a>]</li>
</ul>
</li>
</ul> Ruby master - Misc #12277 (Open): Coding rule: colum numberhttps://bugs.ruby-lang.org/issues/122772016-04-13T07:54:01Zko1 (Koichi Sasada)
<p>Eric proposed that code should be limited in 80 column.<br>
<a href="https://bugs.ruby-lang.org/issues/12236#note-1" class="external">https://bugs.ruby-lang.org/issues/12236#note-1</a></p>
<p>At today's developer's meeting, I asked how long column is suitable.</p>
<ul>
<li>declaration can over limitation.</li>
<li>logic should have some limitation (permit exceptional cases)</li>
</ul>
<p>This is an survey at today's meeting.</p>
<pre><code>Expected column limitation:
80 none
100 2 people
120 some people
over 120 only ko1
</code></pre> Ruby master - Misc #11783 (Open): Do you have any idea if you have a budgets?https://bugs.ruby-lang.org/issues/117832015-12-07T10:29:55Zko1 (Koichi Sasada)
<p>Do you have any idea about Ruby interpreter implementation to do with budgets?</p>
<a name="Background"></a>
<h1 >Background<a href="#Background" class="wiki-anchor">¶</a></h1>
<p>Now, we are summarizing many contributions from many people, organizations and companies.</p>
<p><a href="https://docs.google.com/document/d/1y1sQc40qeuWjF84rVrTmH-ogZ_iNGqU-RUSE8GDlRuk/edit?usp=sharing" class="external">https://docs.google.com/document/d/1y1sQc40qeuWjF84rVrTmH-ogZ_iNGqU-RUSE8GDlRuk/edit?usp=sharing</a></p>
<p>(please let me know if you know any other contributes)<br>
(sorry we wrote contributions especially for MRI, because we don't know)</p>
<p>The great recent news is we get new mac mini machine to run CI on El Capitan. We already have a mac mini machine running CI, but on Yosemite. So we can run CI on both Yosemite and El Capitan.</p>
<p>This new mac mini machine was sponsored by YassLab, Japanese small company.</p>
<p>At first, we ask Nihon-Ruby-no-Kai to prepare this machine, and Takahashi-san (chair man of this organization) tweet about it ("anyone can support it?"). Yasukawa-san, the president of YassLab answers "ok, we'll support it".</p>
<p>We learned that if we show requirements explicitly, anyone may help us.<br>
Listing is important.</p>
<a name="Any-idea"></a>
<h1 >Any idea?<a href="#Any-idea" class="wiki-anchor">¶</a></h1>
<p>Today's developers meeting, we had discussed about that and itemize some dreams.</p>
<blockquote>
<p>nurse: VPS severs for CI are welcome. Especially for Azure.<br>
ko1: travel fee (1,000,000 JPY?) for hackathon to gather MRI developers in one place<br>
ko1: physical machines for development and benchmarks (300,000 JPY)<br>
nobu: development machine (400,000 JPY) because he has several trouble on current machine.<br>
nurse: icc (and other softwares) to try.<br>
martin: grant project for MRI development topics<br>
ko1: education to grow other MRI developer (no estimation)</p>
</blockquote>
<p>Do you have any other idea?<br>
I'll show these list at RubyKaigi, and someone may consider to support us.</p>
<p>(IMO, maybe sponsoring nobu's machine is great contribution for Ruby worlds.<br>
Nobu will put companies logo stickers on his laptop)</p>
<p>Thanks,<br>
Koichi</p> Ruby master - Misc #11570 (Open): Clarify autoload chaining behavior https://bugs.ruby-lang.org/issues/115702015-10-06T16:52:25Zmwpastore (Mike Pastore)mike@oobak.org
<p>I've discovered a discrepancy between how MRI 2.1.7 and 2.2.3 handle autoload "chaining" (which I'll describe below) cf. RBX 2.5.8. I opened <a href="https://github.com/rubinius/rubinius/issues/3513" class="external">an issue</a> with them but the lead contributor of Rubinius is pushing back on me to clarify the expected behavior with you guys. Any guidance you can provide would be appreciated.</p>
<p>Essentially:</p>
<ul>
<li>File A autoloads <code>:Foo</code> from file B, and attempts to invoke methods on class <code>Foo</code>.</li>
<li>File B autoloads <code>:Foo</code> from file C, and attempts to reopen class <code>Foo</code> in order to define additional methods and attributes.</li>
<li>File C defines the base <code>Foo</code> class.</li>
</ul>
<p>In MRI 2.1.7 and 2.2.3, file A can see the methods defined in the base class defined in file C, as well as the extended methods and attributes added in file B. Both autoloads fire in the expected order and the composite class is computed and made available to the caller.</p>
<p>In RBX 2.5.8, file A can only see the extended methods and attributes defined in file B. Only the first autoload fires and the base class definition is never loaded or used.</p>
<p>Which is the correct behavior?</p> Ruby master - Misc #11355 (Open): Exceptions inheriting from Timeout::Error should behave the sam...https://bugs.ruby-lang.org/issues/113552015-07-15T16:59:01Zastratto (Stefano Tortarolo)stefano.tortarolo@gmail.com
<p>Bug <a class="issue tracker-1 status-6 priority-4 priority-default closed" title="Bug: "rescue Exception" rescues Timeout::ExitException (Rejected)" href="https://bugs.ruby-lang.org/issues/8730">#8730</a> addressed a common issue when using Timeout#timeout [*], but I think that the current behaviour is at the very least surprising.</p>
<p>Right now, exceptions provided to Timeout#timeout are rescuable from the inner block and that applies to Timeout::Error too.<br>
The confusing aspect is that there's no way to provide a custom exception that inherits from Timeout::Error and make it not rescuable by the inner block (i.e., <a class="issue tracker-1 status-2 priority-4 priority-default" title="Bug: Logger traps all exceptions; breaks Timeout (Assigned)" href="https://bugs.ruby-lang.org/issues/9115">#9115</a>).</p>
<p>Basically what I would expect is a way to provide a custom exception that's treated calling #catch on it in Timeout#timeout</p>
<pre><code># This could be applied to every exception that inherits from Timeout::Error
# but we need a different interface to provide it, in order to maintain the behaviour that a provided exception is rescuable
bt = Error.catch(message, &bl)
</code></pre>
<p>I'm filing this as Misc and not Bug exactly because reading the code it's expected behaviour, so I'm mainly trying to foster a conversation about whether there's a nice way to support both scenarios.</p>
<p>[*] I don't speak Japanese and I cannot fully trust Google Translate, so forgive me if I lost some fundamental concepts in that thread.</p> Ruby master - Misc #11295 (Open): Request for comments about error messageshttps://bugs.ruby-lang.org/issues/112952015-06-23T01:09:56Zko1 (Koichi Sasada)
<p>(This is not a proposal, bug reports)</p>
<p>Ruby shows error messages when something wrong.</p>
<p>There are several proposals to extend error messages.</p>
<ul>
<li><a href="https://github.com/charliesome/better_errors" class="external">https://github.com/charliesome/better_errors</a></li>
<li><a href="https://github.com/yuki24/did_you_mean" class="external">https://github.com/yuki24/did_you_mean</a></li>
<li><a href="https://github.com/ko1/pretty_backtrace" class="external">https://github.com/ko1/pretty_backtrace</a></li>
</ul>
<p>And some requests.</p>
<ul>
<li>Reverse backtrace and show error messages at the bottom (to avoid scroll up terminal)</li>
<li>Translation error messages to other languages</li>
</ul>
<p>If you have any idea, please tell us.<br>
We can consider about Ruby's error message APIs to realize your ideas.<br>
(I can't guarantee we can implement your ideas :p)</p> Ruby master - Misc #10983 (Open): Why blocks make Ruby methods 439% slower ?https://bugs.ruby-lang.org/issues/109832015-03-19T09:03:44ZSega100500 (Сергей Е)Sergey.V.Ezhov@gmail.com
<p><a href="https://www.omniref.com/ruby/2.2.0/symbols/Proc/yield#annotation=4087638&line=711&hn=1" class="external">https://www.omniref.com/ruby/2.2.0/symbols/Proc/yield#annotation=4087638&line=711&hn=1</a></p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="nb">require</span> <span class="s1">'benchmark/ips'</span>
<span class="k">def</span> <span class="nf">block_call</span><span class="p">(</span><span class="o">&</span><span class="n">block</span><span class="p">)</span>
<span class="n">block</span><span class="p">.</span><span class="nf">call</span>
<span class="k">end</span>
<span class="k">def</span> <span class="nf">just_yield</span>
<span class="k">yield</span>
<span class="k">end</span>
<span class="no">Benchmark</span><span class="p">.</span><span class="nf">ips</span> <span class="k">do</span> <span class="o">|</span><span class="n">x</span><span class="o">|</span>
<span class="n">x</span><span class="p">.</span><span class="nf">report</span><span class="p">(</span><span class="s2">"call"</span><span class="p">)</span> <span class="k">do</span>
<span class="n">block_call</span> <span class="p">{</span> <span class="mi">1</span> <span class="o">+</span> <span class="mi">1</span> <span class="p">}</span>
<span class="k">end</span>
<span class="n">x</span><span class="p">.</span><span class="nf">report</span><span class="p">(</span><span class="s2">"just yield"</span><span class="p">)</span> <span class="k">do</span>
<span class="n">just_yield</span> <span class="p">{</span> <span class="mi">1</span> <span class="o">+</span> <span class="mi">1</span> <span class="p">}</span>
<span class="k">end</span>
<span class="n">x</span><span class="p">.</span><span class="nf">compare!</span>
<span class="k">end</span>
</code></pre>
<p>I run on Ruby 2.2.1</p>
<pre><code>Calculating -------------------------------------
call 40.754k i/100ms
just yield 69.031k i/100ms
-------------------------------------------------
call 814.929k (± 4.0%) i/s - 4.075M
just yield 2.871M (±25.1%) i/s - 12.909M
Comparison:
just yield: 2871127.3 i/s
call: 814929.3 i/s - 3.52x slower
</code></pre> Ruby master - Misc #10791 (Open): [PATCH 1/1] Remove unnecessary passing value from doc for Obser...https://bugs.ruby-lang.org/issues/107912015-01-27T19:43:48Zgogotanaka (Kazuki Tanaka)mail@tanakakazuki.com
<p>Hi, when reading doc for Observable, I notice little unnecessary code which may cause little confusion in example.</p>
<p>take your time.</p>
<p>gogo.</p> Ruby master - Misc #10783 (Open): String#concat has an "appending" behaviorhttps://bugs.ruby-lang.org/issues/107832015-01-26T10:05:42Zas-cii (Antonio Scandurra)me@as-cii.com
<p>Ruby String documentation (<a href="http://www.ruby-doc.org/core-2.2.0/String.html" class="external">http://www.ruby-doc.org/core-2.2.0/String.html</a>) introduces the two terms <strong>Appending</strong> and <strong>Concatenation</strong>:</p>
<ul>
<li>Concatenation (aka <code>+</code>) —Returns a new String containing other_str concatenated to str.</li>
<li>Append (aka <code><<</code>) —Concatenates the given object to str.</li>
</ul>
<p>However, calling <code>concat</code> results in an appending operation. I find this particularly confusing and against the Principle of Least Surprise (e.g. I'd expect <code>concat</code> to actually concatenate something). On the other hand I understand that changing such a small method would result in a quite significant breaking change.</p>
<p>Do you see this as an inconsistency? If yes, is there any particular design (or historical) reason behind it?</p>
<p>Thank you.</p>
<p>P.s. Seems like this is the case for <code>Array</code> as well.</p> Ruby master - Misc #10628 (Open): Peformance of URI modulehttps://bugs.ruby-lang.org/issues/106282014-12-21T14:43:44Ztgxworld (Guo Xiang Tan)gxtan1990@gmail.com
<p>Please view attached screenshot or go to <a href="https://railsbench.herokuapp.com/tgxworld/ruby?utf8=%E2%9C%93&result_types%5B%5D=app_uri&commit=Submit" class="external">the following link</a> to see benchmark graph over time.</p>
<p>It got slower after this <a href="https://github.com/ruby/ruby/commit/bb83f32dc3e0424d25fa4e55d8ff32b061320e41" class="external">commit</a>.</p>
<p>Hope this helps.</p> Ruby master - Misc #10541 (Open): Remove shorthand string interpolation syntaxhttps://bugs.ruby-lang.org/issues/105412014-11-25T16:15:58Zdanielmorrison (Daniel Morrison)daniel@collectiveidea.com
<p>I would like to see the shorthand string interpolation syntax, "foo#@bar" deprecated and then removed in 3.0.</p>
<p>My reasons:</p>
<ol>
<li>Most experienced Ruby developers I've talked to don't even know it exists.</li>
<li>It has been the cause of real problems. <a href="http://status.cloudamqp.com/incidents/vj62pnp62tj9" class="external">http://status.cloudamqp.com/incidents/vj62pnp62tj9</a>
</li>
</ol>
<p>When a syntax is not widely known and has the potential for problems, I think it makes sense to deprecate and remove.</p> Ruby master - Misc #10513 (Open): instance_eval yields the receiver, but is documented to yield n...https://bugs.ruby-lang.org/issues/105132014-11-14T22:29:49Zctm (Cliff Matthews)ctm@devctm.com
<p>instance_eval yields the receiver, but is documented as yielding no arguments.</p>
<p>I searched the bug reports before writing this up and found bug <a class="issue tracker-1 status-8 priority-4 priority-default closed" title="Bug: instance_eval ArgumentError (Third Party's Issue)" href="https://bugs.ruby-lang.org/issues/2476">#2476</a> which was closed with a message that contained "instance_eval yields the receiver in both 1.8 and 1.9. Unfortunately, a Proc object created by lambda raises ArgumentError when extra arguments are yielded in 1.9.". However such behavior is not expected when the calling sequence is:</p>
<pre><code> * call-seq:
* obj.instance_eval(string [, filename [, lineno]] ) -> obj
* obj.instance_eval {| | block } -> obj
</code></pre>
<p>This discrepancy surprised me, but once I realized what was going on I simply used instance_exec instead of instance_eval. All else equal, I would prefer for instance_eval to to not yield the receiver since I can pick up the receiver as self if I want to, but such a change could breaking existing code, so probably documenting the current behavior is better.</p>
<pre><code>bash-3.2$ ruby --version
ruby 2.1.3p242 (2014-09-19 revision 47630) [x86_64-darwin14.0]
bash-3.2$ ./instance_eval
This is the lambda that *does* work.
arg = 32
self = 32
./instance_eval:6:in `block in <main>': wrong number of arguments (1 for 0) (ArgumentError)
from ./instance_eval:17:in `instance_eval'
from ./instance_eval:17:in `<main>'
</code></pre> Ruby master - Misc #10424 (Open): Error message when sorting NaNhttps://bugs.ruby-lang.org/issues/104242014-10-24T21:24:52Zjmthomas (Jason Thomas)
<p>When sorting an array of floats with a NaN you get a very confusing message:<br>
irb(main):001:0> [0.0/0.0,1.0,2.0].sort<br>
ArgumentError: comparison of Float with Float failed</p>
<p>Sorting a nil is much friendlier:<br>
irb(main):012:0> [nil,1.0,2.0].sort<br>
ArgumentError: comparison of NilClass with Float failed</p>
<p>This is confusing for many. Simply google for "comparison of Float with Float failed" and makes for a difficult debugging session for anyone who doesn't know that NaN produces this result. What I would expect is:<br>
irb(main):001:0> [0.0/0.0,1.0,2.0].sort<br>
ArgumentError: comparison of NaN with Float failed</p> Ruby master - Misc #10312 (Open): Give people more control over how the ruby parser sees code and...https://bugs.ruby-lang.org/issues/103122014-10-01T18:28:08Zshevegen (Robert A. Heiler)shevegen@gmail.com
<p>Hi,</p>
<p>I am aware that this proposal has most likely not a chance for<br>
implementation, but I'd still like to make it - this is why I<br>
put it here into misc rather than bugs or features. It's misc -<br>
like ideas!</p>
<p>So first allow me to introduce how I came up with this idea at<br>
all.</p>
<p>I have built a "web framework", which is pretty ugly, but<br>
useful to me. It is actually less of a web framework and<br>
more of a way to describe a "web app" - right now using<br>
valid ruby syntax, but hopefully one day I can transition<br>
into something that is even terser than what it is right<br>
now, and eventually becomes valid ruby (or css or javascript<br>
etc... a bit like HaXe <a href="http://haxe.org/" class="external">http://haxe.org/</a> but with a more<br>
elegant syntax resembling ruby rather than java)</p>
<p>I describe a web-page currently such as that way:</p>
<p>w {<br>
title 'My little page'<br>
css_style '<br>
body {<br>
padding: 0.20em;<br>
}'<br>
favicon 'foo/bar.png'<br>
font_size '20px'<br>
use_jquery<br>
}</p>
<p>Ok, w is simply a method call w() returning an instance of class<br>
WebObject, and we pass it a block. The block I use for a DSL-like<br>
approach to describe the page in question. For instance, use_jquery<br>
simply is in fact w.use_jquery - so it is a method call on that<br>
web object.</p>
<p>Before that, I was using this line here:</p>
<p>jquery :+</p>
<p>The + reminds me of "yes, enable jquery".</p>
<p>Obviously, to disable jquery, I would do:</p>
<p>jquery :-</p>
<p>Then I thought - "Hey, it would be cool if I could do this:</p>
<p>jquery +</p>
<p>instead. In other words, get rid of the : symbol identifier.</p>
<p>But here the ruby parser rightfully chokes because it does not<br>
understand what is meant with jquery +. Fair enough, this is<br>
not valid ruby.</p>
<p>But to my human eyes, jquery + reads nicer than jquery :+</p>
<p>I could get away doing this instead and treat it as a String:</p>
<p>'jquery +'</p>
<p>And simply parse that with ruby. But I already use:</p>
<p>use_jquery</p>
<p>above, so that is nicer IMO than using the two ' characters.</p>
<p>So now, sorry for that long introduction but perhaps you can<br>
understand my line of thought here.</p>
<p>So I was thinking it would be nice if people could get more<br>
control over the Ruby Parser itself.</p>
<p>For instance, in the above example and only for that file/class,<br>
I would like to tell the ruby parser "hey dude, don't mind if<br>
that specific block has invalid syntax, I'd parse on my own.</p>
<p>Possibly it would be enough if those invalid syntax elements<br>
could become strings - then I can parse those strings on my<br>
own.</p>
<p>Of course the net gain between:</p>
<p>jquery :+</p>
<p>and</p>
<p>jquery +</p>
<p>is minimal, but I love ruby's terse syntax.</p>
<p>Anyway, I am aware that this has no real chance for the ruby<br>
2.x era but perhaps considering all the ideas in regards to<br>
optional static type information and what-not for 3.x ruby era,<br>
more control over the ruby parser itself would be nice<br>
(lisp-like macros!).</p>
<p>Regards.</p> Ruby master - Misc #9832 (Open): better concurrency in threadshttps://bugs.ruby-lang.org/issues/98322014-05-12T12:31:12Zariveira (Alexandre Riveira)alexandre@objectdata.com.br
<p>My application runs on top of rainbows using workers with multi-threaded.<br>
I realized that in ruby running on linux (my kernel config is slackware, debian not work)<br>
not equal to distribute the processing threads.<br>
To test this I created the file that is attached test_thread_schedule.rb<br>
The more the final test result is between 20/21 seconds means he has distributed processing equally<br>
So when the road test with ruby 1.9.2 on linux it does not perform.<br>
This improved in ruby 1.9.3 and further in ruby 2.0.<br>
But it still is not the ideal</p>
<p>My tests:<br>
ruby 1.9.2p320 => not work<br>
ruby 1.9.3p545 => 68 secs<br>
ruby 2.0.0p451 => 29 secs<br>
ruby 2.1.2p95 => 29 secs</p>
<p>ruby without GVL workfine<br>
rubinius 2.2.6 => 21 secs<br>
jruby 1.7.12 => 21 secs</p>
<p>But if I apply taskset (uncomment line in the test file <code>taskset -c -p 2 #{Process.pid}</code>)<br>
the results are noticeably better especially in ruby 1.9.2</p>
<p>ruby 1.9.2p320 => 21 secs<br>
ruby 1.9.3p545 => 30 secs<br>
ruby 2.0.0p451 => 23 secs<br>
ruby 2.1.2p95 => 23 secs</p>
<p>This reflects directly in the application, if one thread is is using 100% cpu with rainbows application begins to degrade coming to answer the other threads 7-16 seconds based time passes. Taskset already applied it decreases considerably. The same test applied cougar, gets to be virtually no impact, but since taskset is applied to the process, follow my code</p>
<p>rainbows:</p>
<p>before_fork do |server, worker|<br>
<code>taskset -c -p 2 #{Process.pid}</code></p>
<p>puma:</p>
<p>on_worker_boot do |index|<br>
<code>taskset -c -p 2 #{Process.pid}</code></p>
<p>Could internally ruby linux treat in a special way so that the behavior of threads is improved ???<br>
If this behavior can not be improved through a new feature in ruby I am grateful for any help for<br>
fixing the process taskset on a particular processor which is not ideal.</p> Ruby master - Misc #9724 (Open): Warnings in Ruby: allow per-file directives to i.e. suppress war...https://bugs.ruby-lang.org/issues/97242014-04-10T18:21:31Zshevegen (Robert A. Heiler)shevegen@gmail.com
<p>Hi,</p>
<p>A bit of intro.</p>
<p>I usually run all my ruby code with -w. I feel that it gives me some more security if the<br>
ruby parser does not have to think about ambiguous code.</p>
<p>Now this works perfect for my own code - I know what I have written, I know how to fix it,<br>
so my code runs fine.</p>
<p>Problem is other people who do not use the -w switch, and in doing so their stuff outputs<br>
a lot of warnings if I require their project and use them.</p>
<p>This is somewhat annoying and there is no real good way to fix it as far as I know.</p>
<p>Modifying $VERBOSE and setting it to nil is of no real help because it works globally.<br>
But I'd rather want something to be used on a per-file basis.</p>
<p>Would it be possible to enable something that could be used on a per file<br>
basis? Kernel.no_warnings, or Kernel.be_silent or something like this?</p> Ruby master - Misc #9516 (Open): Consolidate all deprecation messages to one or more helper methodshttps://bugs.ruby-lang.org/issues/95162014-02-13T17:11:56Zenebo (Thomas Enebo)tom.enebo@gmail.com
<p>I was examining this blog entry: <a href="http://batsov.com/articles/2014/02/05/a-list-of-deprecated-stuff-in-ruby/" class="external">http://batsov.com/articles/2014/02/05/a-list-of-deprecated-stuff-in-ruby/</a> and I wanted to add these warning in JRuby. I thought it would be nice if I could make a higher level construct (e.g. @RubyDeprecated(use="Dir.exist?")) but then realized MRI does not consistently have the same warning string formats:</p>
<p>"Dir.exists? is a deprecated name, use Dir.exist? instead"<br>
"GDBM#index is deprecated; use GDBM#key"<br>
"Zlib::GzipReader#bytes is deprecated; use #each_byte instead"</p>
<p>Some helper methods could make these consistent and then I could make the higher level abstraction in JRuby as well. Since these are warnings I might still make an abstraction and let JRuby be a little inconsistent but I thought I would pass this idea along.</p>