<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>larrylv (larrylv)</title>
    <link>https://ruby-china.org/larrylv</link>
    <description>Engineering at @stripe</description>
    <language>en-us</language>
    <item>
      <title>Write a TCP stack in Ruby</title>
      <description>&lt;p&gt;Blog post: &lt;a href="http://blog.larrylv.com/write-a-tcp-stack-in-ruby/" rel="nofollow" target="_blank"&gt;http://blog.larrylv.com/write-a-tcp-stack-in-ruby/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I read [Julia][julia-twitter]'s article [What happens if you write a TCP stack in Python?][julia-article] last year, and since then I really wanted to implement a TCP stack in Ruby language. I saved Julia's article in my [Pocket][pocket], then moved it to my browser bookmark folder, but never touched it again.&lt;/p&gt;

&lt;p&gt;This week, I decided to give it a try and it turns out to be really fun. In this post, I'm going to follow Julia's steps and blog some implementation details.&lt;/p&gt;

&lt;p&gt;My codes are here: [larrylv/teeceepee][my-teeceepee], the name &lt;code&gt;teeceepee&lt;/code&gt; is borrowed from Julia's repo: [jvns/teeceepee][julia-teeceepee].&lt;/p&gt;

&lt;p&gt;What we would like to do here is, I quote from Julia's blog:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;open a raw network socket that lets me send TCP packets&lt;/li&gt;
&lt;li&gt;send a HTTP request to &lt;code&gt;GET&lt;/code&gt; google.com&lt;/li&gt;
&lt;li&gt;get and parse a response&lt;/li&gt;
&lt;li&gt;celebrate!&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I use a gem called [PacketFu][packetfu] to read and write packets. I don't think I could write the stack in such a short time without it, it's really awesome.&lt;/p&gt;
&lt;h2 id="Step 1: the TCP handshake"&gt;Step 1: the TCP handshake&lt;/h2&gt;
&lt;p&gt;The TCP three-way handshake is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;me: SYN&lt;/li&gt;
&lt;li&gt;google: SYNACK&lt;/li&gt;
&lt;li&gt;me: ACK&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Pseduo codes could be something like this:&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;send_syn_packet
read_response
send_ack_packet
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;With &lt;code&gt;PacketFu&lt;/code&gt;, sending a packet is pretty simple:&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'packetfu'&lt;/span&gt;

&lt;span class="n"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;PacketFu&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Utils&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;whoami?&lt;/span&gt;

&lt;span class="n"&gt;synpkt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;PacketFu&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;TCPPacket&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="ss"&gt;config: &lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;flavor: &lt;/span&gt;&lt;span class="s2"&gt;"Linux"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;synpkt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ip_daddr&lt;/span&gt;      &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"216.58.221.142"&lt;/span&gt; &lt;span class="c1"&gt;# ip of google.com&lt;/span&gt;
&lt;span class="n"&gt;synpkt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;tcp_dst&lt;/span&gt;       &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;               &lt;span class="c1"&gt;# port of google.com&lt;/span&gt;
&lt;span class="n"&gt;synpkt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;tcp_flags&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;syn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;                &lt;span class="c1"&gt;# SYN&lt;/span&gt;
&lt;span class="n"&gt;synpkt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;recalc&lt;/span&gt;

&lt;span class="n"&gt;synpkt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_w&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;For ack packet, just set &lt;code&gt;pkt.tcp_flags.ack = 1&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;As to read response, we need to filter packets from the interface.&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'packetfu'&lt;/span&gt;

&lt;span class="n"&gt;cap&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;PacketFu&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Capture&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="ss"&gt;iface: &lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:iface&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="ss"&gt;start: &lt;/span&gt;&lt;span class="kp"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="ss"&gt;filter: &lt;/span&gt;&lt;span class="s2"&gt;"tcp and src 216.58.221.142"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;cap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stream&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="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;pkt&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="c1"&gt;# parse pkt and decide what to do next&lt;/span&gt;
  &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="n"&gt;pkt&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;filter&lt;/code&gt; parameter for &lt;code&gt;PacketFu::Capture&lt;/code&gt; is very interesting, it's a bpf filter and you could find the syntax documentation [here][bpf-syntax]. &lt;code&gt;tcp and src 216.58.221.142&lt;/code&gt; means we would like to filter tcp packets from ip &lt;code&gt;216.58.221.142&lt;/code&gt;, which are exactly what we want to parse.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;tcpdump&lt;/code&gt; also uses bpf filter to filter packets you want.&lt;/p&gt;

&lt;p&gt;Let's say we just want the &lt;code&gt;SYNACK&lt;/code&gt; packets. With tcpdump:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;
$ sudo tcpdump -i eth0 'tcp[13]=18'
&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src="https://l.ruby-china.com/photo/2015/7a3a11d82ac51fea85e4f31dac1295c8.png" title="" alt=""&gt;&lt;/p&gt;

&lt;p&gt;What does &lt;code&gt;tcp[13]=18&lt;/code&gt; mean? Here is the TCP Header Format:&lt;/p&gt;

&lt;p&gt;&lt;img src="https://l.ruby-china.com/photo/2015/f31ba127d9ab8539c96c47145e1afd1b.png" title="" alt=""&gt;&lt;/p&gt;

&lt;p&gt;We could see that the last six bits of fourteenth byte stand for tcp flags, and the previous two bits are both 0. So for &lt;code&gt;SYNACK&lt;/code&gt; packets, tcp flags would be: &lt;code&gt;010010&lt;/code&gt;, the value would be 16 + 2 = 18.&lt;/p&gt;

&lt;p&gt;Bpf is super powerful, and if you would like to know more examples, check &lt;code&gt;tcpdump&lt;/code&gt; manpage.&lt;/p&gt;

&lt;p&gt;In this step, I'm gonna ignore the part of how SEQ and ACK number work, you could check this [article][ack-number-article] to learn more.&lt;/p&gt;
&lt;h2 id="Step 2: Kernel sends a RST after receiving the SYNACK packet"&gt;Step 2: Kernel sends a RST after receiving the SYNACK packet&lt;/h2&gt;
&lt;p&gt;Julia described this in her article, instead of what we think of how it would work, it didn't.&lt;/p&gt;

&lt;p&gt;&lt;img src="https://l.ruby-china.com/photo/2015/2724410fb8514dfc41c51944531a565c.png" title="" alt=""&gt;&lt;/p&gt;

&lt;p&gt;As the picture shown, after receiving &lt;code&gt;SYNACK&lt;/code&gt; packet from google.com, a &lt;code&gt;RST&lt;/code&gt; packet was sent (obviously not by us).&lt;/p&gt;

&lt;p&gt;I will just quote Julia's explaining here:&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;my Python/Ruby program: SYN
google: SYNACK
my kernel: lol wtf I never asked for this! RST!
my Python/Ruby program: ... :(
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Julia used &lt;code&gt;ARP spoofing&lt;/code&gt; to pretend a different IP address, and someone commented about using tap/tun interfaces instead. I tried the two ways both, but none of them worked for me (maybe my implementations are not good). I struggled to find a way to get my kernel just ignore the packet for, like the whole afternoon. Finally, when I used my nameserver's ip as src_ip in the packet, it worked! I'm not exactly sure how this works, but it fixed my problem. I will leave this as a question and ask some network folks later.&lt;/p&gt;

&lt;p&gt;Now, the three-way handshake works!&lt;/p&gt;

&lt;p&gt;&lt;img src="https://l.ruby-china.com/photo/2015/5da0bc1e5158da1d5bb22a287fc470eb.png" title="" alt=""&gt;&lt;/p&gt;
&lt;h2 id="Step 3: get a web page!"&gt;Step 3: get a web page!&lt;/h2&gt;
&lt;p&gt;This is pretty easy, what we should do is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;send a packet containing a HTTP GET request&lt;/li&gt;
&lt;li&gt;listen for packets in response&lt;/li&gt;
&lt;li&gt;parse the packet&lt;/li&gt;
&lt;li&gt;decide what to do based on tcp flag&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Implementing the last one will cost you some time probably, since it comes down to some parts of [TCP Finite State Machine][tcp-fsm].&lt;/p&gt;

&lt;p&gt;Constructing a HTTP &lt;code&gt;Get&lt;/code&gt; request is quite easy, just include &lt;code&gt;GET some_path HTTP/1.0\r\nHost: hostname\r\n\r\n&lt;/code&gt; in your &lt;code&gt;PSH&lt;/code&gt; packet.&lt;/p&gt;

&lt;p&gt;I use a seperate thread to listen for packets from the destination IP, and after parsing the packet, it will send it to main thread and let it respond based on its state and packet tcp flags.&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Listener&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;initialize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dst_ip&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="vi"&gt;@conn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;conn&lt;/span&gt;
    &lt;span class="vi"&gt;@cap&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;PacketFu&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Capture&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="ss"&gt;iface: &lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:iface&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
      &lt;span class="ss"&gt;start: &lt;/span&gt;&lt;span class="kp"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="ss"&gt;filter: &lt;/span&gt;&lt;span class="s2"&gt;"tcp and dst &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:ip_saddr&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; and src &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;dst_ip&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;listen&lt;/span&gt;
    &lt;span class="vi"&gt;@cap.stream.each&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;pkt&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="vi"&gt;@conn.handle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;PacketFu&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Packet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt; &lt;span class="n"&gt;pkt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="no"&gt;Teeceepee&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;CLOSED_STATE&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;More codes on [GitHub][my-teeceepee], this [tcp.rb][my-teeceepee-tcp-rb] file particularly, advice welcome!&lt;/p&gt;
&lt;h2 id="Sum Up"&gt;Sum Up&lt;/h2&gt;
&lt;p&gt;I'm really glad that I finally give this a try and get it worked. Couldn't say more thanks to Julia for her article and codes, I really learned a lot from them.&lt;/p&gt;

&lt;p&gt;The last time I wrote packets related codes is about 5 or 6 years ago during collegue's networking lesson. Mostly with C language back then. Thanks to &lt;code&gt;PacketFu&lt;/code&gt; gem, I really don't need to some dirty work.&lt;/p&gt;

&lt;p&gt;Anyway, this is much more fun than I expected. The moment it worked I was really beyond happy. Try it with your preferred language, have some fun with me too!&lt;/p&gt;

&lt;p&gt;[julia-twitter]: &lt;a href="https://twitter.com/b0rk" rel="nofollow" target="_blank"&gt;https://twitter.com/b0rk&lt;/a&gt;
[julia-article]: &lt;a href="http://jvns.ca/blog/2014/08/12/what-happens-if-you-write-a-tcp-stack-in-python/" rel="nofollow" target="_blank"&gt;http://jvns.ca/blog/2014/08/12/what-happens-if-you-write-a-tcp-stack-in-python/&lt;/a&gt;
[pocket]: &lt;a href="https://getpocket.com" rel="nofollow" target="_blank"&gt;https://getpocket.com&lt;/a&gt;
[my-teeceepee]: &lt;a href="https://github.com/larrylv/teeceepee" rel="nofollow" target="_blank"&gt;https://github.com/larrylv/teeceepee&lt;/a&gt;
[my-teeceepee-tcp-rb]: &lt;a href="https://github.com/larrylv/teeceepee/blob/master/tcp.rb" rel="nofollow" target="_blank"&gt;https://github.com/larrylv/teeceepee/blob/master/tcp.rb&lt;/a&gt;
[julia-teeceepee]: &lt;a href="https://github.com/jvns/teeceepee/" rel="nofollow" target="_blank"&gt;https://github.com/jvns/teeceepee/&lt;/a&gt;
[packetfu]: &lt;a href="https://github.com/packetfu/packetfu" rel="nofollow" target="_blank"&gt;https://github.com/packetfu/packetfu&lt;/a&gt;
[bpf-syntax]: &lt;a href="http://biot.com/capstats/bpf.html" rel="nofollow" target="_blank"&gt;http://biot.com/capstats/bpf.html&lt;/a&gt;
[ack-number-article]: &lt;a href="http://packetlife.net/blog/2010/jun/7/understanding-tcp-sequence-acknowledgment-numbers/" rel="nofollow" target="_blank"&gt;http://packetlife.net/blog/2010/jun/7/understanding-tcp-sequence-acknowledgment-numbers/&lt;/a&gt;
[tcp-fsm]: &lt;a href="http://www.tcpipguide.com/free/t_TCPOperationalOverviewandtheTCPFiniteStateMachineF-2.htm" rel="nofollow" target="_blank"&gt;http://www.tcpipguide.com/free/t_TCPOperationalOverviewandtheTCPFiniteStateMachineF-2.htm&lt;/a&gt;&lt;/p&gt;</description>
      <author>larrylv</author>
      <pubDate>Fri, 27 Nov 2015 10:31:53 +0800</pubDate>
      <link>https://ruby-china.org/topics/28212</link>
      <guid>https://ruby-china.org/topics/28212</guid>
    </item>
    <item>
      <title>Global Variables in Rails</title>
      <description>&lt;p&gt;Blog: &lt;a href="http://blog.larrylv.com/global-variables-in-rails/" rel="nofollow" target="_blank"&gt;http://blog.larrylv.com/global-variables-in-rails/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In a Rails application, sometimes you may wanna use global variables for every request, with which you don't have to send the object as a parameter everywhere, like &lt;code&gt;current_user&lt;/code&gt; for model layers (which may not be a good idea).&lt;/p&gt;

&lt;p&gt;So how could we do that?&lt;/p&gt;
&lt;h2 id="Ruby Global Variables"&gt;Ruby Global Variables&lt;/h2&gt;
&lt;p&gt;If you know Ruby well, you may know variable with a beginning with &lt;code&gt;$&lt;/code&gt; is global.&lt;/p&gt;

&lt;p&gt;But global variables with &lt;code&gt;$&lt;/code&gt; prefix are supposed to be accessible from every single palce of your code, so they are shared among all threads, and that's definitely not what we want, right?&lt;/p&gt;

&lt;p&gt;So basically, don't use Ruby native global variables, ever.&lt;/p&gt;
&lt;h2 id="Thread.current"&gt;Thread.current&lt;/h2&gt;
&lt;p&gt;So we want our global variables to be thread-safe, a.k.a thread-local.&lt;/p&gt;

&lt;p&gt;This is where &lt;code&gt;Thread&lt;/code&gt; comes in.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Threads are the Ruby implementation for a concurrent programming model.&lt;/p&gt;

&lt;p&gt;Programs that require multiple threads of execution are a perfect candidate for Ruby's Thread class.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;With &lt;a href="http://www.ruby-doc.org/core-2.2.0/Thread.html#method-c-current" rel="nofollow" target="_blank" title=""&gt;Thread.current&lt;/a&gt; method, you could get the currently executing thread. Then you could use &lt;a href="http://www.ruby-doc.org/core-2.2.0/Thread.html#method-i-5B-5D" rel="nofollow" target="_blank" title=""&gt;Thread.[]&lt;/a&gt; and &lt;a href="http://www.ruby-doc.org/core-2.2.0/Thread.html#method-i-5B-5D-3D" rel="nofollow" target="_blank" title=""&gt;Thread.[]=&lt;/a&gt; to get and set thread-local variables, respectively.&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="no"&gt;Thread&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;current&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:current_user&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If you read the links of ruby-doc carefully, you may notice that actually the variable is fiber-local instead of thread-local. Since we rarely use fibers these days, especially for new 2.x Ruby versions, we could assume this is equal to thread-local. But if you do use fibers, and want your variables to be thread-local, please use &lt;code&gt;Thread.thread_variable_set&lt;/code&gt; and &lt;code&gt;Thread.thread_variable_get&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;But there is one problem.&lt;/p&gt;

&lt;p&gt;If you use &lt;code&gt;Thread.current&lt;/code&gt; with fancy evented/threaded web servers like &lt;code&gt;Thin&lt;/code&gt; or &lt;code&gt;Puma&lt;/code&gt;, please watch out! Values can stick around longer that you'd expect, and this can cause bugs. For example, if we had this in our controller:&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;index&lt;/span&gt;
  &lt;span class="no"&gt;Thread&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;current&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:counter&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;||=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
  &lt;span class="no"&gt;Thread&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;current&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:counter&lt;/span&gt;&lt;span class="p"&gt;]&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;render&lt;/span&gt; &lt;span class="ss"&gt;:text&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Thread&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;current&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:counter&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;If we ran this on MRI with Webrick, you'd get &lt;code&gt;1&lt;/code&gt; as output, every time. But if you run it with &lt;code&gt;Thin&lt;/code&gt; or &lt;code&gt;Puma&lt;/code&gt;, you get &lt;code&gt;1&lt;/code&gt;, then &lt;code&gt;2&lt;/code&gt;, then &lt;code&gt;3&lt;/code&gt;...&lt;/p&gt;

&lt;p&gt;So what's the solution?&lt;/p&gt;

&lt;p&gt;Steve Klabnik releases a gem called &lt;a href="https://github.com/steveklabnik/request_store" rel="nofollow" target="_blank" title=""&gt;request_store&lt;/a&gt; to do that for you. Everywhere you used &lt;code&gt;Thread.current&lt;/code&gt;, just change it to &lt;code&gt;RequestStore.store&lt;/code&gt;. And no matter what server you use, you'll get &lt;code&gt;1&lt;/code&gt; every time: the storage is local to that request.&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;index&lt;/span&gt;
  &lt;span class="no"&gt;RequestStore&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;store&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:counter&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;||=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
  &lt;span class="no"&gt;RequestStore&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;store&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:counter&lt;/span&gt;&lt;span class="p"&gt;]&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;render&lt;/span&gt; &lt;span class="ss"&gt;:text&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;RequestStore&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;store&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:counter&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;Codes of the gem are pretty simple, just insert a middleware to Rails and use &lt;code&gt;Thread.current[:request_store]&lt;/code&gt; to store variables, and clear &lt;code&gt;Thread.current[:request_store]&lt;/code&gt; after every request.&lt;/p&gt;

&lt;p&gt;But with &lt;code&gt;Thread.current&lt;/code&gt;(or &lt;code&gt;RequestStore.store&lt;/code&gt;), there are two pains may bother you later:&lt;/p&gt;

&lt;p&gt;1. &lt;strong&gt;Someone could accidentally overwrite your data.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If the other developer picks the same key with yours, and overwrite it somewhere, you app will just break. Or if you are a gem author, that is really something you need to consider.&lt;/p&gt;

&lt;p&gt;2. &lt;strong&gt;It's not well-structured.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Or we could say that it's not very OO. You don't know what's in your &lt;code&gt;Thread.current[]&lt;/code&gt;, and you're gonna have to read every line of codes with &lt;code&gt;Thread.current[]&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;And with these two pains, we may ask: What's the better solution?&lt;/p&gt;
&lt;h2 id="ActiveSupport::PerThreadRegistry"&gt;ActiveSupport::PerThreadRegistry&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;ActiveSupport::PerThreadRegistry&lt;/code&gt; module is used to encapsulate access to thread local variables.&lt;/p&gt;

&lt;p&gt;Instead of polluting the thread locals namespace:&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="no"&gt;Thread&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;current&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:connection_handler&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We could define a class that extends this module:&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="nn"&gt;ActiveRecord&lt;/span&gt;
  &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;RuntimeRegistry&lt;/span&gt;
    &lt;span class="kp"&gt;extend&lt;/span&gt; &lt;span class="no"&gt;ActiveSupport&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;PerThreadRegistry&lt;/span&gt;
    &lt;span class="nb"&gt;attr_accessor&lt;/span&gt; &lt;span class="ss"&gt;:connection_handler&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and invoke the declared instancec accessors as class methods. So&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="no"&gt;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;RuntimeRegistry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connection_handler&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;connection_handler&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;sets a connection handler local to the current thread, and&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="no"&gt;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;RuntimeRegistry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connection_handler&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;returns a connection handler local to the current thread.&lt;/p&gt;

&lt;p&gt;This feature is accomplished by instantiating the class and storing the instance as a thread local keyed by the class name. In the example above a key "ActiveRecord::RuntimeRegistry" is stored in &lt;code&gt;Thread.current&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The implementation is pretty simple, too. See the codes here: &lt;a href="https://github.com/rails/rails/blob/v4.2.0/activesupport/lib/active_support/per_thread_registry.rb" rel="nofollow" target="_blank" title=""&gt;module PerThreadRegistry&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;With &lt;code&gt;PerThreadRegistry&lt;/code&gt; module, the previous pains concerning you are gone.&lt;/p&gt;

&lt;p&gt;As to the previous &lt;code&gt;RequestStore&lt;/code&gt; problem, someone provides a &lt;a href="https://github.com/scarfacedeb/request_store_registry" rel="nofollow" target="_blank" title=""&gt;solution&lt;/a&gt;, or you could just hack it yourself. It's quite simple.&lt;/p&gt;
&lt;h2 id="Wrap It Up"&gt;Wrap It Up&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Don't ever use Ruby native global variables.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;Thread.current&lt;/code&gt; could do it, but it's not good for complicated apps or codes of a gem.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Clear thread local variables after every request, or it may stick around longer than you'd expect.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Use &lt;code&gt;ActiveSupport::PerThreadRegistry&lt;/code&gt; for better global variables management and document.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="References"&gt;References&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://www.ruby-doc.org/core-2.2.0/Thread.html" rel="nofollow" target="_blank" title=""&gt;Thread in Ruby Doc&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/steveklabnik/request_store" rel="nofollow" target="_blank" title=""&gt;RequestStore&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://www.justinweiss.com/blog/2014/12/01/better-globals-with-a-tiny-activesupport-module/" rel="nofollow" target="_blank" title=""&gt;Better Globals With a Tiny ActiveSupport Module&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/scarfacedeb/request_store_registry" rel="nofollow" target="_blank" title=""&gt;RequestStoreRegistry&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <author>larrylv</author>
      <pubDate>Fri, 26 Dec 2014 14:59:10 +0800</pubDate>
      <link>https://ruby-china.org/topics/23420</link>
      <guid>https://ruby-china.org/topics/23420</guid>
    </item>
    <item>
      <title>How Did Tenderlove and Others Speed Up Rails?</title>
      <description>&lt;p&gt;Blog Link: &lt;a href="http://blog.larrylv.com/how-did-tenderlove-and-others-speed-up-rails/" rel="nofollow" target="_blank" title=""&gt;http://blog.larrylv.com/how-did-tenderlove-and-others-speed-up-rails/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Rails 4.2.0 beta1 was released August 20, 2014. And according to &lt;a href="http://weblog.rubyonrails.org/2014/8/20/Rails-4-2-beta1/" rel="nofollow" target="_blank" title=""&gt;dhh's release post&lt;/a&gt;, and I quote,&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;a lot of common queries are now no less than twice as fast in Rails 4.2!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So, what did Rails team -- or more specifically -- &lt;a href="https://github.com/tenderlove" rel="nofollow" target="_blank" title=""&gt;tenderlove (Aaron Patterson)&lt;/a&gt; do to improve Rails/ActiveRecord so much? Let's find out through some commits.&lt;/p&gt;
&lt;h2 id="Performance Tools"&gt;Performance Tools&lt;/h2&gt;
&lt;p&gt;Here are some tools Aaron has used for measuring performance according to his &lt;a href="https://www.youtube.com/watch?v=NKs1PjkheQY" rel="nofollow" target="_blank" title=""&gt;Cascadia Ruby 2014 talk&lt;/a&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/evanphx/benchmark-ips" rel="nofollow" target="_blank" title=""&gt;benchmark-ips&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/tmm1/stackprof" rel="nofollow" target="_blank" title=""&gt;stackprof&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/ko1/allocation_tracer" rel="nofollow" target="_blank" title=""&gt;allocation_tracer&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://ruby-doc.org/core-2.1.3/TracePoint.html" rel="nofollow" target="_blank" title=""&gt;TracePoint&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://ruby-doc.org/core-2.1.3/GC.html#method-c-stat" rel="nofollow" target="_blank" title=""&gt;GC.stat&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You should definitely checkout these tools. It would be very useful in your daily Ruby/Rails development.&lt;/p&gt;


&lt;h2 id="GitHub Commit: drastically reduce object allocations "&gt;GitHub Commit: &lt;a href="https://github.com/rails/rails/commit/8899503f62a556a918c45b3e7b5c2effaaa943f4" rel="nofollow" target="_blank" title=""&gt;drastically reduce object allocations &lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Inside the &lt;a href="https://github.com/rails/rails/blob/v4.1.6.rc2/actionview/lib/action_view/helpers/tag_helper.rb#L171-L172" rel="nofollow" target="_blank" title=""&gt;tag_option&lt;/a&gt; method, the &lt;code&gt;value&lt;/code&gt; variable was html escaped first, then interpolated into a string.&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;tag_option&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;escape&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;" "&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;is_a?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;ERB&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Util&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;h&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;escape&lt;/span&gt; &lt;span class="c1"&gt;# html escaped here&lt;/span&gt;
    &lt;span class="sx"&gt;%(&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sx"&gt;="&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sx"&gt;")&lt;/span&gt;                 &lt;span class="c1"&gt;# interpolated into a string here.&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And if digging into &lt;a href="https://github.com/rails/rails/blob/v4.1.6.rc2/activesupport/lib/active_support/core_ext/string/output_safety.rb#L25" rel="nofollow" target="_blank" title=""&gt;html_escape (alias as h)&lt;/a&gt; method, we will see that there will be a AS::SafeBuffer object allocated:&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;html_escape&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_s&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;html_safe?&lt;/span&gt;
        &lt;span class="n"&gt;s&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;
        &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;gsub&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;HTML_ESCAPE_REGEXP&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;HTML_ESCAPE&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;html_safe&lt;/span&gt; &lt;span class="c1"&gt;# a String allocated first(by String#gsub),&lt;/span&gt;
                                                           &lt;span class="c1"&gt;# then a SafeBuffer object allocated.&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So for &lt;code&gt;tag_option&lt;/code&gt;, there will always be an AS::SafeBuffer useless object allocated. This could be solved by adding another escape method but doesn't wrap string with an AS::SafeBuffer. And &lt;code&gt;tag_option&lt;/code&gt; should call that method instead of the old one.&lt;/p&gt;

&lt;p&gt;&lt;img src="https://l.ruby-china.com/photo/2014/4912e015dee5a00ad9b96cc5ada6b544.png" title="" alt=""&gt;&lt;/p&gt;

&lt;p&gt;And this tiny change reduced the AS::SafeBuffer objects from 1527 per request to about 500 per request according to Aaron's benchmark. It is trully drastically, awesome!&lt;/p&gt;
&lt;h2 id="GitHub Commit: No need for another hash allocation / merge! "&gt;GitHub Commit: &lt;a href="https://github.com/rails/rails/commit/ea7fc2e7c0aba43b0c54309d292d982e52ee1b3d" rel="nofollow" target="_blank" title=""&gt;No need for another hash allocation / merge! &lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;This commit is very simple, but it should really attrack our attention when writing Ruby codes.&lt;/p&gt;

&lt;p&gt;&lt;img src="https://l.ruby-china.com/photo/2014/732b90c93c3a90686459c9d53f0aab9a.png" title="" alt=""&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Hash#merge!&lt;/code&gt; will allocate a new hash, but with &lt;code&gt;Hash#[]&lt;/code&gt; this would not happen. And accoriding to my benchmark(I wrote a blog about &lt;a href="http://blog.larrylv.com/performance-differences-in-ruby/" rel="nofollow" target="_blank" title=""&gt;Performance Differences in Ruby&lt;/a&gt;, you may would like to check it out) , it really matters.&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;slow&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;10&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;inject&lt;/span&gt;&lt;span class="p"&gt;({})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;merge!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;e&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="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;fast&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;10&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;inject&lt;/span&gt;&lt;span class="p"&gt;({})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;h&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="o"&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;h&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;pre class="highlight plaintext"&gt;&lt;code&gt;slow    72613.7 (±9.9%) i/s -     364662 in   5.082934s
fast   158245.6 (±7.1%) i/s -     796005 in   5.056857s
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;There are a large number of commits like this in Rails repo recently (because performance really matters, right?).&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/rails/rails/commit/5e181ed0aeb829510f1c739a7dcc8328d2675258" rel="nofollow" target="_blank" title=""&gt;Fewer hash allocations when calling url_for&lt;/a&gt; by Aaron.&lt;/li&gt;
&lt;li&gt;This &lt;a href="https://github.com/rails/rails/commit/e2b49b203f2cb6cef93283f14838f21bf6ffb4a2" rel="nofollow" target="_blank" title=""&gt;commit&lt;/a&gt; by &lt;a href="https://github.com/sferik" rel="nofollow" target="_blank" title=""&gt;&lt;/a&gt;&lt;a href="/sferik" class="user-mention" title="@sferik"&gt;&lt;i&gt;@&lt;/i&gt;sferik&lt;/a&gt;, changing &lt;code&gt;Hash#keys.each&lt;/code&gt; to &lt;code&gt;Hash#each_key&lt;/code&gt;. Because &lt;code&gt;Hash#keys.each&lt;/code&gt; will allocate an array of keys, but &lt;code&gt;Hash#each_key&lt;/code&gt; iterates through the keys without allocating a new array. I also benchmark on this in my article I mentioned above.&lt;/li&gt;
&lt;li&gt;And this &lt;a href="https://github.com/rails/rails/commit/c363fff29f060e6a2effe1e4bb2c4dd4cd805d6e" rel="nofollow" target="_blank" title=""&gt;commit&lt;/a&gt; by Aaron is also the same, use &lt;code&gt;Hash#each_key&lt;/code&gt; to avoid some objects allocation.&lt;/li&gt;
&lt;li&gt;Or this &lt;a href="https://github.com/rails/rails/pull/17093" rel="nofollow" target="_blank" title=""&gt;one&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://github.com/sferik" rel="nofollow" target="_blank" title=""&gt;&lt;/a&gt;&lt;a href="/sferik" class="user-mention" title="@sferik"&gt;&lt;i&gt;@&lt;/i&gt;sferik&lt;/a&gt; gave a talk about these skills at Baruco 2014, and he is also who made me want to blog and benchmark these in my article. The video has not been released, but you should definitely check out his slides &lt;a href="https://speakerdeck.com/sferik/writing-fast-ruby" rel="nofollow" target="_blank" title=""&gt;Writing Fast Ruby&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="GitHub Commit: reduce object allocations"&gt;GitHub Commit: &lt;a href="https://github.com/rails/rails/commit/931ee4186b877856b212b0085cd7bd7f6a4aea67" rel="nofollow" target="_blank" title=""&gt;reduce object allocations&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;This commit is basically same with the previous one. It's about performance differences on how to use &lt;code&gt;Hash#zip&lt;/code&gt;. And Aaron's commit message explains it all.&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;x&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="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;
  &lt;span class="nb"&gt;hash&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
  &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;zip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;v&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="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nb"&gt;hash&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test2&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;
  &lt;span class="no"&gt;Hash&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;zip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test3&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;
  &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;zip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;each_with_object&lt;/span&gt;&lt;span class="p"&gt;({})&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="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&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="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;stat&lt;/span&gt; &lt;span class="n"&gt;num&lt;/span&gt;
  &lt;span class="n"&gt;start&lt;/span&gt; &lt;span class="o"&gt;=&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;stat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:total_allocated_object&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;num&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="k"&gt;yield&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="n"&gt;total_obj_count&lt;/span&gt; &lt;span class="o"&gt;=&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;stat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:total_allocated_object&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt;
  &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;total_obj_count&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; allocations per call"&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;stat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nb"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;stat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;test2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;stat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;test3&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="cp"&gt;__END__
2 allocations per call
7 allocations per call
8 allocations per call
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="Sum Up"&gt;Sum Up&lt;/h2&gt;
&lt;p&gt;When somenone outsite of Ruby/Rails community talks bout Rails, the performance will always be brought to the conversation. And it really concerns developers when choosing tools to build their apps. After giving so much attention to impove it, we could say Rails is getting faster and Rails will be much more faster later.&lt;/p&gt;

&lt;p&gt;So thanks to everyone who has contributed to Rails performance improvement, you guys make this community better and better.&lt;/p&gt;

&lt;p&gt;&lt;img title=":heart:" alt="❤" src="https://twemoji.ruby-china.com/2/svg/2764.svg" class="twemoji"&gt;&lt;/p&gt;</description>
      <author>larrylv</author>
      <pubDate>Wed, 08 Oct 2014 16:19:48 +0800</pubDate>
      <link>https://ruby-china.org/topics/21922</link>
      <guid>https://ruby-china.org/topics/21922</guid>
    </item>
    <item>
      <title>Performance Differences in Ruby</title>
      <description>&lt;p&gt;&lt;a href="http://blog.larrylv.com/performance-differences-in-ruby/" rel="nofollow" target="_blank"&gt;http://blog.larrylv.com/performance-differences-in-ruby/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="http://parley.rubyrogues.com/t/dramatic-performance-differences-in-ruby/2151" rel="nofollow" target="_blank"&gt;http://parley.rubyrogues.com/t/dramatic-performance-differences-in-ruby/2151&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;前几天 &lt;a href="/sferik" class="user-mention" title="@sferik"&gt;&lt;i&gt;@&lt;/i&gt;sferik&lt;/a&gt; 在 Parley 上说最近在准备一个关于 Performance in Ruby 的 talk，发贴讨论了 Ruby 中哪些写法会造成性能的巨大提升，我顺手整理了下帖子内容并实验了一下。&lt;/p&gt;

&lt;p&gt;Benchmark 环境：MacBook Air Mid 2012, Ruby 2.1.1, gem &lt;code&gt;benchmark-ips&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id="Proc#call versus yield"&gt;Proc#call versus yield&lt;/h2&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'benchmark/ips'&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;slow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;block&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;block&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;fast&lt;/span&gt;
  &lt;span class="k"&gt;yield&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="no"&gt;Benchmark&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ips&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;x&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;report&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"slow"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;slow&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;1&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;report&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"fast"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;fast&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;1&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;/code&gt;&lt;/pre&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;slow   770263.8 (±4.8%) i/s -    3849832 in   5.010201s (5 秒钟可运行 3849832 次)
fast  3985294.7 (±8.7%) i/s -   19751563 in   5.001024s (5 秒钟可运行 19751563 次)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;从上面的 benchmark 结果中可以看出两种写法的显著性能差异，这主要是因为第一种写法中要不断的创建 Proc 对象赋给 block 参数导致的。&lt;/p&gt;
&lt;h2 id="Enumerable#map and Array#flatten versus Enumerable#flat_map"&gt;Enumerable#map and Array#flatten versus Enumerable#flat_map&lt;/h2&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;slow&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;50&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;i&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;divmod&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;7&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;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;fast&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;50&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;flat_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;i&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;divmod&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;7&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;/code&gt;&lt;/pre&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;slow   32514.2 (±6.8%) i/s -     162134 in   5.014068s
fast    57858.6 (±7.3%) i/s -     292463 in   5.084633s
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="Hash#merge versus Hash#merge! (bang methods, in general)"&gt;Hash#merge versus Hash#merge! (bang methods, in general)&lt;/h2&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;slow&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;10&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;inject&lt;/span&gt;&lt;span class="p"&gt;({})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;merge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;e&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="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;fast&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;10&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;inject&lt;/span&gt;&lt;span class="p"&gt;({})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;merge!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;e&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;/code&gt;&lt;/pre&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;slow    22054.4 (±6.3%) i/s -     110081 in   5.012558s
fast     75393.0 (±9.3%) i/s -     375577 in   5.028409s
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="Hash#merge! versus Hash#[]="&gt;Hash#merge! versus Hash#[]=&lt;/h2&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;slow&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;10&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;inject&lt;/span&gt;&lt;span class="p"&gt;({})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;merge!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;e&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="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;fast&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;10&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;inject&lt;/span&gt;&lt;span class="p"&gt;({})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;h&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="o"&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;h&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;pre class="highlight plaintext"&gt;&lt;code&gt;slow    72613.7 (±9.9%) i/s -     364662 in   5.082934s
fast   158245.6 (±7.1%) i/s -     796005 in   5.056857s
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="Hash#fetch with second argument versus Hash#fetch with block"&gt;Hash#fetch with second argument versus Hash#fetch with block&lt;/h2&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;slow&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:foo&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="ss"&gt;:bar&lt;/span&gt;&lt;span class="p"&gt;}.&lt;/span&gt;&lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:foo&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="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;to_a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;fast&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:foo&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="ss"&gt;:bar&lt;/span&gt;&lt;span class="p"&gt;}.&lt;/span&gt;&lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:foo&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="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;to_a&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;pre class="highlight plaintext"&gt;&lt;code&gt;slow   412806.8 (±11.2%) i/s -    2037520 in   5.009145s
fast  1134439.1  (±8.1%) i/s -    5662160 in   5.027080s
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="String#gsub versus String#sub"&gt;String#gsub versus String#sub&lt;/h2&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;slow&lt;/span&gt;
  &lt;span class="s1"&gt;'http://parley.rubyrogues.com/'&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;gsub&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;%r{&lt;/span&gt;&lt;span class="se"&gt;\A&lt;/span&gt;&lt;span class="sr"&gt;http://}&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'https://'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;fast&lt;/span&gt;
  &lt;span class="s1"&gt;'http://parley.rubyrogues.com/'&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sub&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;%r{&lt;/span&gt;&lt;span class="se"&gt;\A&lt;/span&gt;&lt;span class="sr"&gt;http://}&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'https://'&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;pre class="highlight plaintext"&gt;&lt;code&gt;slow   237660.4 (±5.0%) i/s -    1190664 in   5.023559s
fast   320335.6 (±5.1%) i/s -    1614839 in   5.055553s
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="String#gsub versus String#tr"&gt;String#gsub versus String#tr&lt;/h2&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;slow&lt;/span&gt;
  &lt;span class="s1"&gt;'slug from title'&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;gsub&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;' '&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'_'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;fast&lt;/span&gt;
  &lt;span class="s1"&gt;'slug from title'&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;tr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;' '&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&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;pre class="highlight plaintext"&gt;&lt;code&gt;slow   187349.7 (±6.8%) i/s -     933140 in   5.012634s
fast  1216071.5 (±8.9%) i/s -    6050762 in   5.024810s
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="Parallel versus sequential assignment"&gt;Parallel versus sequential assignment&lt;/h2&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;slow&lt;/span&gt;
  &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&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="mi"&gt;2&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;fast&lt;/span&gt;
  &lt;span class="n"&gt;a&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;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;slow   189642.1 (±7.6%) i/s -     947520 in   5.031411s
fast  1180907.4 (±7.1%) i/s -    5872020 in   5.002410s
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="Explicit versus implicit String concatenation"&gt;Explicit versus implicit String concatenation&lt;/h2&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;slow&lt;/span&gt;
  &lt;span class="s2"&gt;"foo"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s2"&gt;"bar"&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;fast&lt;/span&gt;
  &lt;span class="s2"&gt;"foo"&lt;/span&gt; &lt;span class="s2"&gt;"bar"&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;slow  1998832.8 (±5.5%) i/s -    9974259 in   5.005887s
fast  3559754.8 (±6.8%) i/s -   17747928 in   5.012536s
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="Using exceptions for control flow"&gt;Using exceptions for control flow&lt;/h2&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;slow&lt;/span&gt;
  &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;no_method&lt;/span&gt;
&lt;span class="k"&gt;rescue&lt;/span&gt; &lt;span class="no"&gt;NoMethodError&lt;/span&gt;
  &lt;span class="s2"&gt;"doh!"&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;fast&lt;/span&gt;
  &lt;span class="nb"&gt;respond_to?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:no_method&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;no_method&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"doh!"&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;slow   194665.7 (±10.9%) i/s -     963144 in   5.029578s
fast  2248844.0  (±6.1%) i/s -   11241017 in   5.020091s
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="while loops versus each_with_index"&gt;while loops versus each_with_index&lt;/h2&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="no"&gt;ARRAY&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="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'2'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'5'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s1"&gt;'10'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;slow&lt;/span&gt;
  &lt;span class="nb"&gt;hash&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

  &lt;span class="no"&gt;ARRAY&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each_with_index&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;item&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;index&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="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="nb"&gt;hash&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;fast&lt;/span&gt;
  &lt;span class="nb"&gt;hash&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
  &lt;span class="n"&gt;index&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
  &lt;span class="n"&gt;length&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;ARRAY&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;length&lt;/span&gt;

  &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;length&lt;/span&gt;
    &lt;span class="nb"&gt;hash&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;ARRAY&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;index&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="nb"&gt;hash&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;slow   147515.1 (±9.6%) i/s -     734100 in   5.038291s
fast   183634.1 (±6.5%) i/s -     918335 in   5.023060s
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Related Pull Request for ActiveRecord: &lt;a href="https://github.com/rails/rails/pull/12065" rel="nofollow" target="_blank" title=""&gt;Perf: micro optimised Result column hash_row creation&lt;/a&gt;&lt;/p&gt;</description>
      <author>larrylv</author>
      <pubDate>Mon, 12 May 2014 23:30:36 +0800</pubDate>
      <link>https://ruby-china.org/topics/19207</link>
      <guid>https://ruby-china.org/topics/19207</guid>
    </item>
  </channel>
</rss>
