<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>tomanderson (thomas)</title>
    <link>https://ruby-china.org/tomanderson</link>
    <description/>
    <language>en-us</language>
    <item>
      <title>puma malformed request 报错</title>
      <description>&lt;p&gt;我的 rails 跑在生产环境经常出现 puma 报错：&lt;/p&gt;

&lt;p&gt;HTTP pase error, malformed request: 
Puma::HttpParseError: Invalid HTTP format, parsing fails. Are you trying to open an SSL connection to a non-SSL Puma?&lt;/p&gt;

&lt;p&gt;用的是 nginx 转发到 rails，内部通信是 http 非 https。&lt;/p&gt;

&lt;p&gt;一开始以为没有什么影响，无非是控制台出一堆报错而已，就没管它。后来发现时间长了会导致 rails 被系统 kill（不知道是不是因为内存方面的原因），这就很麻烦了。&lt;/p&gt;

&lt;p&gt;求教各位，有解决的办法吗？&lt;/p&gt;</description>
      <author>tomanderson</author>
      <pubDate>Tue, 22 Mar 2022 10:46:16 +0800</pubDate>
      <link>https://ruby-china.org/topics/42246</link>
      <guid>https://ruby-china.org/topics/42246</guid>
    </item>
    <item>
      <title>发现一个奇怪的 case：全局变量中的对象 class 竟然不相等</title>
      <description>&lt;p&gt;rails 中，initializer 里 new 一个 Clazz 对象加入数组（全局变量）：
clazz = Clazz.new
$arr = [clazz]&lt;/p&gt;

&lt;p&gt;rails 启动后，再判断$arr 中的 clazz 对象是否为 Clazz：
Clazz === $arr.first&lt;/p&gt;

&lt;p&gt;得到的结果竟然是 false？！&lt;/p&gt;

&lt;p&gt;查看$arr.first.class，确实是 Clazz，当然它也可以正常执行 Clazz 类的任何实例方法。&lt;/p&gt;

&lt;p&gt;所以这是为什么呢？请教。&lt;/p&gt;

&lt;p&gt;我 new 了一个空白项目，只增加 2 行代码，复现了这个问题。&lt;/p&gt;

&lt;p&gt;方法如下：&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;rails new rails_test --api&lt;/li&gt;
&lt;li&gt;rails g model Clazz&lt;/li&gt;
&lt;li&gt;在 initializers 下新增 global_vars.rb，内容为 $clazz = Clazz.new&lt;/li&gt;
&lt;li&gt;在 controllers 新增 test_controller，内容为 render json: Clazz === $clazz&lt;/li&gt;
&lt;li&gt;访问 localhost:3000/test，显示 false（routes.rb 需相应修改）&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;默认的初始项目，rails 版本是最新的，ruby 版本是 3.0.1，不过 3.0.2 也试过一样。&lt;/p&gt;

&lt;p&gt;好像传不了附件，那我就把项目打包放到这个网址了，想复现的可以下载：&lt;/p&gt;

&lt;p&gt;&lt;a href="https://fanyipdf.com/rails_test.zip" rel="nofollow" target="_blank"&gt;https://fanyipdf.com/rails_test.zip&lt;/a&gt;&lt;/p&gt;</description>
      <author>tomanderson</author>
      <pubDate>Wed, 24 Nov 2021 18:29:01 +0800</pubDate>
      <link>https://ruby-china.org/topics/41921</link>
      <guid>https://ruby-china.org/topics/41921</guid>
    </item>
    <item>
      <title>rails 能通过 env 控制 routes 吗</title>
      <description>&lt;p&gt;比如我在 routes.rb 有一条 route，我想当 env=production 的时候启用它，env=development 的时候禁用他，有办法做到吗？&lt;/p&gt;</description>
      <author>tomanderson</author>
      <pubDate>Sat, 13 Nov 2021 19:58:54 +0800</pubDate>
      <link>https://ruby-china.org/topics/41880</link>
      <guid>https://ruby-china.org/topics/41880</guid>
    </item>
    <item>
      <title>ruby 内存持续增加，无法垃圾回收</title>
      <description>&lt;p&gt;我的每个 rails 项目，都发现有长期运行或内存逐渐增加、只增不减的问题。本着严于律己、宽于待人的原则，我一直以为是自己代码写得太烂，出现了内存泄露。&lt;/p&gt;

&lt;p&gt;直到今天做了一个实验，我怀疑这个问题和 ruby 本身有关……&lt;/p&gt;

&lt;p&gt;环境是 ruby3.0.1 + rails6.1.4。&lt;/p&gt;

&lt;p&gt;实验 1：&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;times&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;long_str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"a"&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;10_000_000&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;render&lt;/span&gt; &lt;span class="ss"&gt;json: &lt;/span&gt;&lt;span class="s1"&gt;'OK'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;代码简单至极，就是创建一个长字符串，运行 100 次只是为了效果更明显。&lt;/p&gt;

&lt;p&gt;这段代码的效果是：每次运行大约增加 1g 内存，且不会释放。&lt;/p&gt;

&lt;p&gt;按理说，render 之后整个请求已经结束，long_str 已经没有继续使用的可能，又不是什么实例变量、全局变量，ruby 应该把 long_str 垃圾回收，但是并没有。&lt;/p&gt;

&lt;p&gt;我曾经以为 long_str 已经被回收，只是 ruby 占着内存的坑不想还给系统而已，除非系统内存不足才会还。但是我冒着死机的风险运行到系统内存全部吃光，ruby 进程的内存并没有分毫减少。&lt;/p&gt;

&lt;p&gt;实验 2：&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;long_str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"a"&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;10_000_000&lt;/span&gt;
&lt;span class="n"&gt;long_str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kp"&gt;nil&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;如果之前是因为 ruby 不知道 long_str 已经没用了所以没回收，那现在用 long_str = nil 告诉 ruby 总可以了吧？&lt;/p&gt;

&lt;p&gt;结果：和实验 1 没有什么区别。&lt;/p&gt;

&lt;p&gt;实验 3：&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;long_str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"a"&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;10_000_000&lt;/span&gt;
&lt;span class="n"&gt;long_str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kp"&gt;nil&lt;/span&gt;
&lt;span class="no"&gt;GC&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;start&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;现在每一轮循环结束后手动执行垃圾回收。确实有效果，ruby 不会内存增加 1g 了，但是每次会增长 10m，而且永远不会释放。&lt;/p&gt;

&lt;p&gt;我就想知道，这个问题到底怎么解决，到底怎么写才不会“内存泄露？即使手动执行垃圾回收（在我看来这些代码是多余的），ruby 内存仍然会永久性增长？&lt;/p&gt;

&lt;p&gt;代码已经简单到极点了，如果连这么简单的代码都有内存问题，那真正的项目中怎么可能不出现所谓“内存泄露”？&lt;/p&gt;</description>
      <author>tomanderson</author>
      <pubDate>Wed, 11 Aug 2021 11:24:24 +0800</pubDate>
      <link>https://ruby-china.org/topics/41572</link>
      <guid>https://ruby-china.org/topics/41572</guid>
    </item>
    <item>
      <title>Puma worker 有内存回收/重启机制吗？</title>
      <description>&lt;p&gt;发现 puma 开单进程跑 rails，内存占用似乎只涨不跌。启动时内存 300m，过几天将近 2g，但是从来没有发现内存下降的情况。&lt;/p&gt;

&lt;p&gt;看到这个帖子（&lt;a href="https://ruby-china.org/topics/24479" rel="nofollow" target="_blank"&gt;https://ruby-china.org/topics/24479&lt;/a&gt;）的回复中有人说：&lt;/p&gt;

&lt;p&gt;“细心观察 workers 进程在一定时间就会变动，相当于重启内存回收。”&lt;/p&gt;

&lt;p&gt;但是我在测试环境下开了 workers，等了十几分钟不动，好像 workers 进程和内存占用没有任何变化……&lt;/p&gt;

&lt;p&gt;想问下用过的同学，“workers 会自动重启/回收内存”，是真的吗？具体是什么机制呢？&lt;/p&gt;</description>
      <author>tomanderson</author>
      <pubDate>Tue, 01 Jun 2021 18:13:48 +0800</pubDate>
      <link>https://ruby-china.org/topics/41322</link>
      <guid>https://ruby-china.org/topics/41322</guid>
    </item>
    <item>
      <title>Rails 多线程并发占用 CPU 问题</title>
      <description>&lt;p&gt;在 server 机（4 核）开一个 rails，1 个客户端向 server 请求。假设该请求会消耗 100% 的 cpu，那么 server 机实际占用的 cpu 是 25%。无论这个请求多么耗 cpu，也不可能超过整机的 25%，因为 rails 是单进程 + 单线程模式。这个在预期内。&lt;/p&gt;

&lt;p&gt;开 4 个不同的客户端同时向 server 请求，测试发现，server 机 cpu 占用仍然是 25%！难道无论有多少客户端请求，rails 只能利用 1 个 cpu 核心？rails 作为一个 web server，不应该这样吧？如果是这样的话，那上百万用户的网站，rails 怎么撑得过来？&lt;/p&gt;

&lt;p&gt;我想知道，有没有办法让 rails 利用多核心，这样并发情况下可以多核负载？&lt;/p&gt;</description>
      <author>tomanderson</author>
      <pubDate>Sat, 29 May 2021 15:23:11 +0800</pubDate>
      <link>https://ruby-china.org/topics/41315</link>
      <guid>https://ruby-china.org/topics/41315</guid>
    </item>
    <item>
      <title>ractor 跑一段简单代码，百分百崩溃</title>
      <description>&lt;p&gt;昨天我试图在真实项目中应用 ractor，测出了 ractor 2 线程比 ractor 1 线程慢近 1 倍的诡异现象。原贴在此：&lt;a href="https://ruby-china.org/topics/40901" rel="nofollow" target="_blank"&gt;https://ruby-china.org/topics/40901&lt;/a&gt;。&lt;/p&gt;

&lt;p&gt;今天继续折腾 ractor。经过一系列的失望，我对 ractor 的期望值已经非常低了，我只要它跑起来不要崩溃就谢天谢地了。因为在测试过程中，经常出现 rails 崩溃的情况。结果，我发现一段非常简单的代码，就能让 ractor 百分百崩溃……&lt;/p&gt;

&lt;p&gt;先贴出不用 ractor 的单线程方法，当然运行是正常的：&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;to_a&lt;/span&gt;
&lt;span class="n"&gt;arr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;sub_arr&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="n"&gt;sub_arr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;md5&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}.&lt;/span&gt;&lt;span class="nf"&gt;flatten&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;就是随机生成字符串做 md5。md5 调用 module 中的方法 Digest::MD5.hexdigest(str)。代码中分成 4 个子数组，是为了和 ractor 对比，ractor 方法会开 4 个线程，每个线程处理 1 个子数组：&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;sub_arr&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="no"&gt;Ractor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sub_arr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;sub_arr&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
    &lt;span class="n"&gt;sub_arr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;md5&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="p"&gt;}.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;take&lt;/span&gt;&lt;span class="p"&gt;}.&lt;/span&gt;&lt;span class="nf"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;(:&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这段代码每次运行都会导致 rails 崩溃，报错：*** Error in `puma 5.2.1 (tcp://0:3001) : free(): invalid next size (fast): 0x00007fa7d80032a0 ***&lt;/p&gt;

&lt;p&gt;是代码的问题吗？把 e 改为 1..100，立马不崩溃了，怎么解释？&lt;/p&gt;

&lt;p&gt;e=1..1 万、100 万，又崩溃了。是计算量太大导致崩溃的吗？然而，同样数值用非 ractor 的普通单线程方法，却完全正常。&lt;/p&gt;

&lt;p&gt;我的环境是 ruby3.0+rails6.1.1，所有 gem 升到最新。2 核 4 线程 cpu，空闲内存有 4g。大家可以用自己的环境重现试试。&lt;/p&gt;

&lt;p&gt;要么是我代码的问题，要么是环境的问题，要么是 ractor 本身的问题，我想不出别的可能了。希望是我自己的问题，请各位打脸无妨。如果是我的问题，我还能改；如果是 ractor 的问题，那我只能弃用 ractor 了。&lt;/p&gt;

&lt;p&gt;后续：&lt;/p&gt;

&lt;p&gt;后来把这个问题发到&lt;a href="https://bugs.ruby-lang.org/issues" rel="nofollow" target="_blank"&gt;https://bugs.ruby-lang.org/issues&lt;/a&gt;，处理我问题的是 ko1（Koichi Sasada），他用一个更简化的版本复现了问题，只有一行代码：&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;times&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="no"&gt;Ractor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="kp"&gt;loop&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nb"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_s&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;}.&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="ss"&gt;:take&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;看来基本可以确定是 ruby3.0 的 bug，大概率与 ractor 有关，可能与环境也有关。至于坑有多深我就不知道了，让大神去填吧。&lt;/p&gt;

&lt;p&gt;各位如果方便的话，可以把这行代码放到 irb 里跑一下，只需 1 秒钟的时间。如果有人竟然不报错崩溃的，请回复我，我可以把情况发给 ko1 做个参考。&lt;/p&gt;

&lt;p&gt;结局：&lt;/p&gt;

&lt;p&gt;此问题已被 nobu 和 ko1 修复，原文如下：&lt;/p&gt;

&lt;p&gt;Fixed the race condition when replacing freelist entry with its chained next element. At acquiring an entry, hold the entry once with the special value, then release by replacing it with the next element again after acquired. If another thread is holding the same entry at that time, spinning until the entry gets released.&lt;/p&gt;</description>
      <author>tomanderson</author>
      <pubDate>Mon, 08 Feb 2021 11:10:35 +0800</pubDate>
      <link>https://ruby-china.org/topics/40902</link>
      <guid>https://ruby-china.org/topics/40902</guid>
    </item>
    <item>
      <title>ractor 应用到真实项目，结果彻底失望</title>
      <description>&lt;p&gt;我的一个项目中大量使用了 gem parallel 开多进程，因此对 ractor 很期待，希望能达到 cpu 性能接近多线程、内存占用小的效果。现在已经折腾了一个礼拜，实际结果非常失望。&lt;/p&gt;

&lt;p&gt;首先，ractor 的用法让我觉得很别扭。比如，我要运行 A.xxx 方法，而它又调用了 B.yyy 方法，需要 Ractor.new(A,B) 把所有 class 全部传入才能使用，否则报错方法 undefined。而且，module 中的方法不能直接使用，也不能和 class 一样传入，我只能在 initializer 中 include module 使其能够在 ractor 中访问。&lt;/p&gt;

&lt;p&gt;当然，只要效果能管用，这些都在其次，无非是多了点填坑时间。然而，当我最终在真实项目中把 ractor 跑起来之后，简直大跌眼镜：&lt;/p&gt;

&lt;p&gt;ractor 开 2 线程，竟然比开 1 线程慢近 1 倍。&lt;/p&gt;

&lt;p&gt;这里说的开 1 线程，还不是不用 ractor，只是调整 ractor 并发数而已，连代码都不变。看 cpu 占用发现，2 线程确实能跑满 2 个核心，但就是比 1 线程慢。&lt;/p&gt;

&lt;p&gt;我的第一反应自然是：代码有问题吧？会不会 2 线程执行的总工作量比 1 线程多？于是我把 ractor 线程执行的方法改成一个计算斐波那契数列的简单函数，它的运行时间是固定的。再测，发现效果正常了：2 线程用时是 1 线程的一半左右，继续增加线程超过 cpu 核心数后，耗时不变。又改为 parallel 跑，2 线程也比 1 线程快 30% 左右，不可能出现线程数增加速度反而变慢的效果。&lt;/p&gt;

&lt;p&gt;那么这个让 ractor 多线程变慢的方法有何神奇之处？我觉得只是数学计算和创建对象比较多而已。如果连这都没有，那也用不着跑多线程了。&lt;/p&gt;

&lt;p&gt;ractor 目前是 experimental 状态，我也不指望现在就大面积应用到真实项目。然而在我的项目中，我竟然找不到一处可以换成 ractor 的地方：除了上述无法理解的变慢问题，还发现 1 个 gem 导致 rails 崩溃、1 个 gem 不兼容无法调用。&lt;/p&gt;

&lt;p&gt;但愿是我自己使用的问题，而不是 ractor 本身有问题。如果 ractor 真的不成器的话，对 ruby 实在不是一个好消息，因为 ruby 也没有另一个真正意义上的多线程了。&lt;/p&gt;</description>
      <author>tomanderson</author>
      <pubDate>Sun, 07 Feb 2021 20:32:40 +0800</pubDate>
      <link>https://ruby-china.org/topics/40901</link>
      <guid>https://ruby-china.org/topics/40901</guid>
    </item>
    <item>
      <title>ruby map 有没有更简洁的写法</title>
      <description>&lt;p&gt;arr = [{a:1}, {a:2}]，要得到 [1,2]，一般这样写：&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="nb"&gt;hash&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nb"&gt;hash&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:a&lt;/span&gt;&lt;span class="p"&gt;]}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;我知道有一种写法是：&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'a'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s1"&gt;'b'&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="ss"&gt;:upcase&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;如果能写成这样就好了：
arr.map(&amp;amp;:[:a])&lt;/p&gt;

&lt;p&gt;当然，这样是报错的。&lt;/p&gt;

&lt;p&gt;有没有类似的写法呢？&lt;/p&gt;</description>
      <author>tomanderson</author>
      <pubDate>Thu, 04 Feb 2021 22:19:14 +0800</pubDate>
      <link>https://ruby-china.org/topics/40892</link>
      <guid>https://ruby-china.org/topics/40892</guid>
    </item>
    <item>
      <title>ractor 有没有更简洁的写法</title>
      <description>&lt;p&gt;这两天在测试 ractor。一般的写法如下：&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;ractor&lt;/span&gt;
  &lt;span class="n"&gt;threads&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;  &lt;span class="c1"&gt;#线程数&lt;/span&gt;
  &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;

  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="n"&gt;threads&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Ractor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="no"&gt;B&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;xxx&lt;/span&gt;  &lt;span class="c1"&gt;#执行方法&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="n"&gt;render&lt;/span&gt; &lt;span class="ss"&gt;json: &lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;take&lt;/span&gt; &lt;span class="p"&gt;}.&lt;/span&gt;&lt;span class="nf"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;(:&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;但是感觉有点太繁琐了。以前用 gem parallel，写法是：&lt;/p&gt;

&lt;p&gt;arr_new = Parallel.map(arr, in_processes:4) do |sub_arr| ...&lt;/p&gt;

&lt;p&gt;自动把 arr 拆分，分配到多进程/多线程去运算，结果合并输出。&lt;/p&gt;

&lt;p&gt;ractor 有没有类似的方法？&lt;/p&gt;

&lt;p&gt;本来指望 gem parralle 升级一下，把多线程方法改为 ractor。然而并没有。找了下也没发现有别的 gem 可以做类似功能。&lt;/p&gt;</description>
      <author>tomanderson</author>
      <pubDate>Thu, 28 Jan 2021 16:09:09 +0800</pubDate>
      <link>https://ruby-china.org/topics/40871</link>
      <guid>https://ruby-china.org/topics/40871</guid>
    </item>
    <item>
      <title>Ruby 和 Java 的性能差距太大了</title>
      <description>&lt;p&gt;都知道 ruby 的性能是弱项，但心里总觉得 ruby 一直在进步，差距会越来越小的。&lt;/p&gt;

&lt;p&gt;今天为了试验 ractor，写了一个非常简单的斐波那契数列求和：&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;fib&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
  &lt;span class="n"&gt;fib&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;fib&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;一台小破笔记本，ruby2.7，单线程跑 fib(40)，14 秒。开 jit 后 5 秒（之前以为开不开 jit 一样，后来发现是 rails 的问题，代码是放在 rails 里跑的）。&lt;/p&gt;

&lt;p&gt;当时没觉得有啥，因为没有对比就没有伤害。后来顺便用同机的 java11 跑了下——1 秒不到。&lt;/p&gt;

&lt;p&gt;我从 ruby2.3 用到现在，这是第一次对 ruby 感到绝望。&lt;/p&gt;

&lt;p&gt;难道每一个 ruby 项目的结局，都是用 java 重写吗？&lt;/p&gt;</description>
      <author>tomanderson</author>
      <pubDate>Tue, 26 Jan 2021 20:20:05 +0800</pubDate>
      <link>https://ruby-china.org/topics/40862</link>
      <guid>https://ruby-china.org/topics/40862</guid>
    </item>
    <item>
      <title>Ruby 不同入参类型的函数，能不能用同一个名字</title>
      <description>&lt;p&gt;java 等静态语言中，我可以用两个相同名称的函数来处理不同类型的入参：&lt;/p&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="c1"&gt;//处理str&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;handle&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;str&lt;/span&gt;&lt;span class="o"&gt;){&lt;/span&gt;
    &lt;span class="err"&gt;……&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;//处理数组&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;handle&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;//代码仅为示意&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;str&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="o"&gt;){&lt;/span&gt;
        &lt;span class="n"&gt;handle&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;str&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;当我调用 handle 时，无论什么类型的入参都可以用，很方便。&lt;/p&gt;

&lt;p&gt;在 ruby 中，我只能用两个不同名称的函数：&lt;/p&gt;

&lt;p&gt;def handle_str(str)&lt;/p&gt;

&lt;p&gt;def handle_arr(arr)&lt;/p&gt;

&lt;p&gt;我也想过在同一个函数中通过判断入参类型来分别处理，但是感觉还是很麻烦，特别是当 handle_arr 调用了 handle_str 的时候。&lt;/p&gt;

&lt;p&gt;有没有更优雅的方式呢？&lt;/p&gt;</description>
      <author>tomanderson</author>
      <pubDate>Thu, 07 Jan 2021 23:02:55 +0800</pubDate>
      <link>https://ruby-china.org/topics/40790</link>
      <guid>https://ruby-china.org/topics/40790</guid>
    </item>
    <item>
      <title>Ruby 3.0 用那种方式写并行计算快，ractor 还是 gem parallel</title>
      <description>&lt;p&gt;有一些计算密集型的任务需要并行算。ruby2 时代我常用的套路是：安装 gem parallel，它提供了多线程、多进程两种方法，而且语法也比较简单。一般来说，如果用多进程方法，基本上所有 cpu 核心都可以跑满。&lt;/p&gt;

&lt;p&gt;但是现在 ruby3 有了 ractor。我在想，如果改用 ractor 做并行，会比 parallel 更快吗？&lt;/p&gt;

&lt;p&gt;不清楚 parallel 和 ractor 的具体实现原理，故请各位大神、或者用过的同学指教。&lt;/p&gt;</description>
      <author>tomanderson</author>
      <pubDate>Thu, 31 Dec 2020 23:00:02 +0800</pubDate>
      <link>https://ruby-china.org/topics/40771</link>
      <guid>https://ruby-china.org/topics/40771</guid>
    </item>
    <item>
      <title>Rails 6 做 test 时报错：DEPRECATION WARNING: Initialization autoloaded the constants</title>
      <description>&lt;p&gt;我在 config/initializers 中加了一个启动时执行的方法，它会调用 controllers/concerns 中某个 module 里的一些方法。这样做的目的是，项目中要用到一个全局变量，而生成这个全局变量需要几秒钟，为了避免反复生成它，就放到 initializers 中，让 rails 启动时生成一次，后面直接使用即可。实测完全正常。&lt;/p&gt;

&lt;p&gt;但是在做 test 时出现了警告：&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DEPRECATION WARNING: Initialization autoloaded the constants Const, Util, and Public.

Being able to do this is deprecated. Autoloading during initialization is going
to be an error condition in future versions of Rails.

Reloading does not reboot the application, and therefore code executed during
initialization does not run again. So, if you reload Const, for example,
the expected changes won't be reflected in that stale Module object.

These autoloaded constants have been unloaded.

Please, check the "Autoloading and Reloading Constants" guide for solutions.
 (called from &amp;lt;main&amp;gt; at /home/thomas/rails/project/config/environment.rb:8)
Run options: --seed 18699

# Running:

.

Finished in 0.084160s, 11.8821 runs/s, 47.5284 assertions/s.
1 runs, 4 assertions, 0 failures, 0 errors, 0 skips
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;如果把 initializers 中那个启动时执行的方法去掉，一切正常。然而，如果不用 initializers，我想不出还有什么更好的办法来加载这个全局变量……&lt;/p&gt;

&lt;p&gt;当然，出警告目前并不影响使用。但还是想知道有解决的办法吗？&lt;/p&gt;</description>
      <author>tomanderson</author>
      <pubDate>Sun, 27 Sep 2020 11:04:01 +0800</pubDate>
      <link>https://ruby-china.org/topics/40442</link>
      <guid>https://ruby-china.org/topics/40442</guid>
    </item>
    <item>
      <title>Rails 中 eval 执行变量赋值的问题，binding 相关</title>
      <description>&lt;p&gt;rails 写一个简单函数：&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def test
  eval("a=1")
  return a
end
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;以为会返回 1，但实际报错变量 &lt;code&gt;a undefined&lt;/code&gt;。&lt;/p&gt;

&lt;p&gt;如果是 irb 中，这个问题可以用绑定作用域的方法解决：&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="nb"&gt;eval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"a=1"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="no"&gt;IRB&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;conf&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:MAIN_CONTEXT&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;workspace&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;binding&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;请教各位，在 rails 中如何解决呢？&lt;/p&gt;</description>
      <author>tomanderson</author>
      <pubDate>Tue, 17 Sep 2019 15:48:06 +0800</pubDate>
      <link>https://ruby-china.org/topics/39059</link>
      <guid>https://ruby-china.org/topics/39059</guid>
    </item>
    <item>
      <title>升级 Rails 6.0 后出现的奇怪报错，可能与并行有关</title>
      <description>&lt;p&gt;项目中本来用到一个 gem Parallel，做多进程并行化。rails5.2 升级 6.0，执行并行化进程后 Ctrl-C 关闭 console，就会报错如下：&lt;/p&gt;

&lt;p&gt;/var/lib/gems/2.6.0/gems/concurrent-ruby-1.1.5/lib/concurrent/atomic/ruby_thread_local_var.rb:87: [BUG] rb_vm_get_cref: unreachable
ruby 2.6.2p47 (2019-03-13 revision 67232) [x86_64-linux-gnu]&lt;/p&gt;

&lt;p&gt;目前貌似并不影响功能，只是每次关闭会报错而已。是这个 gem 引起的吗，有办法吗？&lt;/p&gt;</description>
      <author>tomanderson</author>
      <pubDate>Thu, 05 Sep 2019 18:30:56 +0800</pubDate>
      <link>https://ruby-china.org/topics/39019</link>
      <guid>https://ruby-china.org/topics/39019</guid>
    </item>
  </channel>
</rss>
