<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="pretty-feed.xsl" type="text/xsl"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>ivo's awfully random tech blog</title>
    <description>where i document my tech hacks, experiments and discoveries</description>
    <link>https://ivoanjo.me/</link>
    <atom:link href="https://ivoanjo.me/feed.xml" rel="self" type="application/rss+xml"/>
    <pubDate>Sun, 05 Apr 2026 11:41:13 +0100</pubDate>
    <lastBuildDate>Sun, 05 Apr 2026 11:41:13 +0100</lastBuildDate>
    <generator>Jekyll v4.4.1</generator>
    
      <item>
        <title>Low-level Ruby observability APIs</title>
        <description>&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;When we need to understand what&amp;#8217;s going on with our application, it&amp;#8217;s common to (&lt;a href=&quot;https://tenderlovemaking.com/2016/02/05/i-am-a-puts-debuggerer/&quot;&gt;beyond using &lt;code&gt;puts&lt;/code&gt; 😉&lt;/a&gt;) turn to observability tools: tools such as debuggers, profilers, and monitoring tools.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;But have you ever wondered how they work? These tools often require access to Ruby internals that regular Ruby libraries or applications don&amp;#8217;t have (or need).
Language runtimes such as the CRuby VM (or the Java VM!) often put in limits on what applications can do, so as to ensure the memory safety, security and integrity of applications.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;To support use-cases from observability tools, the CRuby VM has a number of low-level APIs that can be used to know more about such things as the state of threads, the global VM lock, object creation, garbage collection, etc. These APIs are:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/ruby/ruby/blob/master/include/ruby/debug.h&quot;&gt;&lt;code&gt;include/ruby/debug.h&lt;/code&gt;&lt;/a&gt;: TracePoint, postponed job, frame-profiling, debug inspector APIs&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/ruby/ruby/blob/master/include/ruby/debug.h&quot;&gt;&lt;code&gt;include/ruby/thread.h&lt;/code&gt;&lt;/a&gt;: GVL instrumentation, thread specific storage APIs&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;These APIs are provided only to native extensions, and you usually need to write some C code to access them. That usually means a higher barrier of entry to start experimenting with them. And that&amp;#8217;s not fun ;)&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;To fix that, I recently created (another!) Ruby gem, called &lt;a href=&quot;https://github.com/ivoanjo/lowlevel-toolkit&quot;&gt;&lt;code&gt;lowlevel-toolkit&lt;/code&gt;&lt;/a&gt;.
The objective of this gem, as the name suggests, is to both provide a toolbox of small observability tools that probably would be too small to release independently, &lt;strong&gt;as well as provide a starting point and living example to quickly get started in experimenting with Ruby observability APIs&lt;/strong&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;As of this writing, the gem provides the following tools, that each make use of the APIs listed above:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;track_wants_gvl&lt;/code&gt;: Track when threads want to acquire the Global VM Lock&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;track_objects_created&lt;/code&gt;: Monitor object creation in your application&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;last_allocation_at&lt;/code&gt;: Get information about the last object allocation&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;on_gc_finish&lt;/code&gt;: Set up callbacks for when garbage collection finishes&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;who_called_me&lt;/code&gt;: Track the call stack of method invocations&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;release_gvl_profiler&lt;/code&gt;: Profile GVL release patterns&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;You can start using these tools today! Or, if you want to learn more and create your own tools, at the RubyKaigi 2025 conference I did a deep dive on each of these tools, and how the APIs they rely on work:&lt;/p&gt;
&lt;/div&gt;
&lt;iframe width=&quot;736&quot; height=&quot;420&quot; src=&quot;https://www.youtube.com/embed/nSdkM-PEL6c?si=xEWCw0Aw15umrMaQ&quot; title=&quot;YouTube video player&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; referrerpolicy=&quot;strict-origin-when-cross-origin&quot; allowfullscreen&gt;&lt;/iframe&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Slide deck:&lt;/p&gt;
&lt;/div&gt;
&lt;iframe src=&quot;https://docs.google.com/presentation/d/e/2PACX-1vQUAe3XmybGTRHKEt9Mh82ukwj67cxFnS5gAze-081HbVjAR6Ph5AdMm6yrtkFkX0oU1O7j-xUnS7dU/embed?start=false&amp;loop=false&amp;delayms=3000&quot; frameborder=&quot;0&quot; width=&quot;736&quot; height=&quot;443&quot; allowfullscreen=&quot;true&quot; mozallowfullscreen=&quot;true&quot; webkitallowfullscreen=&quot;true&quot;&gt;&lt;/iframe&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Please do share what weird bugs you debugged and experiments you made with these APIs. I think the more people poking at these tools, the more we make it easier for everyone to understand what their Ruby apps are up to!&lt;/p&gt;
&lt;/div&gt;</description>
        <pubDate>Sat, 12 Jul 2025 00:00:00 +0100</pubDate>
        <link>https://ivoanjo.me/blog/2025/07/12/lowlevel-toolkit-ruby-gem/</link>
        <guid isPermaLink="true">https://ivoanjo.me/blog/2025/07/12/lowlevel-toolkit-ruby-gem/</guid>
        <category>blog</category>
      </item>
      <item>
        <title>Talking Ruby GVL, Scheduling and Performance on the Dead Code podcast</title>
        <description>&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;I&amp;#8217;m pretty happy that I got to go on the Dead Code podcast. In this episode, we discussed how the Ruby Global VM Lock (GVL) got to be and why it&amp;#8217;s needed, went deep into scheduling&amp;#8201;&amp;#8212;&amp;#8201;how to tweak how much time Ruby gives each thread; how M:N scheduling changes the behavior of threads in Ruby; and how Ruby may need a full scheduler and why.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;We also discuss how tools such as gvl-tracing can be used to identify performance bugs (including in Ruby itself!), the &lt;a href=&quot;/blog/2025/06/15/direct-bind-ruby-gem/&quot;&gt;&lt;code&gt;direct-bind&lt;/code&gt; gem I recently created&lt;/a&gt;, and how it&amp;#8217;s amazing people are starting to forget that Ruby is &quot;supposed&quot; to be slow and actually there&amp;#8217;s been great progress in improving performance.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;You can &lt;a href=&quot;https://sphinx.acast.com/p/open/s/65de32896569fa0017d17653/e/6862fb7a9951fac41b18bca0/media.mp3&quot;&gt;download the episode as an mp3&lt;/a&gt; or listen to it online:&lt;/p&gt;
&lt;/div&gt;
&lt;iframe src=&quot;https://embed.acast.com/$/65de32896569fa0017d17653/eat-your-greens-with-ivo-anjo?&quot; frameBorder=&quot;0&quot; width=&quot;100%&quot; height=&quot;110px&quot; allow=&quot;autoplay&quot;&gt;&lt;/iframe&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;As always, feedback is welcome!&lt;/p&gt;
&lt;/div&gt;</description>
        <pubDate>Sun, 06 Jul 2025 00:00:00 +0100</pubDate>
        <link>https://ivoanjo.me/blog/2025/07/06/ruby-gvl-scheduling-podcast/</link>
        <guid isPermaLink="true">https://ivoanjo.me/blog/2025/07/06/ruby-gvl-scheduling-podcast/</guid>
        <category>blog</category>
      </item>
      <item>
        <title>native-filenames: Find out where native methods are defined in Ruby</title>
        <description>&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;I&amp;#8217;ve just released the first version of the &lt;a href=&quot;https://github.com/ivoanjo/native-filenames/&quot;&gt;&lt;code&gt;native-filenames&lt;/code&gt;&lt;/a&gt; Ruby gem.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;This gem can be used to probe where a native extension was defined. Here&amp;#8217;s a quick example of how to use it:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;CodeRay highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;[&lt;span style=&quot;color:#00D&quot;&gt;1&lt;/span&gt;] pry(main)&amp;gt; require &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;native-filenames&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;

&lt;span style=&quot;color:#777&quot;&gt;# Modern versions of bigdecimal use a native extension:&lt;/span&gt;
[&lt;span style=&quot;color:#00D&quot;&gt;2&lt;/span&gt;] pry(main)&amp;gt; require &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;bigdecimal&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;
[&lt;span style=&quot;color:#00D&quot;&gt;3&lt;/span&gt;] pry(main)&amp;gt; &lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;NativeFilenames&lt;/span&gt;.filename_for(&lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;BigDecimal&lt;/span&gt;.singleton_class, &lt;span style=&quot;color:#A60&quot;&gt;:save_rounding_mode&lt;/span&gt;)
=&amp;gt; &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;/rvm/gems/ruby-3.4.4/gems/bigdecimal-3.2.2/lib/bigdecimal.so&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;

&lt;span style=&quot;color:#777&quot;&gt;# Can also enquire about the standard library:&lt;/span&gt;
[&lt;span style=&quot;color:#00D&quot;&gt;4&lt;/span&gt;] pry(main)&amp;gt; &lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;NativeFilenames&lt;/span&gt;.filename_for(&lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;Array&lt;/span&gt;, &lt;span style=&quot;color:#A60&quot;&gt;:each&lt;/span&gt;)
=&amp;gt; &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;/rvm/rubies/ruby-3.4.4/bin/../lib/libruby.so.3.4&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;

&lt;span style=&quot;color:#777&quot;&gt;# If something is written in Ruby, then you get an error:&lt;/span&gt;
[&lt;span style=&quot;color:#00D&quot;&gt;5&lt;/span&gt;] pry(main)&amp;gt; &lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;NativeFilenames&lt;/span&gt;.filename_for(&lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;Pry&lt;/span&gt;.singleton_class, &lt;span style=&quot;color:#A60&quot;&gt;:start&lt;/span&gt;)
&lt;span style=&quot;color:#606&quot;&gt;RuntimeError&lt;/span&gt;: direct_bind_get_cfunc &lt;span style=&quot;color:#606&quot;&gt;failed&lt;/span&gt;: method_entry is &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;not&lt;/span&gt; a cfunc (&lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;RuntimeError&lt;/span&gt;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;I&amp;#8217;ve just proposed to the Ruby core team that this behavior be incorporated in backtraces by default. (P.s.: This is now the behavior of the &lt;a href=&quot;https://github.com/DataDog/dd-trace-rb/pull/4745&quot;&gt;Datadog Ruby Profiler, starting with release 2.18.0&lt;/a&gt;.)&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;That is, given this example:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;CodeRay highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;require &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;bigdecimal&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;

&lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;BigDecimal&lt;/span&gt;.singleton_class.prepend(
  &lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;Module&lt;/span&gt;.new &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;do&lt;/span&gt;
    &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color:#06B;font-weight:bold&quot;&gt;save_rounding_mode&lt;/span&gt;
      &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;super&lt;/span&gt;
    &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;end&lt;/span&gt;
  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;end&lt;/span&gt;
)

[&lt;span style=&quot;color:#A60&quot;&gt;:example&lt;/span&gt;].each &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;do&lt;/span&gt;
  &lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;BigDecimal&lt;/span&gt;.save_rounding_mode &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;do&lt;/span&gt;
    puts caller
    sleep &lt;span style=&quot;color:#00D&quot;&gt;1&lt;/span&gt;
  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;end&lt;/span&gt;
&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;you&amp;#8217;d see this with Ruby 3.4:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;CodeRay highlight&quot;&gt;&lt;code&gt;native-filenames-example.rb:6:in &apos;BigDecimal.save_rounding_mode&apos;
native-filenames-example.rb:6:in &apos;save_rounding_mode&apos;
native-filenames-example.rb:12:in &apos;block in &amp;lt;main&amp;gt;&apos;
native-filenames-example.rb:11:in &apos;Array#each&apos;
native-filenames-example.rb:11:in &apos;&amp;lt;main&amp;gt;&apos;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;but I&amp;#8217;m hoping that in Ruby 3.5 it&amp;#8217;ll become:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;CodeRay highlight&quot;&gt;&lt;code&gt;/rvm/gems/ruby-3.4.4/gems/bigdecimal-3.2.2/lib/bigdecimal.so:0:in &apos;BigDecimal.save_rounding_mode&apos;
native-filenames-example.rb:6:in &apos;save_rounding_mode&apos;
native-filenames-example.rb:12:in &apos;block in &amp;lt;main&amp;gt;&apos;
/rvm/rubies/ruby-3.4.4/lib/libruby.so.3.4:0:in &apos;Array#each&apos;
native-filenames-example.rb:11:in &apos;&amp;lt;main&amp;gt;&apos;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;If you&amp;#8217;re interested in the discussion, it&amp;#8217;s up on &lt;a href=&quot;https://bugs.ruby-lang.org/issues/21501&quot; class=&quot;bare&quot;&gt;https://bugs.ruby-lang.org/issues/21501&lt;/a&gt;. Feedback very welcome!&lt;/p&gt;
&lt;/div&gt;</description>
        <pubDate>Sat, 05 Jul 2025 00:00:00 +0100</pubDate>
        <link>https://ivoanjo.me/blog/2025/07/05/native-filenames-ruby-gem/</link>
        <guid isPermaLink="true">https://ivoanjo.me/blog/2025/07/05/native-filenames-ruby-gem/</guid>
        <category>blog</category>
      </item>
      <item>
        <title>I wrote another weird ruby gem: direct-bind</title>
        <description>&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;I&amp;#8217;ve written another weird Ruby gem: &lt;a href=&quot;https://github.com/ivoanjo/direct-bind&quot;&gt;&lt;code&gt;direct-bind&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;It solves a very specific problem I keep running into. It&amp;#8217;s oddly specific, so I may actually be alone in this ;)&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;As I find myself working on Ruby observability tools such as &lt;a href=&quot;https://github.com/DataDog/dd-trace-rb&quot;&gt;the profiler in the &lt;code&gt;datadog&lt;/code&gt; gem&lt;/a&gt;, or &lt;a href=&quot;https://github.com/ivoanjo/gvl-tracing/&quot;&gt;the &quot;show your Ruby threads in a timeline&quot; &lt;code&gt;gvl-tracing&lt;/code&gt; gem&lt;/a&gt; or &lt;a href=&quot;https://github.com/ivoanjo/backtracie&quot;&gt;the &quot;build richer stack traces&quot; &lt;code&gt;backtracie&lt;/code&gt; gem&lt;/a&gt; I often mentally ask: &lt;em&gt;Ok, so how do I get X piece of information from Ruby? Is there an API for it?&lt;/em&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;This thought often leads me to use tools such as &lt;code&gt;readelf&lt;/code&gt; to check what functions Ruby exposes as public (&quot;GLOBAL&quot;):&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre&gt;$ readelf -sW libruby.so.3.4.4 | grep GLOBAL | grep &quot;rb_thread_&quot;
   341: 00000000002e5220    82 FUNC    GLOBAL DEFAULT   12 rb_thread_alone
   400: 00000000002e7540   475 FUNC    GLOBAL DEFAULT   12 rb_thread_sleep_deadly
   471: 00000000002e7ff0    11 FUNC    GLOBAL DEFAULT   12 rb_thread_io_blocking_region
   515: 00000000002ea870    56 FUNC    GLOBAL DEFAULT   12 rb_thread_stop
   559: 00000000002e1f00   140 FUNC    GLOBAL DEFAULT   12 rb_thread_lock_native_thread
   582: 00000000002e1cf0   101 FUNC    GLOBAL DEFAULT   12 rb_thread_prevent_fork
   650: 00000000002e5050   139 FUNC    GLOBAL DEFAULT   12 rb_thread_local_aref
   767: 00000000002ea830    25 FUNC    GLOBAL DEFAULT   12 rb_thread_run
   777: 00000000002ea7d0    84 FUNC    GLOBAL DEFAULT   12 rb_thread_schedule

...etc&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;and to spend a bunch of time reading the Ruby VM sources to find which functions exist and how I can access them.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;But sometimes the function I need is right&amp;#8230;&amp;#8203; there&amp;#8230;&amp;#8203; but Ruby does not expose it as a public function (&quot;LOCAL&quot;):&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre&gt;$ readelf -sW libruby.so.3.4.4 |  grep &quot;rb_thread_alive&quot;
  5585: 00000000002db070    63 FUNC    LOCAL  DEFAULT   12 rb_thread_alive_p&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Often, many of these functions are bound to ruby methods (from Ruby&amp;#8217;s &lt;code&gt;thread.c&lt;/code&gt;):&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;CodeRay highlight&quot;&gt;&lt;code data-lang=&quot;c&quot;&gt;&lt;span style=&quot;color:#777&quot;&gt;/*
 *  call-seq:
 *     thr.alive?   -&amp;gt; true or false
 *
 *  Returns +true+ if +thr+ is running or sleeping.
 *
 *     thr = Thread.new { }
 *     thr.join                #=&amp;gt; #&amp;lt;Thread:0x401b3fb0 dead&amp;gt;
 *     Thread.current.alive?   #=&amp;gt; true
 *     thr.alive?              #=&amp;gt; false
 *
 *  See also #stop? and #status.
 */&lt;/span&gt;

&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;static&lt;/span&gt; VALUE
rb_thread_alive_p(VALUE thread)
{
    &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;return&lt;/span&gt; RBOOL(!thread_finished(rb_thread_ptr(thread)));
}


&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt;
Init_Thread(&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;void&lt;/span&gt;)
{
    &lt;span style=&quot;color:#777&quot;&gt;// ...&lt;/span&gt;
    rb_define_method(rb_cThread, &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;alive?&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, rb_thread_alive_p, &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;);
    &lt;span style=&quot;color:#777&quot;&gt;// ...&lt;/span&gt;
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;The only way of calling these functions is to ask Ruby to call the &lt;code&gt;Thread#alive?&lt;/code&gt; method on a given thread object, as you would to in regular Ruby code.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;But&amp;#8230;&amp;#8203; the kind of tools I work on often need to call into the Ruby VM at &quot;inconvenient&quot; times: during a garbage collection cycle; or when a thread does not have the Global VM Lock. In those situations, it&amp;#8217;s not possible to ask Ruby to call methods.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;For instance, recently I was working on a feature for the &lt;code&gt;gvl-tracing&lt;/code&gt; gem where I needed to know if the current thread was still alive, or if it was in the process of terminating. And well, if you try to call &lt;code&gt;Thread#alive?&lt;/code&gt; in the middle of a thread terminating, you&amp;#8217;ll trigger a crash because Ruby has already cleaned up some of the thread&amp;#8217;s state that makes it able to call Ruby methods.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;So again in I went into the Ruby VM source code, and found another solution which &lt;em&gt;almost almost&lt;/em&gt; worked: checking if the current fiber was alive. There&amp;#8217;s a public API for that! But&amp;#8230;&amp;#8203; Ruby allocates fiber objects lazily, so if the fiber object didn&amp;#8217;t exist then&amp;#8230;&amp;#8203; hey here I am crashing the VM because the fiber object can&amp;#8217;t be allocated if a thread is terminating.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;And all the while that &lt;code&gt;rb_thread_alive_p&lt;/code&gt; is exactly what I wanted! So I decided to experiment with something that&amp;#8217;s been gnawing at me for a long time&amp;#8201;&amp;#8212;&amp;#8201;is it possible, and how hard is it to get the pointer to &lt;code&gt;rb_thread_alive_p&lt;/code&gt; that &lt;code&gt;rb_define_method&lt;/code&gt; received back from Ruby?&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;The long answer to that question is that it is possible, and not that hard. The short answer is &lt;a href=&quot;https://github.com/ivoanjo/direct-bind&quot;&gt;&lt;code&gt;direct-bind&lt;/code&gt;&lt;/a&gt; ;)&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;The &lt;code&gt;direct-bind&lt;/code&gt; gem takes heavy inspiration from &lt;a href=&quot;https://github.com/DataDog/dd-trace-rb/pull/4540&quot;&gt;some experiments we&amp;#8217;ve done at Datadog&lt;/a&gt;, that I also recently discovered &lt;a href=&quot;https://github.com/ruby/debug/blob/master/ext/debug/iseq_collector.c&quot;&gt;is what the &lt;code&gt;debug&lt;/code&gt; gem basically does&lt;/a&gt;. There&amp;#8217;s two key insights to doing what we need: The data we want to get access to lives on the Ruby object heap, and so it&amp;#8217;s possible to use the &quot;iterate every object&quot; API &lt;code&gt;rb_objspace_each_objects&lt;/code&gt; to locate the objects we want; and the layout of the data structure itself is quite simple, flat, and has not changed (for the purposes of &lt;code&gt;direct-bind&lt;/code&gt;) in a long time.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;With some C coding, here&amp;#8217;s how the resulting API looks:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;CodeRay highlight&quot;&gt;&lt;code data-lang=&quot;c&quot;&gt;VALUE (*is_thread_alive)(VALUE thread);

is_thread_alive = direct_bind_get_cfunc_with_arity(rb_cThread, rb_intern(&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;alive?&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;), &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;, &lt;span style=&quot;color:#069&quot;&gt;true&lt;/span&gt;).func;

is_thread_alive(rb_thread_current());&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;And that&amp;#8217;s it! Suddenly I was able to &lt;a href=&quot;https://github.com/ivoanjo/gvl-tracing/commit/4a20c2f2f1b8cb1f481e498b98075a4e4e5ee267&quot;&gt;solve my problem&lt;/a&gt; of calling into &lt;code&gt;rb_thread_alive_p&lt;/code&gt;, even though it&amp;#8217;s not a public Ruby API directly available for extensions to use.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Because the specific part of the structure where we&amp;#8217;re getting this info from hasn&amp;#8217;t changed in a long time, &lt;code&gt;direct-bind&lt;/code&gt; works for Ruby 2.5 and above, including current Ruby 3.5 master. (It probably would work on older Rubies but&amp;#8230;&amp;#8203; I leave that as an experiment for someone else.)&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;So&amp;#8230;&amp;#8203; that&amp;#8217;s it! &lt;code&gt;direct-bind&lt;/code&gt; is out there in the world, I&amp;#8217;m not sure if anyone else other than me is ever going to want to do something like this, but yeah, it was a fun hack!&lt;/p&gt;
&lt;/div&gt;</description>
        <pubDate>Sun, 15 Jun 2025 00:00:00 +0100</pubDate>
        <link>https://ivoanjo.me/blog/2025/06/15/direct-bind-ruby-gem/</link>
        <guid isPermaLink="true">https://ivoanjo.me/blog/2025/06/15/direct-bind-ruby-gem/</guid>
        <category>blog</category>
      </item>
      <item>
        <title>M:N scheduling and how the (Ruby) global vm lock impacts app performance</title>
        <description>&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;A while back I created the &lt;a href=&quot;https://github.com/ivoanjo/gvl-tracing/&quot;&gt;gvl-tracing&lt;/a&gt; gem as an experiment to help understand what was going on inside Ruby when multiple threads are in use.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;But Ruby is not standing still! Ruby 3.3 saw the introduction of M:N scheduling (off by default) which is a feature I&amp;#8217;ve been quite looking forward to. What is M:N scheduling, you ask? It&amp;#8217;s a new execution strategy for Ruby threads that is similar/borrows from to the one used by Java&amp;#8217;s virtual threads, Go&amp;#8217;s coroutines or Erlang&amp;#8217;s processes. (Note that when I say it&amp;#8217;s similar to other VMs, I&amp;#8217;m comparing the execution strategy part of the implementation, not the APIs or features provided).&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;With M:N scheduling Ruby threads are no longer mapped 1:1 to operating system threads; instead any &lt;strong&gt;M&lt;/strong&gt; Ruby threads you choose to create are mapped to a pool of &lt;strong&gt;N&lt;/strong&gt; operating system threads that Ruby automatically manages for you. Up until now, Ruby used a 1:1 strategy; now M will usually not be the same as N, and this is where the name comes from.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Why is this cool? For two big reasons: it makes Ruby threads into a simpler programming model, and it provides improved performance. Starting with performance, operating system threads are costly to create and manage, which is where the typical guidance for not creating too many, and to use techniques such as pooling comes from. With the introduction of ractors, this became an even bigger bottleneck for Ruby: without M:N scheduling each ractor would require at least one (new) thread, which put a clear limit on not using too many ractors.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;By decoupling Ruby threads from operating system threads, code using threads or ractors becomes a lot more scalable! This is actually quite similar to how when you use fibers your application can do a lot more with less.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;The second benefit from M:N scheduling is how it simplifies the programming model: Once creating threads and ractors becomes extremely cheap, you no longer need to pool them or reuse them or treat them as very special expensive snowflakes. Instead, they become a lot closer to fibers, where in many cases you can create almost as many as you need and not think too much about it.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;This brings us back to talking about the GVL for two reasons: 1. If you&amp;#8217;re not using ractors, only threads, then even with M:N scheduling you&amp;#8217;ll still only have one Ruby thread running at a time, regardless of how that gets mapped to operating system threads; and 2. How to visualize the impact of M:N scheduling on your app?&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;At RubyConf 2024 I explored this topic and introduced a novel feature for the gvl-tracing gem: the ability to show both what the Ruby threads were doing (the M part) as well as how the Ruby VM was mapping them into operating system threads (the N part).&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;And, while I thought this new feature may be quite interesting by itself, I was quite surprised to uncover two different Ruby VM bugs related to the M:N scheduler (fixes are work in progress as of this writing: &lt;a href=&quot;https://github.com/ruby/ruby/pull/12094&quot;&gt;1&lt;/a&gt;, &lt;a href=&quot;https://github.com/ruby/ruby/pull/12093&quot;&gt;2&lt;/a&gt;).&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;You&amp;#8217;ll find the video and slides for my RubyConf 2024 talk below.&lt;/p&gt;
&lt;/div&gt;
&lt;iframe width=&quot;736&quot; height=&quot;420&quot; src=&quot;https://www.youtube.com/embed/MmKhsvvyiCw?si=tQwtgZLPHLhaX2ep&quot; title=&quot;YouTube video player&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; referrerpolicy=&quot;strict-origin-when-cross-origin&quot; allowfullscreen&gt;&lt;/iframe&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Slide deck:&lt;/p&gt;
&lt;/div&gt;
&lt;iframe src=&quot;https://docs.google.com/presentation/d/e/2PACX-1vRADboUvRklhTU89hzmCc9VnRmQYe0aJut77a2tsiFGOktN8pnxpnh4QIeal8SI40dAQtTuMBFIzdUV/embed?start=false&amp;loop=false&amp;delayms=3000&quot; frameborder=&quot;0&quot; width=&quot;736&quot; height=&quot;443&quot; allowfullscreen&gt;&lt;/iframe&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;And that&amp;#8217;s not all! An additional element was added to this story with Ruby 3.4: it introduces &lt;a href=&quot;https://bugs.ruby-lang.org/issues/20861&quot;&gt;&lt;code&gt;RUBY_THREAD_TIMESLICE&lt;/code&gt;&lt;/a&gt;, a setting to control how long each Ruby thread gets to run before being switched. I&amp;#8217;m hoping this will lead Ruby&amp;#8217;s default of 100ms to be progressively lowered, hopefully to something close to 10ms (which is what Python uses 😉).&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Although, in the medium/long term, and connected to the M:N scheduling changes, what I believe will unlock the next wave of great performance in the presence of multiple threads, ractors and fibers is for Ruby to introduce a full &lt;strong&gt;scheduler&lt;/strong&gt;, similar to the one used inside the operating system. Such a scheduler would allow Ruby to better balance IO-heavy work with CPU-heavy work, and make sure that all parts of the application get to run timely and with a fair distribution of resources. This is especially relevant as the more Ruby does internally, the less the operating system&amp;#8217;s scheduler can help out with.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;In the future, I hope to explore more around this topic of a Ruby scheduler.&lt;/p&gt;
&lt;/div&gt;</description>
        <pubDate>Sun, 30 Mar 2025 00:00:00 +0000</pubDate>
        <link>https://ivoanjo.me/blog/2025/03/30/mn-scheduling-and-how-the-ruby-gvl-impacts-app-perf/</link>
        <guid isPermaLink="true">https://ivoanjo.me/blog/2025/03/30/mn-scheduling-and-how-the-ruby-gvl-impacts-app-perf/</guid>
        <category>blog</category>
      </item>
      <item>
        <title>Building an always-on (Ruby) production profiler</title>
        <description>&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;For the past few years, I&amp;#8217;ve been working at Datadog on a new open-source Ruby profiler.
This profiler is shipped as part of the &lt;a href=&quot;https://github.com/DataDog/dd-trace-rb&quot;&gt;&lt;code&gt;datadog&lt;/code&gt; Ruby gem&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Why spend all this time and effort on building a new profiler? The key detail is that we want (and need) something that is built to be always-on in production. That translates to having really low overhead in several dimensions, including low cpu usage, low memory usage and low impact on the application&amp;#8217;s latency, while also being something that can run for a long time unattended without impacting the application.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Doing this involves a different set of trade-offs than most profilers. For instance, the &lt;code&gt;datadog&lt;/code&gt; profiler is able to profile cpu, wall-time, allocations, heap, the Global VM Lock, and Garbage Collection all at the same time, and while staying within the same low-overhead. It also has workarounds for a number of bugs in Ruby and 3rd-party gems, so as to make sure it never impacts any application it is added to.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;I&amp;#8217;ve had to spent quite a lot of time writing C and Rust to make the Datadog Ruby profiler happen. And it even spawned a few off-shoots I&amp;#8217;ve talked about in this blog in the past, such as the &lt;code&gt;gvl-tracing&lt;/code&gt; gem to investigate activity around Ruby&amp;#8217;s Global VM Lock and the &lt;code&gt;backtracie&lt;/code&gt; gem to read stack traces with more detail and lower overhead.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Last year, at the RubyKaigi 2024 conference I had the chance to talk about how Datadog&amp;#8217;s Ruby profiler works. It took me almost a year to write this blog post, but here&amp;#8217;s the video and slide deck for the talk.&lt;/p&gt;
&lt;/div&gt;
&lt;iframe width=&quot;736&quot; height=&quot;420&quot; src=&quot;https://www.youtube.com/embed/7wWlbvUctoE?si=Cp4Po7woum8u5tUq&quot; title=&quot;YouTube video player&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; referrerpolicy=&quot;strict-origin-when-cross-origin&quot; allowfullscreen&gt;&lt;/iframe&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Slide deck:&lt;/p&gt;
&lt;/div&gt;
&lt;iframe src=&quot;https://docs.google.com/presentation/d/e/2PACX-1vRpYPCrxll-MVn_u2AAP3iSXiAdQV1KC8XMsFPb7kRVS-eB3pLz6i5lxFRyuc3GovXxETdsG1k-G1E7/embed?start=false&amp;loop=false&amp;delayms=3000&quot; frameborder=&quot;0&quot; width=&quot;736&quot; height=&quot;443&quot; allowfullscreen=&quot;true&quot; mozallowfullscreen=&quot;true&quot; webkitallowfullscreen=&quot;true&quot;&gt;&lt;/iframe&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Ruby performance is seeing a big renaissance: YJIT is getting better and better, JRuby and TruffleRuby continue to provide really strong alternatives, there&amp;#8217;s a number of new profilers for Ruby beyond the Datadog profiler (Vernier, pf2), and there&amp;#8217;s ongoing work to upgrade Ruby&amp;#8217;s garbage collector.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;And&amp;#8230;&amp;#8203; I am totally here for it!&lt;/p&gt;
&lt;/div&gt;</description>
        <pubDate>Wed, 19 Mar 2025 00:00:00 +0000</pubDate>
        <link>https://ivoanjo.me/blog/2025/03/19/building-an-always-on-production-ruby-profiler/</link>
        <guid isPermaLink="true">https://ivoanjo.me/blog/2025/03/19/building-an-always-on-production-ruby-profiler/</guid>
        <category>blog</category>
      </item>
      <item>
        <title>Backtracie and the quest for prettier Ruby backtraces</title>
        <description>&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;A backtrace is one of those Ruby features that is extremely useful, but we never think about it. They&amp;#8217;re just always there in our time of need&amp;#8201;&amp;#8212;&amp;#8201;be it when an error happens, when exploring our code inside a irb or a debugger, or even when profiling our app.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;For a while now, I&amp;#8217;ve been thinking about, and working on, possible improvements for Ruby&amp;#8217;s backtraces&amp;#8201;&amp;#8212;&amp;#8201;I&amp;#8217;ve blogged about it [&lt;a href=&quot;/blog/2020/07/05/ruby-experiment-include-class-names-in-backtraces/&quot;&gt;1&lt;/a&gt;, &lt;a href=&quot;/blog/2020/07/19/better-backtraces-in-ruby-using-tracepoint/&quot;&gt;2&lt;/a&gt;], and even ended up creating the &lt;a href=&quot;https://github.com/ivoanjo/backtracie&quot;&gt;&lt;code&gt;backtracie&lt;/code&gt;&lt;/a&gt; Ruby gem to be able to make those improvements a reality.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Recently, at FOSDEM 2024, I had a chance to talk about how Ruby backtraces work inside the Ruby VM, as well as how &lt;code&gt;backtracie&lt;/code&gt; works. If you’ve ever been curious about how this mechanism works, this talk is for you.&lt;/p&gt;
&lt;/div&gt;
&lt;video preload=&quot;none&quot; controls=&quot;controls&quot; width=&quot;736&quot;&gt;
    &lt;source src=&quot;https://video.fosdem.org/2024/k3401/fosdem-2024-2473-backtracie-and-the-quest-for-prettier-ruby-backtraces.av1.webm&quot; type=&quot;video/webm; codecs=&amp;quot;av01.0.08M.08.0.110.01.01.01.0&amp;quot;&quot;&gt;
    &lt;source src=&quot;https://video.fosdem.org/2024/k3401/fosdem-2024-2473-backtracie-and-the-quest-for-prettier-ruby-backtraces.mp4&quot; type=&quot;video/mp4&quot;&gt;
  &lt;/video&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Slide deck:&lt;/p&gt;
&lt;/div&gt;
&lt;iframe src=&quot;https://docs.google.com/presentation/d/e/2PACX-1vSDgT_N3jonFKiRqVIwdtwOKm4ltKOMjE6lQk_0CVT6pSKd0OLais-wlngOWqHNpbAKzDOmZdArokaD/embed?start=false&amp;loop=false&amp;delayms=3000&quot; frameborder=&quot;0&quot; width=&quot;736&quot; height=&quot;443&quot; allowfullscreen=&quot;true&quot; mozallowfullscreen=&quot;true&quot; webkitallowfullscreen=&quot;true&quot;&gt;&lt;/iframe&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Also, during the talk, I mentioned that adding class names to Ruby backtraces was being discussed for &lt;a href=&quot;https://bugs.ruby-lang.org/issues/19117&quot;&gt;integration into Ruby itself&lt;/a&gt; and I&amp;#8217;m very happy to announce that the feature was recently &lt;a href=&quot;https://bugs.ruby-lang.org/issues/19117#note-43&quot;&gt;approved by Matz, the creator of Ruby&lt;/a&gt;:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;quoteblock&quot;&gt;
&lt;blockquote&gt;
&lt;div class=&quot;imageblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;img src=&quot;/img/matz-classnames.png&quot; alt=&quot;matz classnames&quot;&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/blockquote&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&amp;#8230;&amp;#8203;so look forward to it in Ruby 3.4! It&amp;#8217;s really cool to have been part of this effort :)&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;P.s.: If you&amp;#8217;ve not heard before of &lt;a href=&quot;https://fosdem.org/&quot;&gt;FOSDEM&lt;/a&gt;, I really recommend taking a look. This yearly conference is free (you don&amp;#8217;t even need to register), and you get such an amazing amount of talks about every subject in free software. I&amp;#8217;ve been attending it yearly, and hope to come back next year as well.&lt;/p&gt;
&lt;/div&gt;</description>
        <pubDate>Thu, 07 Mar 2024 00:00:00 +0000</pubDate>
        <link>https://ivoanjo.me/blog/2024/03/07/backtracie-and-the-quest-for-prettier-ruby-backtraces/</link>
        <guid isPermaLink="true">https://ivoanjo.me/blog/2024/03/07/backtracie-and-the-quest-for-prettier-ruby-backtraces/</guid>
        <category>blog</category>
      </item>
      <item>
        <title>Look out! Gotchas of using threads in Ruby</title>
        <description>&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Threads (along with fibers and ractors) are all extremely powerful and useful tools for Ruby developers. Yet, they often seem to be surrounded by this aura of mystery, as if they are something for wizards to employ in their magicks and not for mere mortals to make use of.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;I recently spoke at EuRuKo 2023 about this topic with the aim of demystifying Ruby threads. You can find the video and slides for my &quot;Look out! Gotchas of using threads in Ruby&quot; talk below.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;By documenting common gotchas, and then explaining why they happen and how to fix them, let&amp;#8217;s build a better mental model of how the Ruby concurrency primitives work, and hopefully get confident and excited about using them safely 😉&lt;/p&gt;
&lt;/div&gt;
&lt;iframe width=&quot;736&quot; height=&quot;420&quot; src=&quot;https://www.youtube.com/embed/B8f8-UhgQkQ&quot; title=&quot;YouTube video player&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; referrerpolicy=&quot;strict-origin-when-cross-origin&quot; allowfullscreen&gt;&lt;/iframe&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Slide deck:&lt;/p&gt;
&lt;/div&gt;
&lt;iframe src=&quot;https://docs.google.com/presentation/d/e/2PACX-1vThx73aTVJ2uDmdnGPhAP9hRtACfmkHCJBE4qx3G29dYf4ACM06UQhdQ4oHXoMkUUgwlxeQmwr4c84R/embed?start=false&amp;loop=false&amp;delayms=3000&quot; frameborder=&quot;0&quot; width=&quot;736&quot; height=&quot;443&quot; allowfullscreen=&quot;true&quot; mozallowfullscreen=&quot;true&quot; webkitallowfullscreen=&quot;true&quot;&gt;&lt;/iframe&gt;</description>
        <pubDate>Mon, 04 Mar 2024 00:00:00 +0000</pubDate>
        <link>https://ivoanjo.me/blog/2024/03/04/look-out-gotchas-of-using-threads-in-ruby/</link>
        <guid isPermaLink="true">https://ivoanjo.me/blog/2024/03/04/look-out-gotchas-of-using-threads-in-ruby/</guid>
        <category>blog</category>
      </item>
      <item>
        <title>Understanding the Ruby Global VM Lock by observing it</title>
        <description>&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;The Global VM Lock (GVL), also known as Global Interpreter Lock (GIL), is an implementation detail of the Ruby VM. At a high-level, it prevents Ruby code across multiple threads from running in parallel (while still allowing concurrency!).&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;The GVL is an extremely important implementation detail, as it can have a big impact on the performance and responsiveness of any Ruby application that uses more than a single thread to do its work.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;I&amp;#8217;ve previously blogged (see bottom of the post for links!) about my ongoing experiments building the &lt;a href=&quot;https://github.com/ivoanjo/gvl-tracing&quot;&gt;&lt;code&gt;gvl-tracing&lt;/code&gt;&lt;/a&gt; gem to try to learn more about how the GVL works, and how it impacts Ruby apps.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Recently, I had the incredible opportunity to present what I&amp;#8217;ve learned so far at the RubyKaigi 2023 conference.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;You can find the video and slides for this talk below, and &lt;a href=&quot;/rubykaigi2023/&quot;&gt;here&amp;#8217;s a live link to all the experiments, including code and perfetto links&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;iframe width=&quot;736&quot; height=&quot;420&quot; src=&quot;https://www.youtube.com/embed/rI4XlFvMNEw&quot; title=&quot;YouTube video player&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; referrerpolicy=&quot;strict-origin-when-cross-origin&quot; allowfullscreen&gt;&lt;/iframe&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Slide deck:&lt;/p&gt;
&lt;/div&gt;
&lt;iframe src=&quot;https://docs.google.com/presentation/d/e/2PACX-1vThPEqaFNBSjY6AL6pRsac9Grp7bJ6iTYy0Aq9uRywU47Yk7kPB58i4oWKTvhN6cIHbFhABm9avPag_/embed?start=false&amp;loop=false&amp;delayms=3000&quot; frameborder=&quot;0&quot; width=&quot;736&quot; height=&quot;443&quot; allowfullscreen=&quot;true&quot; mozallowfullscreen=&quot;true&quot; webkitallowfullscreen=&quot;true&quot;&gt;&lt;/iframe&gt;</description>
        <pubDate>Sun, 23 Jul 2023 00:00:00 +0100</pubDate>
        <link>https://ivoanjo.me/blog/2023/07/23/understanding-the-ruby-global-vm-lock-by-observing-it/</link>
        <guid isPermaLink="true">https://ivoanjo.me/blog/2023/07/23/understanding-the-ruby-global-vm-lock-by-observing-it/</guid>
        <category>blog</category>
      </item>
      <item>
        <title>Ruby's unexpected I/O vs CPU unfairness</title>
        <description>&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Recently, while benchmarking a test application, I observed that if I mixed threads doing input/output (such as reading files or network/database requests) and threads doing CPU work, the I/O work would be slowed down massively. It took me a while to realize this was caused by how (and when) Ruby switches between threads.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;For instance consider querying a web server (here I&amp;#8217;m using google as an example) as fast as possible:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;CodeRay highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;require &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;net/http&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;
require &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;benchmark/ips&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;

&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color:#06B;font-weight:bold&quot;&gt;perform_request&lt;/span&gt;
  &lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;Net&lt;/span&gt;::&lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;HTTP&lt;/span&gt;.start(&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;www.google.com&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;, &lt;span style=&quot;color:#606&quot;&gt;open_timeout&lt;/span&gt;: &lt;span style=&quot;color:#60E&quot;&gt;0.5&lt;/span&gt;, &lt;span style=&quot;color:#606&quot;&gt;read_timeout&lt;/span&gt;: &lt;span style=&quot;color:#60E&quot;&gt;0.5&lt;/span&gt;, &lt;span style=&quot;color:#606&quot;&gt;write_timeout&lt;/span&gt;: &lt;span style=&quot;color:#60E&quot;&gt;0.5&lt;/span&gt;) &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;do&lt;/span&gt; |http|
    http.get(&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;)
  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;end&lt;/span&gt;
&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;end&lt;/span&gt;

&lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;Benchmark&lt;/span&gt;.ips &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;do&lt;/span&gt; |x|
  x.config(&lt;span style=&quot;color:#606&quot;&gt;time&lt;/span&gt;: &lt;span style=&quot;color:#00D&quot;&gt;1&lt;/span&gt;, &lt;span style=&quot;color:#606&quot;&gt;warmup&lt;/span&gt;: &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;)
  x.report(&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;request&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;) { perform_request }
&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;When I run this example on my current wifi, I get:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre&gt;$ bundle exec ruby io-cpu-unfairness-1.rb
Calculating -------------------------------------
             request     16.571  (±12.1%) i/s -     17.000  in   1.039825s&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;I get an OK-ish 60ms per request, which means I do a little over 16 such requests in a second.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Now, what happens if I add a background thread that is crunching some data while I&amp;#8217;m trying to reach out to google?&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;CodeRay highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;require &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;net/http&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;
require &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;benchmark/ips&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;

&lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;Thread&lt;/span&gt;.new &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;do&lt;/span&gt;
  &lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;Thread&lt;/span&gt;.current.name = &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;cpu-heavy&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;
  foo = &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;
  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;while&lt;/span&gt; &lt;span style=&quot;color:#069&quot;&gt;true&lt;/span&gt;
    foo += &lt;span style=&quot;color:#00D&quot;&gt;1&lt;/span&gt;
    foo = &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt; &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;if&lt;/span&gt; foo &amp;gt; &lt;span style=&quot;color:#00D&quot;&gt;1_000_000_000_000&lt;/span&gt;
  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;end&lt;/span&gt;
&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;end&lt;/span&gt;

&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color:#06B;font-weight:bold&quot;&gt;perform_request&lt;/span&gt;
  &lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;Net&lt;/span&gt;::&lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;HTTP&lt;/span&gt;.start(&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;www.google.com&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;, &lt;span style=&quot;color:#606&quot;&gt;open_timeout&lt;/span&gt;: &lt;span style=&quot;color:#60E&quot;&gt;0.5&lt;/span&gt;, &lt;span style=&quot;color:#606&quot;&gt;read_timeout&lt;/span&gt;: &lt;span style=&quot;color:#60E&quot;&gt;0.5&lt;/span&gt;, &lt;span style=&quot;color:#606&quot;&gt;write_timeout&lt;/span&gt;: &lt;span style=&quot;color:#60E&quot;&gt;0.5&lt;/span&gt;) &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;do&lt;/span&gt; |http|
    http.get(&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;)
  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;end&lt;/span&gt;
&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;end&lt;/span&gt;

&lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;Benchmark&lt;/span&gt;.ips &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;do&lt;/span&gt; |x|
  x.config(&lt;span style=&quot;color:#606&quot;&gt;time&lt;/span&gt;: &lt;span style=&quot;color:#00D&quot;&gt;1&lt;/span&gt;, &lt;span style=&quot;color:#606&quot;&gt;warmup&lt;/span&gt;: &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;)
  x.report(&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;request&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;) { perform_request }
&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre&gt;$ bundle exec ruby io-cpu-unfairness-2.rb
Calculating -------------------------------------
             request      1.664  (± 0.0%) i/s -      2.000  in   1.201622s&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Suddenly, performance takes a big dive and we don&amp;#8217;t even get through more than a single request per second.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;What&amp;#8217;s going on here?&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Using the &lt;a href=&quot;https://github.com/ivoanjo/gvl-tracing/&quot;&gt;&lt;code&gt;gvl-tracing&lt;/code&gt; gem&lt;/a&gt; (on Ruby 3.2), we can actually visualize what&amp;#8217;s happening.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Compare the thread timelines for both examples:&lt;/p&gt;
&lt;/div&gt;
&lt;img class=&quot;fullsize&quot; src=&quot;/img/io-cpu-gvl-1.png&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&lt;strong&gt;Figure 1&lt;/strong&gt;: Timeline for fast example.&lt;/p&gt;
&lt;/div&gt;
&lt;img class=&quot;fullsize&quot; src=&quot;/img/io-cpu-gvl-2.png&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&lt;strong&gt;Figure 2&lt;/strong&gt;: Timeline for slow example (with a background thread consuming CPU).&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;This is in fact caused by Ruby&amp;#8217;s Global VM Lock (GVL), and the way Ruby decides when to switch between several threads.
Whenever a thread is going to block waiting for some reply, and there are other threads wanting to run, Ruby will switch to them. But if a thread never blocks, then Ruby will give it around &lt;a href=&quot;https://github.com/ruby/ruby/blob/f313514563853f1ee623135c2959df2b518ee755/thread_pthread.c#L300-L305&quot;&gt;100ms&lt;/a&gt; to run before forcing a switch.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;This explains the difference between figures 1 and 2: In figure 1, the &quot;network requests&quot; thread spends most of its time waiting on network requests, and if we zoom in (figure 3, below), we see that when a reply is available, the thread immediately wakes up and issues the next network request.&lt;/p&gt;
&lt;/div&gt;
&lt;img class=&quot;fullsize&quot; src=&quot;/img/io-cpu-gvl-3.png&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&lt;strong&gt;Figure 3&lt;/strong&gt;: Zooming in on the fast example.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;In the figure 2, the &quot;network requests&quot; thread spends most of its time in the ready state&amp;#8201;&amp;#8212;&amp;#8201;that is, it&amp;#8217;s ready to continue working, but it must wait for the cpu-heavy thread to finish its own 100ms.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;This behavior ends up being quite unfair for a thread doing I/O work. That thread may only work for a few milliseconds before blocking, but once it blocks it must wait for all other threads to have their own go, which at 100ms per thread can take a long time.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;The takeaway here is, be careful when mixing input/output (such as reading files or network/database requests) and CPU work: suddenly your I/O will be slower and it may be hard to understand why. This can happen if you&amp;#8217;re using a multi-threaded webserver, such as puma, or a multi-threaded job queue such as sidekiq.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&lt;strong&gt;Edit&lt;/strong&gt;: If you know that some block of Ruby code will be CPU intensive, then as &lt;a href=&quot;https://twitter.com/maciejmensfeld/status/1624527582619205632&quot;&gt;@maciejmensfeld&lt;/a&gt; suggested, you can use &lt;a href=&quot;https://rubyapi.org/3.2/o/thread#method-c-pass&quot;&gt;&lt;code&gt;Thread#pass&lt;/code&gt;&lt;/a&gt; to tell the Ruby scheduler to give other threads a chance before the 100ms period is up.&lt;/p&gt;
&lt;/div&gt;</description>
        <pubDate>Sat, 11 Feb 2023 00:00:00 +0000</pubDate>
        <link>https://ivoanjo.me/blog/2023/02/11/ruby-unexpected-io-vs-cpu-unfairness/</link>
        <guid isPermaLink="true">https://ivoanjo.me/blog/2023/02/11/ruby-unexpected-io-vs-cpu-unfairness/</guid>
        <category>blog</category>
      </item>
      <item>
        <title>Talking Ruby Performance Tooling at the Ruby Rogues podcast</title>
        <description>&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;I was recently invited to the Ruby Rogues podcast for a second time. We talked about the pitfalls of Ruby performance, when and why you should profile, and the tools I&amp;#8217;ve been working on to better explore and optimize Ruby performance.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;These include:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;/blog/2022/07/17/tracing-ruby-global-vm-lock/&quot;&gt;Tracing the Ruby Global VM Lock using the &lt;code&gt;gvl-tracing&lt;/code&gt; gem&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/datadog/dd-trace-rb&quot;&gt;The Datadog Continuous Profiler for Ruby included in the &lt;code&gt;ddtrace&lt;/code&gt; gem&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;/blog/2022/11/09/hunting-production-memory-leaks-rubykaigi-2022/&quot;&gt;A gem for investigating memory leaks in production &lt;code&gt;ruby_memprofiler_pprof&lt;/code&gt; that I helped out with&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;You can &lt;a href=&quot;https://audio4.redcircle.com/episodes/45246b2d-043f-4e9b-94b2-c04347186f49/stream.mp3&quot;&gt;download the episode as an mp3&lt;/a&gt; or listen to it online at &lt;a href=&quot;https://topenddevs.com/podcasts/ruby-rogues/optimizing-ruby-user-experience-with-ivo-anjo-ruby-574&quot; class=&quot;bare&quot;&gt;https://topenddevs.com/podcasts/ruby-rogues/optimizing-ruby-user-experience-with-ivo-anjo-ruby-574&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Hope you find it useful!&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;P.s.: This blog is now brought to you by Ruby 3.2 with YJIT ;)&lt;/p&gt;
&lt;/div&gt;</description>
        <pubDate>Tue, 24 Jan 2023 00:00:00 +0000</pubDate>
        <link>https://ivoanjo.me/blog/2023/01/24/ruby-performance-tooling-podcast/</link>
        <guid isPermaLink="true">https://ivoanjo.me/blog/2023/01/24/ruby-performance-tooling-podcast/</guid>
        <category>blog</category>
      </item>
      <item>
        <title>Ruby reuses native OS threads after Ruby Threads die</title>
        <description>&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Since Ruby 1.9, each Ruby &lt;code&gt;Thread&lt;/code&gt; gets executed on its own native operating system thread.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;But, as a performance optimization, Ruby will try to reuse native operating system threads if it can.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;When a Ruby &lt;code&gt;Thread&lt;/code&gt; terminates, Ruby will not immediately terminate the operating system thread that was hosting it. Instead, it will keep it around for a few seconds, and if in that time period the application starts a new &lt;code&gt;Thread&lt;/code&gt;, then Ruby will reuse an existing operating system thread.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;This can be observed on Ruby 3.1+ by using the new &lt;code&gt;Thread#native_thread_id&lt;/code&gt; method:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;CodeRay highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;puts &lt;span style=&quot;color:#069&quot;&gt;RUBY_DESCRIPTION&lt;/span&gt;

&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color:#06B;font-weight:bold&quot;&gt;thread_info&lt;/span&gt;
  &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;Thread &lt;/span&gt;&lt;span style=&quot;background-color:hsla(0,0%,0%,0.07);color:black&quot;&gt;&lt;span style=&quot;font-weight:bold;color:#666&quot;&gt;#{&lt;/span&gt;&lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;Thread&lt;/span&gt;.current&lt;span style=&quot;font-weight:bold;color:#666&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt; is being hosted by &lt;/span&gt;&lt;span style=&quot;background-color:hsla(0,0%,0%,0.07);color:black&quot;&gt;&lt;span style=&quot;font-weight:bold;color:#666&quot;&gt;#{&lt;/span&gt;&lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;Thread&lt;/span&gt;.current.native_thread_id&lt;span style=&quot;font-weight:bold;color:#666&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;end&lt;/span&gt;

puts &lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;Thread&lt;/span&gt;.new { thread_info }.value
puts &lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;Thread&lt;/span&gt;.new { thread_info }.value
puts &lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;Thread&lt;/span&gt;.new { thread_info }.value

puts &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;Sleeping for a bit...&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
sleep &lt;span style=&quot;color:#00D&quot;&gt;10&lt;/span&gt;

puts &lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;Thread&lt;/span&gt;.new { thread_info }.value&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&amp;#8230;&amp;#8203;and here&amp;#8217;s the result of running this example:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre&gt;ruby 3.1.2p20 (2022-04-12 revision 4491bb740a) [x86_64-linux]
Thread #&amp;lt;Thread:0x00007f0e5e985030 example1.rb:7 run&amp;gt; is being hosted by 44061
Thread #&amp;lt;Thread:0x00007f0e5e9841a8 example1.rb:8 run&amp;gt; is being hosted by 44061
Thread #&amp;lt;Thread:0x00007f0e5e98bcc8 example1.rb:9 run&amp;gt; is being hosted by 44061
Sleeping for a bit...
Thread #&amp;lt;Thread:0x00007f0e5e98b070 example1.rb:14 run&amp;gt; is being hosted by 44084&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;On older Rubies, &lt;code&gt;Thread#native_thread_id&lt;/code&gt; did not not exist yet, but we can implement our own:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;CodeRay highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;puts &lt;span style=&quot;color:#069&quot;&gt;RUBY_DESCRIPTION&lt;/span&gt;

&lt;span style=&quot;color:#777&quot;&gt;# Only for Linux; supporting other OS&apos;s is left as an exercise for the reader ;)&lt;/span&gt;
&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color:#06B;font-weight:bold&quot;&gt;current_native_thread_id&lt;/span&gt;
  &lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;File&lt;/span&gt;.readlink(&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;/proc/thread-self&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;).split(&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;).last
&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;end&lt;/span&gt;

&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color:#06B;font-weight:bold&quot;&gt;thread_info&lt;/span&gt;
  &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;Thread &lt;/span&gt;&lt;span style=&quot;background-color:hsla(0,0%,0%,0.07);color:black&quot;&gt;&lt;span style=&quot;font-weight:bold;color:#666&quot;&gt;#{&lt;/span&gt;&lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;Thread&lt;/span&gt;.current&lt;span style=&quot;font-weight:bold;color:#666&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt; is being hosted by &lt;/span&gt;&lt;span style=&quot;background-color:hsla(0,0%,0%,0.07);color:black&quot;&gt;&lt;span style=&quot;font-weight:bold;color:#666&quot;&gt;#{&lt;/span&gt;current_native_thread_id&lt;span style=&quot;font-weight:bold;color:#666&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;end&lt;/span&gt;

puts &lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;Thread&lt;/span&gt;.new { thread_info }.value
puts &lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;Thread&lt;/span&gt;.new { thread_info }.value
puts &lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;Thread&lt;/span&gt;.new { thread_info }.value

puts &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;Sleeping for a bit...&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
sleep &lt;span style=&quot;color:#00D&quot;&gt;10&lt;/span&gt;

puts &lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;Thread&lt;/span&gt;.new { thread_info }.value&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&amp;#8230;&amp;#8203;and here&amp;#8217;s the result of running this example on the older Ruby 2.7 series:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre&gt;ruby 2.7.2p137 (2020-10-01 revision 5445e04352) [x86_64-linux]
Thread #&amp;lt;Thread:0x0000564a32b02110 example2.rb:12 run&amp;gt; is being hosted by 45998
Thread #&amp;lt;Thread:0x0000564a32afbdb0 example2.rb:13 run&amp;gt; is being hosted by 45998
Thread #&amp;lt;Thread:0x0000564a32af9f38 example2.rb:14 run&amp;gt; is being hosted by 45998
Sleeping for a bit...
Thread #&amp;lt;Thread:0x0000564a32af7e90 example2.rb:19 run&amp;gt; is being hosted by 46002&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;I hope you found this Ruby tidbit interesting!&lt;/p&gt;
&lt;/div&gt;</description>
        <pubDate>Sat, 26 Nov 2022 00:00:00 +0000</pubDate>
        <link>https://ivoanjo.me/blog/2022/11/26/ruby-reuses-native-threads/</link>
        <guid isPermaLink="true">https://ivoanjo.me/blog/2022/11/26/ruby-reuses-native-threads/</guid>
        <category>blog</category>
      </item>
      <item>
        <title>Hunting production memory leaks at RubyKaigi 2022</title>
        <description>&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Existing Ruby tooling is quite helpful when investigating memory leaks if and when we can reproduce them on our development machine or staging environment. But what about those cases when the memory leak only really shows up in Production? Perhaps over a long time period?&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Me and &lt;a href=&quot;https://twitter.com/KJTsanaktsidis&quot;&gt;@KJ Tsanaktsidis&lt;/a&gt; recently &lt;a href=&quot;https://rubykaigi.org/2022/presentations/KnuX.html#day2&quot;&gt;presented a talk at RubyKaigi 2022&lt;/a&gt; about two new Ruby gems&amp;#8201;&amp;#8212;&amp;#8201;&lt;a href=&quot;https://rubygems.org/gems/ruby_memprofiler_pprof&quot;&gt;&lt;code&gt;ruby_memprofiler_pprof&lt;/code&gt;&lt;/a&gt; and &lt;a href=&quot;https://rubygems.org/gems/backtracie&quot;&gt;&lt;code&gt;backtracie&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Together, they can be used to provide low-overhead heap sampling, enabling the investigation of Ruby memory leaks in production.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;You can find the video and slides for the talk below! And as always, feedback is very welcome!&lt;/p&gt;
&lt;/div&gt;
&lt;iframe width=&quot;736&quot; height=&quot;420&quot; src=&quot;https://www.youtube.com/embed/xoGJPtNp074&quot; title=&quot;YouTube video player&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; referrerpolicy=&quot;strict-origin-when-cross-origin&quot; allowfullscreen&gt;&lt;/iframe&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Slide deck:&lt;/p&gt;
&lt;/div&gt;
&lt;iframe src=&quot;https://docs.google.com/presentation/d/e/2PACX-1vQJOB3ex8kpDletIMwfhRFj2RKnuvstq2UryYZB_-GMJZ4X4drT0NkANlka84dN-8e92YwbH8PjD2zI/embed?start=false&amp;loop=false&amp;delayms=3000&quot; frameborder=&quot;0&quot; width=&quot;736&quot; height=&quot;420&quot; allowfullscreen=&quot;true&quot; mozallowfullscreen=&quot;true&quot; webkitallowfullscreen=&quot;true&quot;&gt;&lt;/iframe&gt;</description>
        <pubDate>Wed, 09 Nov 2022 00:00:00 +0000</pubDate>
        <link>https://ivoanjo.me/blog/2022/11/09/hunting-production-memory-leaks-rubykaigi-2022/</link>
        <guid isPermaLink="true">https://ivoanjo.me/blog/2022/11/09/hunting-production-memory-leaks-rubykaigi-2022/</guid>
        <category>blog</category>
      </item>
      <item>
        <title>Tracing Ruby's (Global) VM Lock</title>
        <description>&lt;div id=&quot;preamble&quot;&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&lt;em&gt;(&lt;a href=&quot;https://techracho.bpsinc.jp/hachi8833/2022_09_02/120530&quot;&gt;🇯🇵 Japanese translation&lt;/a&gt; thanks to &lt;a href=&quot;https://twitter.com/hachi8833&quot;&gt;@hachi8833&lt;/a&gt;)&lt;br&gt;
(&lt;a href=&quot;https://velog.io/@heka1024/%EB%B2%88%EC%97%AD-tracing-rubys-global-vm-lock&quot;&gt;🇰🇷 Korean translation&lt;/a&gt; thanks to &lt;a href=&quot;https://velog.io/@heka1024&quot;&gt;@heka1024&lt;/a&gt;)&lt;/em&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;I recently created a new Ruby gem: &lt;a href=&quot;https://github.com/ivoanjo/gvl-tracing&quot;&gt;the &lt;code&gt;gvl-tracing&lt;/code&gt; gem&lt;/a&gt;. This gem can be used to generate a visualization of what your Ruby threads are up to:&lt;/p&gt;
&lt;/div&gt;
&lt;img class=&quot;fullsize&quot; src=&quot;/img/gvl-tracing-1.png&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Click &lt;a href=&quot;javascript:;&quot; id=&quot;openExample1&quot;&gt;Open Example 1&lt;/a&gt; to explore this example.
Alternatively, download &lt;a href=&quot;https://ivoanjo.me/blog-extra/gvl-tracing/example1.json.gz&quot;&gt;example1.json.gz&lt;/a&gt; and open it with the &lt;a href=&quot;https://ui.perfetto.dev&quot;&gt;Perfetto UI&lt;/a&gt;.
Example code is from &lt;a href=&quot;https://github.com/ivoanjo/gvl-tracing/blob/master/examples/example1.rb&quot;&gt;example1.rb&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;script type=&quot;text/javascript&quot;&gt;
const openExample1 = document.getElementById(&apos;openExample1&apos;);
openExample1.onclick = () =&gt; fetchAndOpen(&apos;https://ivoanjo.me/blog-extra/gvl-tracing/example1.json.gz&apos;, openExample1);
&lt;/script&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Interested? Read on for details and how to generate your own traces.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;what-is-the-global-vm-lock&quot;&gt;what is the global vm lock?&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;The Ruby VM is a big program mainly written in the C programming language (we&amp;#8217;ll leave JRuby and TruffleRuby for another day 😁).&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;When you create threads in your Ruby application, the Ruby VM actually matches them, one to one, to operating system threads. (There&amp;#8217;s been some discussion on changing this at some point, which would be really interesting!)&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Thus, the Ruby VM a big &lt;em&gt;multi-threaded&lt;/em&gt; C program. In such programs, to avoid concurrency bugs, you need to adopt a strategy to ensure correctness when multiple threads are working at the same time. The Ruby developers adopted a strategy that they chose to call the &lt;strong&gt;Global VM Lock&lt;/strong&gt;, or &lt;strong&gt;GVL&lt;/strong&gt; for short.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;(As an aside, you may have heard the GVL instead being called the Global Interpreter Lock, or GIL. This term comes from the Python community; the Python interpreter uses something very similar to the GVL, for similar reasons. The Python developers just named it differently.)&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;The concept of the GVL is that whenever any thread is running Ruby code or otherwise needs to interact with Ruby VM structures, that thread needs to be holding the GVL, and no other thread can be doing the same. This ensures the correctness of the Ruby VM by making sure threads are not modifying objects and other critical VM structures at the same time.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;As a consequence of the GVL, at the level of our own Ruby code in our Ruby applications, we can observe concurrency (multiple Ruby threads can be working on multiple things at a time), but not parallelism (at any one time, only one Ruby thread is making progress).&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;actually-the-global-vm-lock-is-no-more&quot;&gt;actually, the global vm lock is no more!&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;One of the big features of the Ruby 3.0 release is the introduction of Ractors. Ractors are a new concurrency primitive that was introduced to both the language and VM (and that I experimented with in other posts, see &lt;a href=&quot;/blog/2021/02/14/ractor-experiments-safe-async/&quot;&gt;1&lt;/a&gt; and &lt;a href=&quot;/blog/2022/01/22/ractors-concurrency-podcast/&quot;&gt;2&lt;/a&gt;).&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;A key refactoring that was done when Ractors were introduced was making the Ruby VM go from having a single Global VM Lock to having multiple Global VM Locks, one per Ractor.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Now you may have spotted that naming something &lt;em&gt;Global&lt;/em&gt; but then having multiple of them is probably slightly confusing, and the Ruby core developers agree with you:  They actually don&amp;#8217;t call it the Global VM Lock anymore. Since &lt;a href=&quot;https://github.com/ruby/ruby/pull/5814&quot; class=&quot;bare&quot;&gt;https://github.com/ruby/ruby/pull/5814&lt;/a&gt;, they just call it &lt;code&gt;thread_sched&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;But, if your Ruby application is not using Ractors&amp;#8201;&amp;#8212;&amp;#8201;which I would bet is still the case for most applications&amp;#8201;&amp;#8212;&amp;#8201;then, for all intents and purposes, you still are at the mercy of a single &lt;code&gt;thread_sched&lt;/code&gt;, which acts exactly as the GVL did prior to Ruby 3.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Having gone through all that introduction, let&amp;#8217;s move on to the fun parts!&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;lets-talk-gvl-tracing&quot;&gt;let&amp;#8217;s talk gvl tracing&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Recently, &lt;a href=&quot;https://twitter.com/_byroot&quot;&gt;@_byroot&lt;/a&gt; (Jean Boussier) introduced an amazing new Ruby VM feature that gives users access to the state of the GVL. He called it the &lt;a href=&quot;https://github.com/ruby/ruby/pull/5500&quot;&gt;GVL Instrumentation API&lt;/a&gt;, and with it we can observe in detail what is happening with the GVL: when threads &lt;strong&gt;grab it&lt;/strong&gt;, when they &lt;strong&gt;release it&lt;/strong&gt;, &lt;strong&gt;how long&lt;/strong&gt; they hold on to it, and &lt;strong&gt;how long&lt;/strong&gt; other threads &lt;strong&gt;spend waiting for it&lt;/strong&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&lt;strong&gt;Update, 2023&lt;/strong&gt;: &lt;em&gt;I feel awful that I failed to notice that the &lt;a href=&quot;https://github.com/ruby/ruby/pull/5500&quot;&gt;GVL Instrumentation API PR&lt;/a&gt; stated that the feature was co-authored by &lt;a href=&quot;https://twitter.com/eightbitraptor&quot;&gt;@eightbitraptor&lt;/a&gt; (Matt Valentine-House) and I had originally omitted this detail. Big thanks to Matt as well! 🙇&lt;/em&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Ever since I learned of this new VM API I knew what I wanted to use it for: I wanted to build a visual timeline showing all this information.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Thus the &lt;a href=&quot;https://github.com/ivoanjo/gvl-tracing&quot;&gt;&lt;code&gt;gvl-tracing&lt;/code&gt; gem&lt;/a&gt; was born.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;And here&amp;#8217;s how it looks for a very simple Ruby application:&lt;/p&gt;
&lt;/div&gt;
&lt;img class=&quot;fullsize&quot; src=&quot;/img/gvl-tracing-2.png&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;You can play with this example yourself by clicking &lt;a href=&quot;javascript:;&quot; id=&quot;openExample2&quot;&gt;Open Example 2&lt;/a&gt;. Alternatively, download &lt;a href=&quot;https://ivoanjo.me/blog-extra/gvl-tracing/example2.json.gz&quot;&gt;example2.json.gz&lt;/a&gt; and open it with the &lt;a href=&quot;https://ui.perfetto.dev&quot;&gt;Perfetto UI&lt;/a&gt;.
Example code is from &lt;a href=&quot;https://github.com/ivoanjo/gvl-tracing/blob/master/examples/example2.rb&quot;&gt;&lt;code&gt;example2.rb&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;script type=&quot;text/javascript&quot;&gt;
const openExample2 = document.getElementById(&apos;openExample2&apos;);
openExample2.onclick = () =&gt; fetchAndOpen(&apos;https://ivoanjo.me/blog-extra/gvl-tracing/example2.json.gz&apos;, openExample2);
&lt;/script&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;So, what are we looking at here? We&amp;#8217;re looking at this Ruby code:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;CodeRay highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;require &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;gvl-tracing&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;

&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color:#06B;font-weight:bold&quot;&gt;fib&lt;/span&gt;(n)
  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;return&lt;/span&gt; n &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;if&lt;/span&gt; n &amp;lt;= &lt;span style=&quot;color:#00D&quot;&gt;1&lt;/span&gt;
  fib(n - &lt;span style=&quot;color:#00D&quot;&gt;1&lt;/span&gt;) + fib(n - &lt;span style=&quot;color:#00D&quot;&gt;2&lt;/span&gt;)
&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;end&lt;/span&gt;

&lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;GvlTracing&lt;/span&gt;.start(&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;example2.json&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;)

other_thread = &lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;Thread&lt;/span&gt;.new { fib(&lt;span style=&quot;color:#00D&quot;&gt;37&lt;/span&gt;) } &lt;span style=&quot;color:#777&quot;&gt;# runs in other thread&lt;/span&gt;
fib(&lt;span style=&quot;color:#00D&quot;&gt;37&lt;/span&gt;) &lt;span style=&quot;color:#777&quot;&gt;# runs in main thread&lt;/span&gt;

other_thread.join
&lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;GvlTracing&lt;/span&gt;.stop&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;In this app, two threads are competing for the GVL, and you can see how Ruby gives each of them 100ms to run at a time, before pausing and switching to the next one. The thread executing at any point is the one in the &lt;strong&gt;resumed&lt;/strong&gt; state; the other thread remains in the &lt;strong&gt;ready&lt;/strong&gt; state, meaning it has work to do, it&amp;#8217;s just waiting for its next turn holding the GVL.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;You can observe how in Ruby you usually get concurrency, but not parallelism: both threads have plenty of work to do, but they take turns executing, which makes them both take longer.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;If you add more threads you can start to see longer and longer gaps between when any given thread actually gets its turn. Here&amp;#8217;s the same example I presented at the beginning of this post reproduced again: with 3 threads competing for the GVL, each thread needs to wait for 200ms for each 100ms spent working.&lt;/p&gt;
&lt;/div&gt;
&lt;img class=&quot;fullsize&quot; src=&quot;/img/gvl-tracing-1.png&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;How would this application look if it was changed to use two different Ractors? As you may have suspected, you get real parallelism, with threads inside different Ractors acting independently:&lt;/p&gt;
&lt;/div&gt;
&lt;img class=&quot;fullsize&quot; src=&quot;/img/gvl-tracing-3.png&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;You can play with this example yourself by clicking
&lt;a href=&quot;javascript:;&quot; id=&quot;openExample3&quot;&gt;Open Example 3&lt;/a&gt;. Alternatively, download &lt;a href=&quot;https://ivoanjo.me/blog-extra/gvl-tracing/example3.json.gz&quot;&gt;example3.json.gz&lt;/a&gt; and open it with the &lt;a href=&quot;https://ui.perfetto.dev&quot;&gt;Perfetto UI&lt;/a&gt;.
Example code is from &lt;a href=&quot;https://github.com/ivoanjo/gvl-tracing/blob/master/examples/example3.rb&quot;&gt;&lt;code&gt;example3.rb&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;script type=&quot;text/javascript&quot;&gt;
const openExample3 = document.getElementById(&apos;openExample3&apos;);
openExample3.onclick = () =&gt; fetchAndOpen(&apos;https://ivoanjo.me/blog-extra/gvl-tracing/example3.json.gz&apos;, openExample3);
&lt;/script&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Yay, we established that ractors work! Both threads, each belonging to a different Ractor, run in parallel, unimpeded by the other.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;using-gvl-tracing-you-need-ruby-3-2&quot;&gt;using gvl-tracing: you need ruby 3.2+&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Ruby 3.2 was released in December 2022 and includes the GVL Instrumentation API. Ruby 3.3 and other future versions will also work as well!&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;using-gvl-tracing-how-to-try-it-on-your-own-applications&quot;&gt;using gvl-tracing: how to try it on your own applications&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;The gvl-tracing gem provides only provides two apis: &lt;code&gt;start&lt;/code&gt; and &lt;code&gt;stop&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;olist arabic&quot;&gt;
&lt;ol class=&quot;arabic&quot;&gt;
&lt;li&gt;
&lt;p&gt;Use start with a file name to start recording data: &lt;code&gt;GvlTracing.start(&apos;my-test-trace.json&apos;)&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Use stop to finish the recording: &lt;code&gt;GvlTracing.stop()&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;You can browse the resulting tracing file by loading it into the &lt;a href=&quot;https://ui.perfetto.dev&quot;&gt;Perfetto UI&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;share-your-traces-and-learnings&quot;&gt;share your traces and learnings!&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;We&amp;#8217;re still at the very beginning of exploring gvl tracing and what we can learn about the Ruby internals with it.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Find something interesting? Consider dropping it on a &lt;a href=&quot;https://gist.github.com/&quot;&gt;GitHub gist&lt;/a&gt; and sharing the link! I&amp;#8217;m &lt;a href=&quot;https://twitter.com/knux&quot;&gt;@KnuX on twitter&lt;/a&gt;, and feel free to reach out via e-mail as well.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Finally, I&amp;#8217;d like to thank &lt;a href=&quot;https://twitter.com/_byroot&quot;&gt;@_byroot&lt;/a&gt; (Jean Boussier) for the awesome new API, and I also recommend you check out &lt;a href=&quot;https://github.com/Shopify/gvltools&quot;&gt;Shopify&amp;#8217;s &lt;code&gt;gvltools&lt;/code&gt; gem&lt;/a&gt;, which provides other ways of measuring the impact of the GVL on your own applications.&lt;/p&gt;
&lt;/div&gt;
&lt;script type=&quot;text/javascript&quot;&gt;
const ORIGIN = &apos;https://ui.perfetto.dev&apos;;

async function fetchAndOpen(traceUrl, btnFetch) {
  const resp = await fetch(traceUrl);
  // TODO: Missing error checking
  const blob = await resp.blob();
  const arrayBuffer = await blob.arrayBuffer();
  openTrace(arrayBuffer, traceUrl, btnFetch);
}

function openTrace(arrayBuffer, traceUrl, btnFetch) {
  const win = window.open(ORIGIN);
  if (!win) {
    btnFetch.style.background = &apos;#f3ca63&apos;;
    btnFetch.onclick = () =&gt; openTrace(arrayBuffer, traceUrl, btnFetch);
    btnFetch.innerText = &apos;Popups blocked, click here to open the trace file&apos;;
    return;
  }

  const timer = setInterval(() =&gt; win.postMessage(&apos;PING&apos;, ORIGIN), 50);

  const onMessageHandler = (evt) =&gt; {
    if (evt.data !== &apos;PONG&apos;) return;

    // We got a PONG, the UI is ready.
    window.clearInterval(timer);
    window.removeEventListener(&apos;message&apos;, onMessageHandler);

    const reopenUrl = new URL(location.href);
    reopenUrl.hash = `#reopen=${traceUrl}`;
    win.postMessage({
      perfetto: {
        buffer: arrayBuffer,
        title: &apos;The Trace Title&apos;,
        url: reopenUrl.toString(),
    }}, ORIGIN);
  };

  window.addEventListener(&apos;message&apos;, onMessageHandler);
}

// This is triggered when following the link from the Perfetto UI&apos;s sidebar.
if (location.hash.startsWith(&apos;#reopen=&apos;)) {
 const traceUrl = location.hash.substr(8);
 fetchAndOpen(traceUrl);
}
&lt;/script&gt;
&lt;/div&gt;
&lt;/div&gt;</description>
        <pubDate>Sun, 17 Jul 2022 00:00:00 +0100</pubDate>
        <link>https://ivoanjo.me/blog/2022/07/17/tracing-ruby-global-vm-lock/</link>
        <guid isPermaLink="true">https://ivoanjo.me/blog/2022/07/17/tracing-ruby-global-vm-lock/</guid>
        <category>blog</category>
      </item>
      <item>
        <title>Talking Ruby Ractors and Concurrency at the Ruby Rogues podcast</title>
        <description>&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;I was recently invited to the Ruby Rogues podcast to talk about Ractors (the new Ruby concurrency primitive added in Ruby 3),
as well as Ruby concurrency in general.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;You can &lt;a href=&quot;https://aphid.fireside.fm/d/1437767933/609340ce-500a-41f5-9206-5dc980d135e2/260a6e79-105a-4d82-beb5-4b5d660cdc2b.mp3&quot;&gt;download the episode as an mp3&lt;/a&gt; or listen to it online at &lt;a href=&quot;https://topenddevs.com/podcasts/ruby-rogues/ractors-ft-ivo-anjo-ruby-527&quot; class=&quot;bare&quot;&gt;https://topenddevs.com/podcasts/ruby-rogues/ractors-ft-ivo-anjo-ruby-527&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;As usual, all feedback is welcome! Get in touch if you&amp;#8217;d like to talk about Ractors and Ruby concurrency&amp;#8201;&amp;#8212;&amp;#8201;I can literally talk for hours about it :)&lt;/p&gt;
&lt;/div&gt;</description>
        <pubDate>Sat, 22 Jan 2022 00:00:00 +0000</pubDate>
        <link>https://ivoanjo.me/blog/2022/01/22/ractors-concurrency-podcast/</link>
        <guid isPermaLink="true">https://ivoanjo.me/blog/2022/01/22/ractors-concurrency-podcast/</guid>
        <category>blog</category>
      </item>
      <item>
        <title>The unexpected cost of Ruby's NoMethodError exception</title>
        <description>&lt;div class=&quot;admonitionblock note&quot;&gt;
&lt;table&gt;
&lt;tr&gt;
&lt;td class=&quot;icon&quot;&gt;
&lt;div class=&quot;title&quot;&gt;💡&lt;/div&gt;
&lt;/td&gt;
&lt;td class=&quot;content&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;A fix for this performance gotcha has been merged for Ruby 3.3!&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;See &lt;a href=&quot;https://github.com/ruby/ruby/pull/6950&quot; class=&quot;bare&quot;&gt;https://github.com/ruby/ruby/pull/6950&lt;/a&gt; and &lt;a href=&quot;https://bugs.ruby-lang.org/issues/18285&quot; class=&quot;bare&quot;&gt;https://bugs.ruby-lang.org/issues/18285&lt;/a&gt; for details!&lt;/p&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;The &lt;code&gt;NoMethodError&lt;/code&gt; exception is how Ruby signals that the code tried to call a method that does not exist.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;CodeRay highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;class&lt;/span&gt; &lt;span style=&quot;color:#B06;font-weight:bold&quot;&gt;Example&lt;/span&gt;
&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;end&lt;/span&gt;

&lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;Example&lt;/span&gt;.new.foo
&lt;span style=&quot;color:#777&quot;&gt;# =&amp;gt; NoMethodError: undefined method `foo&apos; for #&amp;lt;Example:0x00005636879ce398&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Now, raising and rescuing exceptions is known to be slow (due to, among other things, expensive stack trace generation)
and thus it&amp;#8217;s pretty common knowledge that you should avoid having triggering too many of them in your production code.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;But&amp;#8230;&amp;#8203; have you ever considered that after you rescue an exception, getting or printing the &lt;code&gt;message&lt;/code&gt; from it may be expensive as well?&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;In particular, the &lt;code&gt;message&lt;/code&gt; from a &lt;code&gt;NoMethodError&lt;/code&gt; can be much costlier than for other Ruby exceptions.
Consider the following example:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;CodeRay highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;require &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;bundler/inline&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;

gemfile &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;do&lt;/span&gt;
  source &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;https://rubygems.org&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;

  gem &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;benchmark-ips&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;end&lt;/span&gt;

puts &lt;span style=&quot;color:#069&quot;&gt;RUBY_DESCRIPTION&lt;/span&gt;

&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;class&lt;/span&gt; &lt;span style=&quot;color:#B06;font-weight:bold&quot;&gt;GemInformation&lt;/span&gt;
  &lt;span style=&quot;color:#777&quot;&gt;# ...&lt;/span&gt;

  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color:#06B;font-weight:bold&quot;&gt;get_no_method_error&lt;/span&gt;
    method_does_not_exist
  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;rescue&lt;/span&gt; =&amp;gt; e
    e
  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;end&lt;/span&gt;

  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color:#06B;font-weight:bold&quot;&gt;get_runtime_error&lt;/span&gt;
    raise &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;Another Error&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;
  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;rescue&lt;/span&gt; =&amp;gt; e
    e
  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;end&lt;/span&gt;
&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;end&lt;/span&gt;

&lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;NO_METHOD_ERROR_INSTANCE&lt;/span&gt; = &lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;GemInformation&lt;/span&gt;.new.get_no_method_error
&lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;RUNTIME_ERROR_INSTANCE&lt;/span&gt; = &lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;GemInformation&lt;/span&gt;.new.get_runtime_error

&lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;Benchmark&lt;/span&gt;.ips &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;do&lt;/span&gt; |x|
  x.config(&lt;span style=&quot;color:#A60&quot;&gt;:time&lt;/span&gt; =&amp;gt; &lt;span style=&quot;color:#00D&quot;&gt;5&lt;/span&gt;, &lt;span style=&quot;color:#A60&quot;&gt;:warmup&lt;/span&gt; =&amp;gt; &lt;span style=&quot;color:#00D&quot;&gt;2&lt;/span&gt;)

  x.report(&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;no method error message cost&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;) { &lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;NO_METHOD_ERROR_INSTANCE&lt;/span&gt;.message }
  x.report(&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;runtime error message cost&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;) { &lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;RUNTIME_ERROR_INSTANCE&lt;/span&gt;.message }

  x.compare!
&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&amp;#8230;&amp;#8203;now let&amp;#8217;s run it:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre&gt;ruby 3.0.2p107 (2021-07-07 revision 0db68f0233) [x86_64-linux]

no method error message cost
                        180.215k (±14.4%) i/s -    885.250k in   5.015251s
runtime error message cost
                          6.806M (± 1.8%) i/s -     34.324M in   5.045347s

Comparison:
runtime error message cost:  6805678.3 i/s
no method error message cost:   180214.6 i/s - 37.76x  (± 0.00) slower&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;On my machine, getting the &lt;code&gt;message&lt;/code&gt; from a &lt;code&gt;NoMethodError&lt;/code&gt; is 37 times slower than from a regular &lt;code&gt;RuntimeException&lt;/code&gt;
in this example.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;But wait, it gets worse!
A common pattern in Ruby is to implement an &lt;code&gt;inspect&lt;/code&gt; method that prints extra information for debugging.
Let&amp;#8217;s see what happens to the benchmark when we augment our &lt;code&gt;Example&lt;/code&gt; class with one such method:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;CodeRay highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;class&lt;/span&gt; &lt;span style=&quot;color:#B06;font-weight:bold&quot;&gt;GemInformation&lt;/span&gt;
  &lt;span style=&quot;color:#777&quot;&gt;# ...&lt;/span&gt;

  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color:#06B;font-weight:bold&quot;&gt;get_no_method_error&lt;/span&gt;
    method_does_not_exist
  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;rescue&lt;/span&gt; =&amp;gt; e
    e
  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;end&lt;/span&gt;

  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color:#06B;font-weight:bold&quot;&gt;get_runtime_error&lt;/span&gt;
    raise &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;Another Error&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;
  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;rescue&lt;/span&gt; =&amp;gt; e
    e
  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;end&lt;/span&gt;

  &lt;span style=&quot;color:#777&quot;&gt;# &amp;lt;-- We added this!&lt;/span&gt;
  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color:#06B;font-weight:bold&quot;&gt;inspect&lt;/span&gt;
    &lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;Gem&lt;/span&gt;::&lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;Specification&lt;/span&gt;._all.inspect
  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;end&lt;/span&gt;
&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&amp;#8230;&amp;#8203;and the benchmark result:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre&gt;ruby 3.0.2p107 (2021-07-07 revision 0db68f0233) [x86_64-linux]

no method error message cost
                        115.390  (± 1.7%) i/s -    580.000  in   5.027822s
runtime error message cost
                          6.938M (± 0.5%) i/s -     35.334M in   5.092617s

Comparison:
runtime error message cost:  6938381.6 i/s
no method error message cost:      115.4 i/s - 60130.02x  (± 0.00) slower&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Yes, you read that well. Printing the message of a &lt;code&gt;NoMethodError&lt;/code&gt; just got 60130 times slower.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;TL;DR today I learned that while getting the &lt;code&gt;message&lt;/code&gt; from a &lt;code&gt;NoMethodError&lt;/code&gt; exception, &lt;strong&gt;Ruby will call &lt;code&gt;inspect&lt;/code&gt;
on the object that was missing the method&lt;/strong&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;This means that for instance, if your method has a very costly &lt;code&gt;inspect&lt;/code&gt; (because you really only thought it was
going to be called during development), you may have a bad time. For instance, if &lt;strong&gt;your object is a Rails controller,
or a similar object that holds and prints many references when being debugged&lt;/strong&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;We can confirm this with another small example:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;CodeRay highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;class&lt;/span&gt; &lt;span style=&quot;color:#B06;font-weight:bold&quot;&gt;Example&lt;/span&gt;
  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color:#06B;font-weight:bold&quot;&gt;inspect&lt;/span&gt;
    puts &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;#inspect got called&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;
  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;end&lt;/span&gt;
&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;end&lt;/span&gt;

&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;begin&lt;/span&gt;
  &lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;Example&lt;/span&gt;.new.foo
&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;rescue&lt;/span&gt; =&amp;gt; e
  puts &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;Error message is:&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;
  puts &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;background-color:hsla(0,0%,0%,0.07);color:black&quot;&gt;&lt;span style=&quot;font-weight:bold;color:#666&quot;&gt;#{&lt;/span&gt;e.message&lt;span style=&quot;font-weight:bold;color:#666&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&amp;#8230;&amp;#8203;and its output:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre&gt;Error message is:
#inspect got called
undefined method `foo&apos; for :Example&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;</description>
        <pubDate>Mon, 01 Nov 2021 00:00:00 +0000</pubDate>
        <link>https://ivoanjo.me/blog/2021/11/01/nomethoderror-ruby-cost/</link>
        <guid isPermaLink="true">https://ivoanjo.me/blog/2021/11/01/nomethoderror-ruby-cost/</guid>
        <category>blog</category>
      </item>
      <item>
        <title>Sunday Lol: Embedding images in commit logs</title>
        <description>&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Recently, I discovered the &lt;a href=&quot;https://github.com/dankamongmen/notcurses&quot;&gt;notcurses&lt;/a&gt; library, the latest in a long line of weird ways of abusing a terminal emulator.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;It provides a tool called &lt;code&gt;ncplayer&lt;/code&gt; which can be used to preview images and videos from the terminal.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;And then&amp;#8201;&amp;#8212;&amp;#8201;I decided to see if I could pipe its result into &lt;code&gt;git&lt;/code&gt;, and turn it into a commit message. Turns out that it works!&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;imageblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;img src=&quot;/img/image-in-commit.gif&quot; alt=&quot;image in commit&quot;&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;(P.s.: &lt;a href=&quot;https://github.com/dankamongmen/notcurses/issues/1342&quot;&gt;You&amp;#8217;ll need a recent version of &lt;code&gt;ncplayer&lt;/code&gt;&lt;/a&gt;)&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Of course, this is an awful thing: it won&amp;#8217;t work outside a terminal (definitely will not show up correctly on GitHub), it probably will break on different kinds of terminals, etc. So, just a curiosity :)&lt;/p&gt;
&lt;/div&gt;</description>
        <pubDate>Sun, 14 Mar 2021 00:00:00 +0000</pubDate>
        <link>https://ivoanjo.me/blog/2021/03/14/embedding-images-in-commit-logs/</link>
        <guid isPermaLink="true">https://ivoanjo.me/blog/2021/03/14/embedding-images-in-commit-logs/</guid>
        <category>blog</category>
      </item>
      <item>
        <title>Ruby Ractor Experiments: Safe async communication</title>
        <description>&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&lt;em&gt;(This post is also &lt;a href=&quot;https://techracho.bpsinc.jp/hachi8833/2021_10_14/112316&quot;&gt;available in 🇯🇵 Japanese&lt;/a&gt; thanks to &lt;a href=&quot;https://twitter.com/hachi8833&quot;&gt;@hachi8833&lt;/a&gt;.)&lt;/em&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Ractors (&lt;a href=&quot;https://rubyapi.org/3.0/o/ractor&quot;&gt;api documentation&lt;/a&gt;, &lt;a href=&quot;https://github.com/ruby/ruby/blob/master/doc/ractor.md&quot;&gt;design documentation&lt;/a&gt;) are a new concurrency abstraction for Ruby 3.0 inspired on the actor model.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;From the point of view of a Ractor that wants to send some information to another, communication can either be:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;em&gt;asynchrous&lt;/em&gt; (or &lt;em&gt;non-blocking&lt;/em&gt;): a Ractor can send information to another using &lt;a href=&quot;https://rubyapi.org/3.0/o/ractor#method-i-send&quot;&gt;&lt;code&gt;Ractor#send&lt;/code&gt;&lt;/a&gt;, placing it into an infinite queue that can be read by the destination Ractor with &lt;a href=&quot;https://rubyapi.org/3.0/o/ractor#method-c-receive&quot;&gt;&lt;code&gt;Ractor.receive&lt;/code&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;em&gt;synchronous&lt;/em&gt; (or &lt;em&gt;blocking&lt;/em&gt;): a Ractor can use &lt;a href=&quot;https://rubyapi.org/3.0/o/ractor#method-c-yield&quot;&gt;&lt;code&gt;Ractor.yield&lt;/code&gt;&lt;/a&gt; to block until another Ractor calls &lt;a href=&quot;https://rubyapi.org/3.0/o/ractor#method-i-take&quot;&gt;&lt;code&gt;Ractor#take&lt;/code&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Let&amp;#8217;s consider the async case: Let&amp;#8217;s say we want to send information to another Ractor, but don&amp;#8217;t want to block for it to finish processing it. What happens if the receiving Ractor is too slow to process the data?&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;CodeRay highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;receiver_ractor = &lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;Ractor&lt;/span&gt;.new &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;do&lt;/span&gt;
  loop &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;do&lt;/span&gt;
    message = &lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;Ractor&lt;/span&gt;.receive
    sleep &lt;span style=&quot;color:#00D&quot;&gt;1&lt;/span&gt;
    puts &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;Processed &lt;/span&gt;&lt;span style=&quot;background-color:hsla(0,0%,0%,0.07);color:black&quot;&gt;&lt;span style=&quot;font-weight:bold;color:#666&quot;&gt;#{&lt;/span&gt;message&lt;span style=&quot;font-weight:bold;color:#666&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;end&lt;/span&gt;
&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;end&lt;/span&gt;

counter = &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;
&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;while&lt;/span&gt; &lt;span style=&quot;color:#069&quot;&gt;true&lt;/span&gt;
  counter += &lt;span style=&quot;color:#00D&quot;&gt;1&lt;/span&gt;
  receiver_ractor.send(counter)
&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;imageblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;img src=&quot;/img/ractor/ractor-unbounded-memory.gif&quot; alt=&quot;ractor unbounded memory&quot;&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;br&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;As expected, if the receiver cannot keep up with the sender, more and more memory will be used, until the system memory is exhausted and the application crashes.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Looking at the Ractor API, there&amp;#8217;s no built-in way for the sender to check if the receiver is falling behind or not, so I came up with the following approach:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;CodeRay highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;receiver_ractor = &lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;Ractor&lt;/span&gt;.new &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;do&lt;/span&gt;
  processing_queue = &lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;Queue&lt;/span&gt;.new

  &lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;Thread&lt;/span&gt;.new &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;do&lt;/span&gt;
    sleep(&lt;span style=&quot;color:#00D&quot;&gt;1&lt;/span&gt;) &lt;span style=&quot;color:#777&quot;&gt;# simulate a slow start for this thread&lt;/span&gt;

    loop &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;do&lt;/span&gt;
      message = processing_queue.pop
      puts &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;Processed from queue: &lt;/span&gt;&lt;span style=&quot;background-color:hsla(0,0%,0%,0.07);color:black&quot;&gt;&lt;span style=&quot;font-weight:bold;color:#666&quot;&gt;#{&lt;/span&gt;message&lt;span style=&quot;font-weight:bold;color:#666&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
    &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;end&lt;/span&gt;
  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;end&lt;/span&gt;

  loop &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;do&lt;/span&gt;
    queue_size = processing_queue.size
    sender, message = &lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;Ractor&lt;/span&gt;.select(&lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;Ractor&lt;/span&gt;.current, &lt;span style=&quot;color:#606&quot;&gt;yield_value&lt;/span&gt;: queue_size)

    &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;if&lt;/span&gt; sender != &lt;span style=&quot;color:#A60&quot;&gt;:yield&lt;/span&gt;
      processing_queue &amp;lt;&amp;lt; message
      puts &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;Added message to queue: &lt;/span&gt;&lt;span style=&quot;background-color:hsla(0,0%,0%,0.07);color:black&quot;&gt;&lt;span style=&quot;font-weight:bold;color:#666&quot;&gt;#{&lt;/span&gt;message&lt;span style=&quot;font-weight:bold;color:#666&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
    &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;else&lt;/span&gt;
      puts &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;Sent queue status: &lt;/span&gt;&lt;span style=&quot;background-color:hsla(0,0%,0%,0.07);color:black&quot;&gt;&lt;span style=&quot;font-weight:bold;color:#666&quot;&gt;#{&lt;/span&gt;queue_size&lt;span style=&quot;font-weight:bold;color:#666&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
    &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;end&lt;/span&gt;
  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;end&lt;/span&gt;
&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;end&lt;/span&gt;

receiver_ractor.send(&lt;span style=&quot;color:#00D&quot;&gt;1&lt;/span&gt;)
receiver_ractor.send(&lt;span style=&quot;color:#00D&quot;&gt;2&lt;/span&gt;)
receiver_ractor.send(&lt;span style=&quot;color:#00D&quot;&gt;3&lt;/span&gt;)
puts &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;Finished submissions&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;

sleep(&lt;span style=&quot;color:#60E&quot;&gt;0.5&lt;/span&gt;)

receiver_ractor.take &lt;span style=&quot;color:#777&quot;&gt;# force refresh status&lt;/span&gt;
puts &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;Receiver queue length: &lt;/span&gt;&lt;span style=&quot;background-color:hsla(0,0%,0%,0.07);color:black&quot;&gt;&lt;span style=&quot;font-weight:bold;color:#666&quot;&gt;#{&lt;/span&gt;receiver_ractor.take&lt;span style=&quot;font-weight:bold;color:#666&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;

sleep(&lt;span style=&quot;color:#00D&quot;&gt;1&lt;/span&gt;)

receiver_ractor.take &lt;span style=&quot;color:#777&quot;&gt;# force refresh status&lt;/span&gt;
puts &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;Receiver queue length: &lt;/span&gt;&lt;span style=&quot;background-color:hsla(0,0%,0%,0.07);color:black&quot;&gt;&lt;span style=&quot;font-weight:bold;color:#666&quot;&gt;#{&lt;/span&gt;receiver_ractor.take&lt;span style=&quot;font-weight:bold;color:#666&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Here&amp;#8217;s how this looks when it executes:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre&gt;&amp;lt;internal:ractor&amp;gt;:267: warning: Ractor is experimental, and the behavior may change in future versions of Ruby! Also there are many implementation issues.
Finished submissions
Added message to queue: 1
Added message to queue: 2
Added message to queue: 3
Sent queue status: 3
Sent queue status: 3
Receiver queue length: 3
Processed from queue: 1
Processed from queue: 2
Processed from queue: 3
Sent queue status: 3
Sent queue status: 0
Receiver queue length: 0&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;And here&amp;#8217;s the timeline:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;olist arabic&quot;&gt;
&lt;ol class=&quot;arabic&quot;&gt;
&lt;li&gt;
&lt;p&gt;The main Ractor sends three messages to the &lt;code&gt;receiver_ractor&lt;/code&gt;, containing &lt;code&gt;1&lt;/code&gt;, &lt;code&gt;2&lt;/code&gt; and &lt;code&gt;3&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The main Ractor goes to sleep&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The receiver Ractor wakes up, reads the three messages, and redirects them to the &lt;code&gt;processing_queue&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The main Ractor wakes up, forces a refresh of the &lt;code&gt;queue_size&lt;/code&gt; (see below for more details)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The main Ractor calls &lt;code&gt;take&lt;/code&gt;, observes the &lt;code&gt;queue_size&lt;/code&gt; is 3&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The main Ractor goes to sleep&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The receiver Ractor&amp;#8217;s second thread wakes up and processes the three messages: &lt;code&gt;1&lt;/code&gt;, &lt;code&gt;2&lt;/code&gt; and &lt;code&gt;3&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The main Ractor wakes up, forces a refresh of the &lt;code&gt;queue_size&lt;/code&gt; (again)&amp;#8201;&amp;#8212;&amp;#8201;notice that this refresh was needed, because the value was outdated (goes from 3 to 0)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The main Ractor observes that the queue is empty!&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Inside the receiver Ractor, this strategy works as follows: There are now two threads. One of the threads uses &lt;a href=&quot;https://rubyapi.org/3.0/o/ractor#method-c-select&quot;&gt;&lt;code&gt;Ractor.select&lt;/code&gt;&lt;/a&gt; to do two things at once&amp;#8201;&amp;#8212;&amp;#8201;either receive new items for processing, putting them on a regular thread-safe queue, or returning back the current size of the queue. The second thread just processes items from the thread-safe queue.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;The sender can now either use &lt;code&gt;send&lt;/code&gt; to send items, or call &lt;code&gt;take&lt;/code&gt; twice to get the size of the queue. Why twice? Because this value is only refreshed before &lt;code&gt;select&lt;/code&gt; gets called, if a long time passes between &lt;code&gt;select&lt;/code&gt; is entered and any calls to &lt;code&gt;send&lt;/code&gt; or &lt;code&gt;take&lt;/code&gt;, this value can become outdated, as happened the example above. Calling &lt;code&gt;take&lt;/code&gt; twice in a row guarantees that we get a &quot;fresh&quot; value&amp;#8201;&amp;#8212;&amp;#8201;we know the value was just refreshed for the second &lt;code&gt;take&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Building atop this construction, we can implement a number of strategies for better communication between two Ractors. For instance, we can review the original example to make sure that the sender never runs &quot;too far ahead&quot; the receiver:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;CodeRay highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;receiver_ractor = &lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;Ractor&lt;/span&gt;.new &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;do&lt;/span&gt;
  processing_queue = &lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;Queue&lt;/span&gt;.new

  &lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;Thread&lt;/span&gt;.new &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;do&lt;/span&gt;
    loop &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;do&lt;/span&gt;
      message = processing_queue.pop
      sleep(&lt;span style=&quot;color:#00D&quot;&gt;1&lt;/span&gt;)
      puts &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;Processed &lt;/span&gt;&lt;span style=&quot;background-color:hsla(0,0%,0%,0.07);color:black&quot;&gt;&lt;span style=&quot;font-weight:bold;color:#666&quot;&gt;#{&lt;/span&gt;message&lt;span style=&quot;font-weight:bold;color:#666&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
    &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;end&lt;/span&gt;
  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;end&lt;/span&gt;

  loop &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;do&lt;/span&gt;
    queue_size = processing_queue.size
    sender, message = &lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;Ractor&lt;/span&gt;.select(&lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;Ractor&lt;/span&gt;.current, &lt;span style=&quot;color:#606&quot;&gt;yield_value&lt;/span&gt;: queue_size)

    &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;if&lt;/span&gt; sender != &lt;span style=&quot;color:#A60&quot;&gt;:yield&lt;/span&gt;
      processing_queue &amp;lt;&amp;lt; message
      puts &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;Added message to queue: &lt;/span&gt;&lt;span style=&quot;background-color:hsla(0,0%,0%,0.07);color:black&quot;&gt;&lt;span style=&quot;font-weight:bold;color:#666&quot;&gt;#{&lt;/span&gt;message&lt;span style=&quot;font-weight:bold;color:#666&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
    &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;else&lt;/span&gt;
      puts &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;Sent queue status: &lt;/span&gt;&lt;span style=&quot;background-color:hsla(0,0%,0%,0.07);color:black&quot;&gt;&lt;span style=&quot;font-weight:bold;color:#666&quot;&gt;#{&lt;/span&gt;queue_size&lt;span style=&quot;font-weight:bold;color:#666&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
    &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;end&lt;/span&gt;
  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;end&lt;/span&gt;
&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;end&lt;/span&gt;

counter = &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;
&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;while&lt;/span&gt; &lt;span style=&quot;color:#069&quot;&gt;true&lt;/span&gt;
  counter += &lt;span style=&quot;color:#00D&quot;&gt;1&lt;/span&gt;
  receiver_ractor.send(counter)

  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;if&lt;/span&gt; counter % &lt;span style=&quot;color:#00D&quot;&gt;10&lt;/span&gt; == &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;
    receiver_ractor.take &lt;span style=&quot;color:#777&quot;&gt;# force refresh status&lt;/span&gt;
    queue_size = receiver_ractor.take
    &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;if&lt;/span&gt; queue_size &amp;gt; &lt;span style=&quot;color:#00D&quot;&gt;5&lt;/span&gt;
      puts &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;Ractor is falling behind (&lt;/span&gt;&lt;span style=&quot;background-color:hsla(0,0%,0%,0.07);color:black&quot;&gt;&lt;span style=&quot;font-weight:bold;color:#666&quot;&gt;#{&lt;/span&gt;queue_size&lt;span style=&quot;font-weight:bold;color:#666&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt; elements unprocessed); sleeping for a while&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
      sleep(&lt;span style=&quot;color:#00D&quot;&gt;1&lt;/span&gt;) &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;while&lt;/span&gt; (receiver_ractor.take &amp;amp;&amp;amp; receiver_ractor.take &amp;gt; &lt;span style=&quot;color:#00D&quot;&gt;1&lt;/span&gt;)
    &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;end&lt;/span&gt;
  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;end&lt;/span&gt;
&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;And here&amp;#8217;s how it looks:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre&gt;&amp;lt;internal:ractor&amp;gt;:267: warning: Ractor is experimental, and the behavior may change in future versions of Ruby! Also there are many implementation issues.
Added message to queue: 1
Added message to queue: 2
Added message to queue: 3
Added message to queue: 4
Added message to queue: 5
Added message to queue: 6
Added message to queue: 7
Added message to queue: 8
Added message to queue: 9
Added message to queue: 10
Sent queue status: 10
Sent queue status: 9
Ractor is falling behind (9 elements unprocessed); sleeping for a while
Sent queue status: 9
Sent queue status: 9
Processed 1
Sent queue status: 9
Sent queue status: 8
Processed 2
Sent queue status: 8
Sent queue status: 7
Processed 3
Sent queue status: 7
Sent queue status: 6
Processed 4
Sent queue status: 6
Sent queue status: 5
Processed 5
Sent queue status: 5
Sent queue status: 4
Processed 6
Sent queue status: 4
Sent queue status: 3
Processed 7
Sent queue status: 3
Sent queue status: 2
Processed 8
Sent queue status: 2
Sent queue status: 1
Added message to queue: 11
Added message to queue: 12
Added message to queue: 13
Added message to queue: 14
Added message to queue: 15
Added message to queue: 16
Added message to queue: 17
Added message to queue: 18
Added message to queue: 19
Added message to queue: 20
Sent queue status: 11
Sent queue status: 11
Ractor is falling behind (11 elements unprocessed); sleeping for a while&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Sleeping is a very simplistic solution, but gets the job done. Other alternatives could be to switch to synchronous communication, or to instead submit the work to a different Ractor/code path.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;That&amp;#8217;s it for my first experiment with Ractors!&lt;/p&gt;
&lt;/div&gt;</description>
        <pubDate>Sun, 14 Feb 2021 00:00:00 +0000</pubDate>
        <link>https://ivoanjo.me/blog/2021/02/14/ractor-experiments-safe-async/</link>
        <guid isPermaLink="true">https://ivoanjo.me/blog/2021/02/14/ractor-experiments-safe-async/</guid>
        <category>blog</category>
      </item>
      <item>
        <title>Looking into Array memory usage in Ruby</title>
        <description>&lt;div id=&quot;preamble&quot;&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;What&amp;#8217;s the memory impact of keeping a number of objects in a Ruby array?
To answer this question, I decided to look into how exactly arrays are internally represented by Ruby.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Note that because we&amp;#8217;ll be looking at the Ruby internals, these results may and do change between Ruby versions; Nevertheless, the techniques used to measure overheads should be reusable for newer Ruby versions.
Note also that the results I present here only apply to the official Ruby &quot;MRI&quot; implementation, not to JRuby or TruffleRuby.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;So, let&amp;#8217;s dive in!&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;whats-in-a-ruby-object&quot;&gt;What&amp;#8217;s in a Ruby object?&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Ruby objects are represented on your application&amp;#8217;s heap memory using a &lt;a href=&quot;https://github.com/ruby/ruby/blob/ruby_3_0/gc.c#L557-L603&quot;&gt;&lt;code&gt;struct RVALUE&lt;/code&gt;&lt;/a&gt;. Note that this &lt;code&gt;struct&lt;/code&gt; is what is called a &lt;code&gt;union&lt;/code&gt;&amp;#8201;&amp;#8212;&amp;#8201;it can actually adopt a number of different layouts for keeping data inside of it, which is taken advantage of by the multiple Ruby built-in data structures. Note that this optimization is only available for parts of the VM implementation written in C, so unfortunately, regular Ruby objects cannot take advantage of these layouts to be more efficient.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Usually on modern machines this &lt;code&gt;struct RVALUE&lt;/code&gt; occupies 40 bytes. We can confirm this using the MRI Ruby-specific API &lt;a href=&quot;https://rubyapi.org/3.0/o/objectspace#method-c-memsize_of&quot;&gt;&lt;code&gt;ObjectSpace.memsize_of(obj)&lt;/code&gt;&lt;/a&gt;:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;CodeRay highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;require &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;objspace&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;

puts &lt;span style=&quot;color:#069&quot;&gt;RUBY_DESCRIPTION&lt;/span&gt;
puts &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;Size of new object: &lt;/span&gt;&lt;span style=&quot;background-color:hsla(0,0%,0%,0.07);color:black&quot;&gt;&lt;span style=&quot;font-weight:bold;color:#666&quot;&gt;#{&lt;/span&gt;&lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;ObjectSpace&lt;/span&gt;.memsize_of(&lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;Object&lt;/span&gt;.new)&lt;span style=&quot;font-weight:bold;color:#666&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;

&lt;span style=&quot;color:#777&quot;&gt;## Output:&lt;/span&gt;
&lt;span style=&quot;color:#777&quot;&gt;# ruby 3.0.0p0 (2020-12-25 revision 95aff21468) [x86_64-linux]&lt;/span&gt;
&lt;span style=&quot;color:#777&quot;&gt;# Size of new object: 40&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;As expected, a new object takes up 40 bytes. As you may have noticed, I&amp;#8217;ll be using Ruby 3.0.0 for the examples.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;lets-talk-arrays&quot;&gt;Let&amp;#8217;s talk Arrays&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;A Ruby array can actually take two different shapes&amp;#8201;&amp;#8212;&amp;#8201;let&amp;#8217;s call them &lt;em&gt;embedded&lt;/em&gt; and &lt;em&gt;extended&lt;/em&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Arrays in Ruby are represented internally using a &lt;a href=&quot;https://github.com/ruby/ruby/blob/ruby_3_0/include/ruby/internal/core/rarray.h#L87-L105&quot;&gt;&lt;code&gt;struct RArray&lt;/code&gt;&lt;/a&gt;; this is one of the layouts that can be adopted by a &lt;code&gt;struct RVALUE&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;the-embedded-shape&quot;&gt;The &lt;em&gt;embedded&lt;/em&gt; shape&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Because arrays do not need to store a lot of extra metadata (they are quite simple objects), there&amp;#8217;s leftover space in the 40 bytes of a &lt;code&gt;struct RVALUE&lt;/code&gt; to store a few array items in the struct itself. This is controlled by the &lt;a href=&quot;https://github.com/ruby/ruby/blob/ruby_3_0/include/ruby/internal/core/rbasic.h#L43&quot;&gt;&lt;code&gt;RARRAY_EMBED_LEN_MAX&lt;/code&gt;&lt;/a&gt; constant, which for the Ruby releases I checked, is set to 3.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;So whenever a new array is created with 0 to 3 elements, the &lt;em&gt;embedded&lt;/em&gt; shape which fits within 40 bytes is used:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;CodeRay highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;require &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;objspace&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;

puts &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;Size of empty array: &lt;/span&gt;&lt;span style=&quot;background-color:hsla(0,0%,0%,0.07);color:black&quot;&gt;&lt;span style=&quot;font-weight:bold;color:#666&quot;&gt;#{&lt;/span&gt;&lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;ObjectSpace&lt;/span&gt;.memsize_of([])&lt;span style=&quot;font-weight:bold;color:#666&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
puts &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;Size of array of size 1: &lt;/span&gt;&lt;span style=&quot;background-color:hsla(0,0%,0%,0.07);color:black&quot;&gt;&lt;span style=&quot;font-weight:bold;color:#666&quot;&gt;#{&lt;/span&gt;&lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;ObjectSpace&lt;/span&gt;.memsize_of([&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;a&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;])&lt;span style=&quot;font-weight:bold;color:#666&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
puts &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;Size of array of size 2: &lt;/span&gt;&lt;span style=&quot;background-color:hsla(0,0%,0%,0.07);color:black&quot;&gt;&lt;span style=&quot;font-weight:bold;color:#666&quot;&gt;#{&lt;/span&gt;&lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;ObjectSpace&lt;/span&gt;.memsize_of([&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;a&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;, &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;b&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;])&lt;span style=&quot;font-weight:bold;color:#666&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
puts &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;Size of array of size 3: &lt;/span&gt;&lt;span style=&quot;background-color:hsla(0,0%,0%,0.07);color:black&quot;&gt;&lt;span style=&quot;font-weight:bold;color:#666&quot;&gt;#{&lt;/span&gt;&lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;ObjectSpace&lt;/span&gt;.memsize_of([&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;a&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;, &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;b&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;, &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;c&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;])&lt;span style=&quot;font-weight:bold;color:#666&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;

&lt;span style=&quot;color:#777&quot;&gt;## Output:&lt;/span&gt;
&lt;span style=&quot;color:#777&quot;&gt;# Size of empty array: 40&lt;/span&gt;
&lt;span style=&quot;color:#777&quot;&gt;# Size of array of size 1: 40&lt;/span&gt;
&lt;span style=&quot;color:#777&quot;&gt;# Size of array of size 2: 40&lt;/span&gt;
&lt;span style=&quot;color:#777&quot;&gt;# Size of array of size 3: 40&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;What happens after the fourth element?&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;the-extended-shape&quot;&gt;The &lt;em&gt;extended&lt;/em&gt; shape&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;From the fourth element on, the &lt;em&gt;extended&lt;/em&gt; shape for the Array is used instead: a separate C array is allocated in memory to keeps pointers to each array element.
A Ruby array using this shape will now occupy 40 bytes (for the &lt;code&gt;struct RVALUE&lt;/code&gt;) + number of elements * machine word size (usually 8 bytes&amp;#8201;&amp;#8212;&amp;#8201;64 bits).&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;So for an array with four elements we&amp;#8217;ll have: 40 + 4 * 8 = 72 bytes being used, and so on for the next elements:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;CodeRay highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;require &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;objspace&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;

puts &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;Size of array of size 4: &lt;/span&gt;&lt;span style=&quot;background-color:hsla(0,0%,0%,0.07);color:black&quot;&gt;&lt;span style=&quot;font-weight:bold;color:#666&quot;&gt;#{&lt;/span&gt;&lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;ObjectSpace&lt;/span&gt;.memsize_of([&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;a&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;, &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;b&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;, &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;c&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;, &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;d&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;])&lt;span style=&quot;font-weight:bold;color:#666&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
puts &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;Size of array of size 5: &lt;/span&gt;&lt;span style=&quot;background-color:hsla(0,0%,0%,0.07);color:black&quot;&gt;&lt;span style=&quot;font-weight:bold;color:#666&quot;&gt;#{&lt;/span&gt;&lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;ObjectSpace&lt;/span&gt;.memsize_of([&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;a&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;, &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;b&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;, &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;c&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;, &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;d&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;, &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;e&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;])&lt;span style=&quot;font-weight:bold;color:#666&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;

&lt;span style=&quot;color:#777&quot;&gt;## Output:&lt;/span&gt;
&lt;span style=&quot;color:#777&quot;&gt;# Size of array of size 4: 72&lt;/span&gt;
&lt;span style=&quot;color:#777&quot;&gt;# Size of array of size 5: 80&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Up until now I&amp;#8217;ve been showing how much space is used when an array is pre-created with some number of elements. But does all of this still apply we modify an existing array?&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;And what does Ruby really do when an array needs to grow or shrink?&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;growing-an-array&quot;&gt;Growing an Array&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;What happens when an array needs to grow to accommodate new elements? As expected, an &lt;em&gt;embedded&lt;/em&gt; array will keep on using that shape while it can:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;CodeRay highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;require &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;objspace&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;

example_array = []
puts &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;Size of example array: &lt;/span&gt;&lt;span style=&quot;background-color:hsla(0,0%,0%,0.07);color:black&quot;&gt;&lt;span style=&quot;font-weight:bold;color:#666&quot;&gt;#{&lt;/span&gt;&lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;ObjectSpace&lt;/span&gt;.memsize_of(example_array)&lt;span style=&quot;font-weight:bold;color:#666&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
example_array &amp;lt;&amp;lt; &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;a&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;
puts &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;Size of example array: &lt;/span&gt;&lt;span style=&quot;background-color:hsla(0,0%,0%,0.07);color:black&quot;&gt;&lt;span style=&quot;font-weight:bold;color:#666&quot;&gt;#{&lt;/span&gt;&lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;ObjectSpace&lt;/span&gt;.memsize_of(example_array)&lt;span style=&quot;font-weight:bold;color:#666&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
example_array &amp;lt;&amp;lt; &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;b&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;
puts &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;Size of example array: &lt;/span&gt;&lt;span style=&quot;background-color:hsla(0,0%,0%,0.07);color:black&quot;&gt;&lt;span style=&quot;font-weight:bold;color:#666&quot;&gt;#{&lt;/span&gt;&lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;ObjectSpace&lt;/span&gt;.memsize_of(example_array)&lt;span style=&quot;font-weight:bold;color:#666&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
example_array &amp;lt;&amp;lt; &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;c&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;
puts &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;Size of example array: &lt;/span&gt;&lt;span style=&quot;background-color:hsla(0,0%,0%,0.07);color:black&quot;&gt;&lt;span style=&quot;font-weight:bold;color:#666&quot;&gt;#{&lt;/span&gt;&lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;ObjectSpace&lt;/span&gt;.memsize_of(example_array)&lt;span style=&quot;font-weight:bold;color:#666&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;

&lt;span style=&quot;color:#777&quot;&gt;## Output:&lt;/span&gt;
&lt;span style=&quot;color:#777&quot;&gt;# Size of example array: 40&lt;/span&gt;
&lt;span style=&quot;color:#777&quot;&gt;# Size of example array: 40&lt;/span&gt;
&lt;span style=&quot;color:#777&quot;&gt;# Size of example array: 40&lt;/span&gt;
&lt;span style=&quot;color:#777&quot;&gt;# Size of example array: 40&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;But you may be surprised to see what happens after we add the next element:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;CodeRay highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;require &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;objspace&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;

example_array = [&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;a&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;, &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;b&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;, &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;c&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;]
puts &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;Size of example array: &lt;/span&gt;&lt;span style=&quot;background-color:hsla(0,0%,0%,0.07);color:black&quot;&gt;&lt;span style=&quot;font-weight:bold;color:#666&quot;&gt;#{&lt;/span&gt;&lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;ObjectSpace&lt;/span&gt;.memsize_of(example_array)&lt;span style=&quot;font-weight:bold;color:#666&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;

example_array &amp;lt;&amp;lt; &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;d&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;
puts &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;Size of example array: &lt;/span&gt;&lt;span style=&quot;background-color:hsla(0,0%,0%,0.07);color:black&quot;&gt;&lt;span style=&quot;font-weight:bold;color:#666&quot;&gt;#{&lt;/span&gt;&lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;ObjectSpace&lt;/span&gt;.memsize_of(example_array)&lt;span style=&quot;font-weight:bold;color:#666&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;

&lt;span style=&quot;color:#777&quot;&gt;## Output:&lt;/span&gt;
&lt;span style=&quot;color:#777&quot;&gt;# Size of example array: 40&lt;/span&gt;
&lt;span style=&quot;color:#777&quot;&gt;# Size of example array: 200&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Why 200 bytes and not the 72 bytes we saw above?&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;This is the Ruby VM doing a trade-off between space (memory) and time (CPU processing): expanding the underlying C array entails creating a new one with a bigger size, copying the existing elements onto this new array, and then finally adding the new element.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Because this is an expensive operation, Ruby tries to avoid doing it on every insertion, and thus instead adds some slack: in this case it jumps from 3 to (200 - 40) / 8 = 20 elements. Thus the trade-off: to avoid doing this expansion on every insertion (reduce CPU processing) we use up more space (memory) than may end up being actually needed.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;What if we know in advance how many more elements we want to add?&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&lt;code&gt;Array.new(capacity)&lt;/code&gt; allows an array to be created with a given capacity. If, after that, you only work within this capacity, the array will keep its size.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;If, on the other hand, you&amp;#8217;d like to resize an array sometime after creating it, that&amp;#8217;s not possible. An array can only be sized-to-fit at creation, and it&amp;#8217;s not possible to ask Ruby to resize it to a specific size afterwards&amp;#8201;&amp;#8212;&amp;#8201;Ruby will self-manage the size of the underlying memory.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;shrinking-an-array&quot;&gt;Shrinking an Array&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;When elements are removed from an array, does it ever shrink? The answer is yes, but again Ruby will try to avoid shrinking/growing the array too often, so it will always leave some slack:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;CodeRay highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;require &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;objspace&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;

example_array = [&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;a&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;, &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;b&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;, &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;c&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;]
example_array &amp;lt;&amp;lt; &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;d&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;
puts &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;Size of example array: &lt;/span&gt;&lt;span style=&quot;background-color:hsla(0,0%,0%,0.07);color:black&quot;&gt;&lt;span style=&quot;font-weight:bold;color:#666&quot;&gt;#{&lt;/span&gt;&lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;ObjectSpace&lt;/span&gt;.memsize_of(example_array)&lt;span style=&quot;font-weight:bold;color:#666&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;

example_array.pop
puts &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;Size of example array: &lt;/span&gt;&lt;span style=&quot;background-color:hsla(0,0%,0%,0.07);color:black&quot;&gt;&lt;span style=&quot;font-weight:bold;color:#666&quot;&gt;#{&lt;/span&gt;&lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;ObjectSpace&lt;/span&gt;.memsize_of(example_array)&lt;span style=&quot;font-weight:bold;color:#666&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;

&lt;span style=&quot;color:#777&quot;&gt;## Output:&lt;/span&gt;
&lt;span style=&quot;color:#777&quot;&gt;# Size of example array: 200&lt;/span&gt;
&lt;span style=&quot;color:#777&quot;&gt;# Size of example array: 104&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;To force an array to shrink to size, you can use &lt;a href=&quot;https://rubyapi.org/3.0/o/array#method-i-compact&quot;&gt;&lt;code&gt;Array#compact&lt;/code&gt;&lt;/a&gt;. This returns a new sized-to-fit array:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;CodeRay highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;require &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;objspace&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;

example_array = [&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;a&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;, &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;b&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;, &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;c&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;]
example_array &amp;lt;&amp;lt; &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;d&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;
puts &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;Size of example array: &lt;/span&gt;&lt;span style=&quot;background-color:hsla(0,0%,0%,0.07);color:black&quot;&gt;&lt;span style=&quot;font-weight:bold;color:#666&quot;&gt;#{&lt;/span&gt;&lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;ObjectSpace&lt;/span&gt;.memsize_of(example_array)&lt;span style=&quot;font-weight:bold;color:#666&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;

compact_array = example_array.compact
puts &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;Size of example array: &lt;/span&gt;&lt;span style=&quot;background-color:hsla(0,0%,0%,0.07);color:black&quot;&gt;&lt;span style=&quot;font-weight:bold;color:#666&quot;&gt;#{&lt;/span&gt;&lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;ObjectSpace&lt;/span&gt;.memsize_of(compact_array)&lt;span style=&quot;font-weight:bold;color:#666&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;

&lt;span style=&quot;color:#777&quot;&gt;## Output:&lt;/span&gt;
&lt;span style=&quot;color:#777&quot;&gt;# Size of example array: 200&lt;/span&gt;
&lt;span style=&quot;color:#777&quot;&gt;# Size of example array: 72&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;That&amp;#8217;s it for our tour of Ruby arrays!&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&lt;strong&gt;Updated 2022-09&lt;/strong&gt;: Updated post to call shapes &lt;em&gt;embedded&lt;/em&gt;/&lt;em&gt;extended&lt;/em&gt; rather than &lt;em&gt;inline&lt;/em&gt;/&lt;em&gt;regular&lt;/em&gt; as the former are commonly used in the Ruby community.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;</description>
        <pubDate>Thu, 11 Feb 2021 00:00:00 +0000</pubDate>
        <link>https://ivoanjo.me/blog/2021/02/11/looking-into-array-memory-usage/</link>
        <guid isPermaLink="true">https://ivoanjo.me/blog/2021/02/11/looking-into-array-memory-usage/</guid>
        <category>blog</category>
      </item>
      <item>
        <title>What I've been reading: December+January 2021 Edition</title>
        <description>&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;This blog post is a continuation of my &lt;a href=&quot;/blog/2020/11/03/what-ive-been-reading-october-2020-edition/&quot;&gt;ongoing experiment&lt;/a&gt; with collecting and summing up the best technical (with a bit of non-technical) stuff I&amp;#8217;ve read and watched recently.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;(P.s.: &lt;a href=&quot;/blog/2020/12/01/creating-a-newsletter/&quot;&gt;You can now receive my blog as a newsletter!&lt;/a&gt;)&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Happy reading!&lt;/p&gt;
&lt;/div&gt;
&lt;h3 id=&quot;1-painting-a-selfie-girl-with-maths-youtube-video&quot; class=&quot;discrete&quot;&gt;1. &lt;a href=&quot;https://www.youtube.com/watch?v=8&amp;#8212;&amp;#8203;5LwHRhjk&quot;&gt;&lt;em&gt;Painting a Selfie Girl, with Maths&lt;/em&gt;&lt;/a&gt; (YouTube Video):&lt;/h3&gt;
&lt;iframe width=&quot;736&quot; height=&quot;420&quot; src=&quot;https://www.youtube.com/embed/8--5LwHRhjk&quot; title=&quot;YouTube video player&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; referrerpolicy=&quot;strict-origin-when-cross-origin&quot; allowfullscreen&gt;&lt;/iframe&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&lt;a href=&quot;https://www.iquilezles.org/&quot;&gt;Inigo Quilez&lt;/a&gt; is a master computer graphics artist, and in this video he paints a picture of a girl taking a selfie, using only code. Even cooler, the code is available on the &lt;a href=&quot;https://www.shadertoy.com/view/WsSBzh&quot;&gt;Shadertoy&lt;/a&gt; website, where you can play with it &lt;strong&gt;in real-time&lt;/strong&gt;, &lt;em&gt;in your browser&lt;/em&gt;!&lt;/p&gt;
&lt;/div&gt;
&lt;h3 id=&quot;2-lifi-product&quot; class=&quot;discrete&quot;&gt;2. &lt;a href=&quot;https://purelifi.com/lifi-technology/&quot;&gt;&lt;em&gt;LiFi&lt;/em&gt;&lt;/a&gt; (Product):&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Is the future of wireless networking the use of light? pureLiFi is proposing the use of light modulation (aka blinking lights so fast that the human eye can&amp;#8217;t spot them) as a solution to some of our wifi woes.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;The idea seems interesting, and I really got a laugh out of their FAQ:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;quoteblock&quot;&gt;
&lt;blockquote&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Q: Will LiFi work in my pocket?&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;A: No LiFi does not work in your pocket, unless you have a transparent suit.&lt;/p&gt;
&lt;/div&gt;
&lt;/blockquote&gt;
&lt;/div&gt;
&lt;h3 id=&quot;3-nonlinear-increases-in-complexity-make-unification-excruciating-blog-post&quot; class=&quot;discrete&quot;&gt;3. &lt;a href=&quot;https://jessitron.com/2020/12/06/unification-excruciating/&quot;&gt;&lt;em&gt;Nonlinear increases in complexity make unification excruciating&lt;/em&gt;&lt;/a&gt; (Blog Post):&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Jessica Kerr makes a really good case for not allowing the allure of the &quot;magical all-encompassing unified platform&quot; to limit innovation and raise maintenance costs.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;A key observation is that the cost of changes to a system grows non-linearly; complexity grows way faster than value.&lt;/p&gt;
&lt;/div&gt;
&lt;h3 id=&quot;4-on-the-metal-kenneth-finnegan-podcast-episode&quot; class=&quot;discrete&quot;&gt;4. &lt;a href=&quot;https://oxide.computer/podcast/on-the-metal-6-kenneth-finnegan/&quot;&gt;&lt;em&gt;On the Metal: Kenneth Finnegan&lt;/em&gt;&lt;/a&gt; (Podcast Episode):&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;The &lt;a href=&quot;https://oxide.computer/podcast/&quot;&gt;&lt;em&gt;On the Metal&lt;/em&gt;&lt;/a&gt; podcast has quite entertaining guests talking about their background on hardware and software design, usually with a good amount of discussion of how computing has evolved and what we can learn from it.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;On this episode, Kenneth Finnegan and a few friends decided to start running their own internet service provider &lt;em&gt;for the lulz&lt;/em&gt;, and things went really deep from there. If you&amp;#8217;ve ever wondered how some of the &lt;a href=&quot;https://youtu.be/iDbyYGrswtg&quot;&gt;elders of the internet&lt;/a&gt; keep the lights on, this episode is for you.&lt;/p&gt;
&lt;/div&gt;
&lt;h3 id=&quot;5-java-flight-recorder-will-support-event-throttling-erm-jira-ticket&quot; class=&quot;discrete&quot;&gt;5. &lt;a href=&quot;https://bugs.openjdk.java.net/browse/JDK-8257602&quot;&gt;&lt;em&gt;Java Flight Recorder will support event throttling&lt;/em&gt;&lt;/a&gt; (Erm&amp;#8230;&amp;#8203; JIRA ticket):&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;This new feature will enable low-overhead always-on memory allocation tracking for Java. Previously, trying to get this information out of the JVM could lead to a lot of overhead.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;(Compared to the other items, this is a bit specific, but hey, it&amp;#8217;s pretty cool that this feature was contributed by my colleague Jaroslav Bachorík!)&lt;/p&gt;
&lt;/div&gt;
&lt;h3 id=&quot;6-napkin-math-blog-posts&quot; class=&quot;discrete&quot;&gt;6. &lt;a href=&quot;https://sirupsen.com/napkin/&quot;&gt;&lt;em&gt;Napkin Math&lt;/em&gt;&lt;/a&gt; (Blog Posts):&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Simon Hørup Eskildsen explores how with a bit of math that fits on a napkin, one can explore problem spaces and estimate rough system performance.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;It&amp;#8217;s quite insightful to follow along, and even more interesting to try to solve the problems as well.&lt;/p&gt;
&lt;/div&gt;
&lt;h3 id=&quot;7-no-cookie-for-you-blog-post&quot; class=&quot;discrete&quot;&gt;7. &lt;a href=&quot;https://github.blog/2020-12-17-no-cookie-for-you/&quot;&gt;&lt;em&gt;No cookie for you&lt;/em&gt;&lt;/a&gt; (Blog Post):&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;GitHub solved the problem of the annoying &quot;allow cookie banners&quot; that try to tackle us on every website.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Their great solution: They removed all tracking cookies. For all customers. Even outside the EU. That&amp;#8217;s it. No more list of 2000+ advertisers.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Not a solution for every business, but something that should really be applauded. I&amp;#8217;ve removed google tracking and disqus comments from the blog recently as well; good riddance.&lt;/p&gt;
&lt;/div&gt;
&lt;h3 id=&quot;8-ditherpunk-the-article-i-wish-i-had-about-monochrome-image-dithering-blog-post&quot; class=&quot;discrete&quot;&gt;8. &lt;a href=&quot;https://surma.dev/things/ditherpunk/&quot;&gt;&lt;em&gt;Ditherpunk — The article I wish I had about monochrome image dithering&lt;/em&gt;&lt;/a&gt; (Blog Post):&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&lt;em&gt;Dithering&lt;/em&gt; is a technique for choosing and placing colors from a limited palette in such a way that our brain &quot;sees&quot; more colors than really are there.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;For instance, there are a lot less colors being used in this screenshot of Monkey Island than may appear at first sight:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;imageblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;img src=&quot;/img/monkeyisland.png&quot; alt=&quot;monkeyisland&quot;&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;This amazing blog post introduces and explores how dithering works, going from the simplest algorithm to nicer implementations that produce better results.&lt;/p&gt;
&lt;/div&gt;
&lt;h3 id=&quot;9-towards-continuous-performance-regression-testing-blog-post&quot; class=&quot;discrete&quot;&gt;9. &lt;a href=&quot;https://www.morling.dev/blog/towards-continuous-performance-regression-testing/&quot;&gt;&lt;em&gt;Towards Continuous Performance Regression Testing&lt;/em&gt;&lt;/a&gt; (Blog Post):&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;This blog post introduces &lt;a href=&quot;https://github.com/gunnarmorling/jfrunit&quot;&gt;JfrUnit&lt;/a&gt;, a Java tool that enables unit tests to integrate with the Java Flight Recorder.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Using JfrUnit, a developer can augment tests with checks that validate how much memory was allocated, how much I/O was performed, etc.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Although I expect that too strict usage of such a toolkit can lead to a somewhat brittle test suite that can break with JDK and OS, the concept does seem quite powerful when used correctly.&lt;/p&gt;
&lt;/div&gt;
&lt;h3 id=&quot;10-performance-summit-london-edition-ii-online-event&quot; class=&quot;discrete&quot;&gt;10. &lt;a href=&quot;https://performancesummitlondonedition.splashthat.com/&quot;&gt;&lt;em&gt;Performance Summit London Edition II&lt;/em&gt;&lt;/a&gt; (Online Event):&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;This free online event gathers engineers that are working on tackling performance challenges&amp;#8201;&amp;#8212;&amp;#8201;from building tooling to making massive systems scale.&lt;/p&gt;
&lt;/div&gt;
&lt;h3 id=&quot;11-programming-idioms-cheatsheets-website&quot; class=&quot;discrete&quot;&gt;11. &lt;a href=&quot;https://programming-idioms.org/about#about-block-cheatsheets&quot;&gt;Programming-Idioms Cheatsheets&lt;/a&gt; (Website):&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;This website allows you to pick one or more programming languages, and to get a cheat sheet of now to perform many common operations in those languages.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;For instance&amp;#8201;&amp;#8212;&amp;#8201;here&amp;#8217;s a pair that I quite like: &lt;a href=&quot;https://programming-idioms.org/cheatsheet/Ruby/Kotlin&quot;&gt;Ruby and Kotlin&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;hr&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;More soon! I gathered quite a few links these past couple of months :)&lt;/p&gt;
&lt;/div&gt;</description>
        <pubDate>Sat, 06 Feb 2021 00:00:00 +0000</pubDate>
        <link>https://ivoanjo.me/blog/2021/02/06/what-ive-been-reading-december-january-2021-edition-part-i/</link>
        <guid isPermaLink="true">https://ivoanjo.me/blog/2021/02/06/what-ive-been-reading-december-january-2021-edition-part-i/</guid>
        <category>blog</category>
      </item>
      <item>
        <title>What I've been reading: November 2020 Edition</title>
        <description>&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;This blog post is a continuation of my &lt;a href=&quot;/blog/2020/11/03/what-ive-been-reading-october-2020-edition/&quot;&gt;ongoing experiment&lt;/a&gt; with collecting and summing up the best technical (with a bit of non-technical) stuff I&amp;#8217;ve read and watched this past month.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;I&amp;#8217;m still experimenting with the format, so feedback is definitely welcome.&lt;br&gt;
(P.s.: &lt;a href=&quot;/blog/2020/12/01/creating-a-newsletter/&quot;&gt;You can now subscribe to my newsletter too!&lt;/a&gt;)&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;This month I&amp;#8217;ve gone a bit down the rabbit hole of the GDC (Game Developers Conference) &lt;a href=&quot;https://www.youtube.com/channel/UC0JB7TSe49lg56u6qH8y_MQ&quot;&gt;youtube archives&lt;/a&gt;.
Even if you&amp;#8217;re not interested in the gaming industry, there&amp;#8217;s amazing engineering and design efforts going on there, and there&amp;#8217;s a lot to be learned from the top companies in that field.&lt;/p&gt;
&lt;/div&gt;
&lt;h3 id=&quot;1-magic-the-gathering-twenty-years-twenty-lessons-learned-conference-talk&quot; class=&quot;discrete&quot;&gt;1. &lt;a href=&quot;https://www.youtube.com/watch?v=QHHg99hwQGY&quot;&gt;&lt;em&gt;Magic: the Gathering: Twenty Years, Twenty Lessons Learned&lt;/em&gt;&lt;/a&gt; (Conference Talk):&lt;/h3&gt;
&lt;div class=&quot;imageblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;a class=&quot;image&quot; href=&quot;https://www.youtube.com/watch?v=QHHg99hwQGY&quot;&gt;&lt;img src=&quot;/img/magic-20-years-lessons.png&quot; alt=&quot;magic 20 years lessons&quot;&gt;&lt;/a&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;This talk is a masterclass in design. Replace &lt;em&gt;player&lt;/em&gt; with &lt;strong&gt;user&lt;/strong&gt; and &lt;em&gt;game&lt;/em&gt; with &lt;strong&gt;product&lt;/strong&gt; and every single item still applies and is incredibly relevant. If you watch one talk I link to in this post, make it this one!&lt;/p&gt;
&lt;/div&gt;
&lt;h3 id=&quot;2-up-sht-creek-pro-tips-for-managing-the-unmanageable-project-conference-talk&quot; class=&quot;discrete&quot;&gt;2. &lt;a href=&quot;https://www.youtube.com/watch?v=dNlEZZlmIcw&quot;&gt;&lt;em&gt;Up Sh*t Creek: Pro Tips for Managing the Unmanageable Project&lt;/em&gt;&lt;/a&gt; (Conference Talk):&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;The presenter describes her experience on being brought into software (game) projects that are spiraling out of control, and their approach and recommendations to &quot;turn the ship around&quot; and make the project a success.&lt;/p&gt;
&lt;/div&gt;
&lt;h3 id=&quot;3-50-game-camera-mistakes-conference-talk&quot; class=&quot;discrete&quot;&gt;3. &lt;a href=&quot;https://www.youtube.com/watch?v=C7307qRmlMI&quot;&gt;&lt;em&gt;50 Game Camera Mistakes&lt;/em&gt;&lt;/a&gt; (Conference Talk):&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;This talk is not generally applicable as the others above, but a through analysis into how much goes into making something that &lt;em&gt;seems as simple as&lt;/em&gt; &quot;the camera&quot; behave in such a way that you never even notice it is there.&lt;/p&gt;
&lt;/div&gt;
&lt;h3 id=&quot;4-game-balance-concepts-blog-posts&quot; class=&quot;discrete&quot;&gt;4. &lt;em&gt;Game Balance Concepts&lt;/em&gt; (Blog Posts):&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;I&amp;#8217;ve ran into this collection of blog posts by Ian Schreiber for his class on Game Balancing. I&amp;#8217;m still going through them, but I really liked &lt;a href=&quot;https://gamebalanceconcepts.wordpress.com/2010/07/28/level-4-probability-and-randomness/&quot;&gt;&lt;em&gt;Level 4: Probability and Randomness&lt;/em&gt;&lt;/a&gt; as a great refresher on probability (and got stuck on the monty hall problem as well), and &lt;a href=&quot;https://gamebalanceconcepts.wordpress.com/2010/07/21/level-3-transitive-mechanics-and-cost-curves/&quot;&gt;&lt;em&gt;Level 3: Transitive Mechanics and Cost Curves&lt;/em&gt;&lt;/a&gt; with a really interesting analysis of how costs work in Magic: The Gathering.&lt;/p&gt;
&lt;/div&gt;
&lt;h3 id=&quot;5-bpf-binaries-btf-co-re-and-the-future-of-bpf-perf-tools-blog-post&quot; class=&quot;discrete&quot;&gt;5. &lt;a href=&quot;http://www.brendangregg.com/blog/2020-11-04/bpf-co-re-btf-libbpf.html&quot;&gt;&lt;em&gt;BPF binaries: BTF, CO-RE, and the future of BPF perf tools&lt;/em&gt;&lt;/a&gt; (Blog Post):&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;If you haven&amp;#8217;t heard about eBPF/BPF, it&amp;#8217;s an amazingly interesting tool that was added to the Linux kernel, and that allows tiny scripts to be run inside the kernel itself. Its origins come from networking&amp;#8201;&amp;#8212;&amp;#8201;you could use it to write very flexible + efficient firewall rules, but it&amp;#8217;s now possible to use it to instrument many many things in the kernel, enabling A LOT of new observability and debugging use cases (as well as profiling, my main interest!).&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;But thus far getting it to work is still a bit awkward: the API is still being expanded, so many features need very recent Linux kernels, and often you need to compile your eBPF application with the headers of the exact kernel it&amp;#8217;s going to run on. This blog post details the ongoing work to solve this by making eBPF applications portable.&lt;/p&gt;
&lt;/div&gt;
&lt;h3 id=&quot;6-getting-noticed-as-a-remote-engineer-and-why-it-matters-blog-post&quot; class=&quot;discrete&quot;&gt;6. &lt;a href=&quot;https://triplebyte.com/blog/getting-noticed-as-a-remote-engineer-and-why-it-matters/&quot;&gt;&lt;em&gt;Getting noticed as a remote engineer – and why it matters&lt;/em&gt;&lt;/a&gt; (Blog Post):&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;A few things that remote engineers should keep in mind when working remotely.&lt;/p&gt;
&lt;/div&gt;
&lt;h3 id=&quot;7-breakpoint-day-1-4-technology-constraints-drive-automation-talk&quot; class=&quot;discrete&quot;&gt;7. &lt;a href=&quot;https://www.youtube.com/watch?v=rnk47_h01xQ&quot;&gt;&lt;em&gt;Breakpoint Day 1.4: Technology constraints drive automation&lt;/em&gt;&lt;/a&gt; (Talk):&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Shopify&amp;#8217;s director of production engineering describes the approach taken by his team to boost their tech stack through careful selective standardization while also being open to evolution and feedback, and in cooperating with the product teams that need to deliver using the stack daily.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;A very though-provoking presentation, as this approach doesn&amp;#8217;t seem to be very common in the industry: many other companies either have a lot more freedom in the software stack, but then have a lot of integration headaches and duplicated efforts, or they have a very strict top-down mandate on their whole tech stack, but are very closed to evolution, feedback, and re-evaluating their choices.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Shopify more and more seems to be a company to be on the look out for ;)&lt;/p&gt;
&lt;/div&gt;
&lt;h3 id=&quot;8-one-size-fits-none-everything-you-learned-in-your-dbms-class-is-wrong-talk&quot; class=&quot;discrete&quot;&gt;8. &lt;a href=&quot;http://slideshot.epfl.ch/play/suri_stonebraker&quot;&gt;&lt;em&gt;One Size Fits None - (Everything You Learned in Your DBMS Class is Wrong)&lt;/em&gt;&lt;/a&gt; (Talk):&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;A critique of the database design foundations that were (and still are?) taught to students, driven by a careful analysis on how databases are used nowadays: by whom, using which data, on which hardware, and with what expectations of performance, reliability and cost.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;This talk is presented by Michael Stonebraker, which has a Turing award for his 40+ years of research and contributions on the field of databases, so he knows a thing or two about the foundations of the field.&lt;/p&gt;
&lt;/div&gt;
&lt;h3 id=&quot;9-the-tyranny-of-structurelessness-essay&quot; class=&quot;discrete&quot;&gt;9. &lt;a href=&quot;https://www.jofreeman.com/joreen/tyranny.htm&quot;&gt;&lt;em&gt;THE TYRANNY of STRUCTURELESSNESS&lt;/em&gt;&lt;/a&gt; (Essay):&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;This thoughtful analysis, written in the context of female rights movement, but completely applicable to every such group, discusses how groups and organizations that decide to be entirely without structure end up coming short, because in the absence of a formal structure, informal structures (elites) spring up, and how that ends up blocking such a group from attaining concrete goals (e.g beyond raising awareness).&lt;/p&gt;
&lt;/div&gt;
&lt;h3 id=&quot;10-the-impact-of-toxic-influencers-on-communities-blog-post&quot; class=&quot;discrete&quot;&gt;10. &lt;a href=&quot;https://intenseminimalism.com/2020/the-impact-of-toxic-influencers-on-communities/&quot;&gt;&lt;em&gt;The Impact of Toxic Influencers on Communities&lt;/em&gt;&lt;/a&gt; (Blog Post):&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Great (and depressing) analysis of the patterns exhibited by toxic influencers in the context of online communities, how they establish themselves, and the behaviors that they display.&lt;/p&gt;
&lt;/div&gt;
&lt;h3 id=&quot;11-ux-request-tell-dont-hide-blog-post&quot; class=&quot;discrete&quot;&gt;11. &lt;a href=&quot;https://jessitron.com/2020/11/30/ux-request-tell-dont-hide/&quot;&gt;&lt;em&gt;UX request: Tell, don’t hide&lt;/em&gt;&lt;/a&gt; (Blog Post):&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;How you really shouldn&amp;#8217;t hide UX elements when a given user doesn&amp;#8217;t have permissions to access them, because then the users can&amp;#8217;t tell what&amp;#8217;s going on.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;If options would show up on a given screen, disable, rather than hide them!&lt;/p&gt;
&lt;/div&gt;
&lt;h3 id=&quot;12-arm-and-lock-free-programming-blog-post&quot; class=&quot;discrete&quot;&gt;12. &lt;a href=&quot;https://randomascii.wordpress.com/2020/11/29/arm-and-lock-free-programming/&quot;&gt;&lt;em&gt;ARM and Lock-Free Programming&lt;/em&gt;&lt;/a&gt; (Blog Post):&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;With the release of Apple&amp;#8217;s M1 chips, excitement over ARM CPUs seems to be at an all-high (and the chips &lt;em&gt;do&lt;/em&gt; look amazing).&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;This blog post discusses how the ARM architecture has a weaker memory model than our usual x86 machines, and how it can break low-level concurrency code that accidentally relied on having a stricter model.&lt;/p&gt;
&lt;/div&gt;</description>
        <pubDate>Wed, 02 Dec 2020 00:00:00 +0000</pubDate>
        <link>https://ivoanjo.me/blog/2020/12/02/what-ive-been-reading-november-2020-edition/</link>
        <guid isPermaLink="true">https://ivoanjo.me/blog/2020/12/02/what-ive-been-reading-november-2020-edition/</guid>
        <category>blog</category>
      </item>
      <item>
        <title>Creating a newsletter!</title>
        <description>&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;I&amp;#8217;ve been listening to &lt;a href=&quot;https://www.penguin.co.uk/books/312/312524/company-of-one/9780241470466.html&quot;&gt;&amp;#8220;Company of One&amp;#8221;&lt;/a&gt; (which I do recommend) and that got me thinking that it may be cool to allow readers to subscribe to the blog via e-mail.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;So I&amp;#8217;ve decided to setup a newsletter! You can sign up by &lt;a href=&quot;/newsletter&quot;&gt;clicking here&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Or, if you&amp;#8217;re a RSS feeds person, you can subscribe via &lt;a href=&quot;/feed.xml&quot;&gt;&lt;a href=&quot;https://ivoanjo.me/feed.xml&quot; class=&quot;bare&quot;&gt;https://ivoanjo.me/feed.xml&lt;/a&gt;&lt;/a&gt; as well.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;That&amp;#8217;s it for today! :)&lt;/p&gt;
&lt;/div&gt;</description>
        <pubDate>Tue, 01 Dec 2020 00:00:00 +0000</pubDate>
        <link>https://ivoanjo.me/blog/2020/12/01/creating-a-newsletter/</link>
        <guid isPermaLink="true">https://ivoanjo.me/blog/2020/12/01/creating-a-newsletter/</guid>
        <category>blog</category>
      </item>
      <item>
        <title>What I've been reading: October 2020 Edition</title>
        <description>&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;A few years ago, I acquired the habit of regularly collecting and sharing with my work colleagues the highlights of what
I was reading from week to week. As I&amp;#8217;m preparing to start working at a new company soon, I&amp;#8217;ve been wondering if it
would be useful to share this with a wider audience, and how I would do it.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;I&amp;#8217;ve decided that the easiest way to start is to use this blog.
I&amp;#8217;m not sure how often I&amp;#8217;ll do these, or if I&amp;#8217;ll end up creating a separate section to avoid drowning out my more
specific posts with just &lt;em&gt;what I read on X month&lt;/em&gt; ones, but in the spirit of agile and YAGNI, here&amp;#8217;s my first stab at
sharing what I&amp;#8217;m reading.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;I don&amp;#8217;t often get feedback, but it&amp;#8217;s definitely welcome as always&amp;#8201;&amp;#8212;&amp;#8201;let me know what you&amp;#8217;ve thought of these articles
and the format in general :)&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Without further ado, here&amp;#8217;s what&amp;#8217;s been keeping me interested:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;em&gt;Why Aren’t More Users More Happy With Our VMs?&lt;/em&gt; &lt;a href=&quot;https://tratt.net/laurie/blog/entries/why_arent_more_users_more_happy_with_our_vms_part_1.html&quot;&gt;Part 1&lt;/a&gt; and &lt;a href=&quot;https://tratt.net/laurie/blog/entries/why_arent_more_users_more_happy_with_our_vms_part_2.html&quot;&gt;Part 2&lt;/a&gt; (Blog Post): A writeup and analysis on how VM benchmarking often gets done wrong, including the benchmarking done by VM implementors, and how that can lead to wrong optimizations or trade-offs being taken as a result.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://basecamp.com/books/rework&quot;&gt;&lt;em&gt;Rework&lt;/em&gt;&lt;/a&gt; (Book): Describes the approaches championed by Jason Fried, David Heinemeier Hansson on managing their company Basecamp, and what we can learn from them. Its focus on staying small and doing more with less really resonated with what I&amp;#8217;m thinking these days. (There&amp;#8217;s an audiobook version as well!)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://twitter.com/1st1/status/1318558048265404420&quot;&gt;Nice performance improvement landing in Python 3.10&lt;/a&gt; (Tweet):&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;Python 3.10 will be up to 10% faster: &lt;a href=&quot;https://t.co/7ydQ4iATsN&quot;&gt;https://t.co/7ydQ4iATsN&lt;/a&gt;. Here&amp;#39;s the email that I wrote to python-dev 4.5 years ago with some perf ideas: &lt;a href=&quot;https://t.co/tuJL7yXmjZ&quot;&gt;https://t.co/tuJL7yXmjZ&lt;/a&gt;. Thanks to &lt;a href=&quot;https://twitter.com/pyblogsal?ref_src=twsrc%5Etfw&quot;&gt;@pyblogsal&lt;/a&gt; for picking up my patch and polishing it to get it merged. 🚀&lt;/p&gt;&amp;mdash; Yury Selivanov (@1st1) &lt;a href=&quot;https://twitter.com/1st1/status/1318558048265404420?ref_src=twsrc%5Etfw&quot;&gt;October 20, 2020&lt;/a&gt;&lt;/blockquote&gt; &lt;script async src=&quot;https://platform.twitter.com/widgets.js&quot; charset=&quot;utf-8&quot;&gt;&lt;/script&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/openjdk/jdk/pull/760&quot;&gt;&lt;em&gt;OpenJDK: add diagnostic command to write Linux perf map file&lt;/em&gt;&lt;/a&gt; (Pull Request):
This pull request adds native support for the jcmd tool to generate the symbols needed when profiling OpenJDK with the
Linux perf tool, without needing to use the third-party &lt;a href=&quot;https://github.com/jvm-profiling-tools/perf-map-agent&quot;&gt;perf-map-agent&lt;/a&gt;.
Translation: One less step to worry about when profiling using perf&amp;#8201;&amp;#8212;&amp;#8201;the JVM will now do the generation itself.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://netflixtechblog.com/building-netflixs-distributed-tracing-infrastructure-bb856c319304&quot;&gt;&lt;em&gt;Building Netflix’s Distributed Tracing Infrastructure&lt;/em&gt;&lt;/a&gt; (Blog Post):
Deep dive on a distributed tracing design that allows very flexible sampling decisions (up to 100% for a specific subset
of requests, even), as well as how to handle storing data from traces using a combination of architectural improvements,
late sampling, compression and tiered storage.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://faster-cpython.readthedocs.io/&quot;&gt;&lt;em&gt;Faster CPython&lt;/em&gt;&lt;/a&gt; (Website): Collects a number of ideas,
experiments and measurements around improving the performance of the CPython interpreter.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;http://harmful.cat-v.org/software/OO_programming/_pdf/Pitfalls_of_Object_Oriented_Programming_GCAP_09.pdf&quot;&gt;&lt;em&gt;Pitfalls of Object Oriented Programming&lt;/em&gt;&lt;/a&gt; (PDF Presentation):
This presentation discusses how some common object-oriented idioms can cause bottlenecks in high-performance realtime
applications (*cof* games *cof*) and how to refactor and break apart such approaches to extract more performance.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://stackoverflow.com/questions/64392845/when-busy-spining-java-thread-is-bound-to-physical-core-can-context-switch-happ/64404504#64404504&quot;&gt;&lt;em&gt;When busy-spining Java thread is bound to physical core, can context switch happen by the reason that new branch in code is reached?&lt;/em&gt;&lt;/a&gt; (Discussion):
This Stack Overflow question triggered an amazing answer by Andrei Pangin
(the author of &lt;a href=&quot;https://github.com/jvm-profiling-tools/async-profiler&quot;&gt;async-profiler&lt;/a&gt;) discussing how and when the JVM
interrupts user code to perform optimizations and measurements.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://tratt.net/laurie/research/pubs/papers/tratt__dynamically_typed_languages.pdf&quot;&gt;&lt;em&gt;Dynamically Typed Languages&lt;/em&gt;&lt;/a&gt; (PDF Article): Interesting discussion on how dynamic languages differ from static languages, and what they have to offer.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://magic-wormhole.readthedocs.io/en/latest/&quot;&gt;&lt;em&gt;Magic-Wormhole: Get Things From One Computer To Another, Safely&lt;/em&gt;&lt;/a&gt; (Tool): Small tool to securely transfer data between two computers, even behind firewalls and whatnot.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://googleprojectzero.blogspot.com/2020/10/enter-the-vault-auth-issues-hashicorp-vault.html&quot;&gt;&lt;em&gt;Enter the Vault: Authentication Issues in HashiCorp Vault&lt;/em&gt;&lt;/a&gt; (Blog post):
Deep dive discussion into two recent issues with the Vault system for securing access to credentials. It highlights
how even an apparently solid design can be breached by exploiting wrong assumptions and incomplete implementations
when such system is integrated with third-party APIs.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://svpg.com/inspired-how-to-create-products-customers-love/&quot;&gt;&lt;em&gt;INSPIRED: How to Create Tech Products Customers Love&lt;/em&gt;&lt;/a&gt; (Book):
Describes what and how a product managers can work together with engineering teams and other company
stakeholders to discover and deliver really good solutions to customer&amp;#8217;s issues.&lt;/p&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;It took me a few months to go through the entire book, but I cannot recommend it enough&amp;#8201;&amp;#8212;&amp;#8201;even for, and especially for
  engineers that regularly work with product managers.
  I especially liked the &quot;missionaries vs mercenaries&quot; categorization of product teams, as it really aligns with my own
  experience in the field.
  (There&amp;#8217;s an audiobook version as well!)&lt;/p&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://nebula-plugins.github.io/&quot;&gt;&lt;em&gt;Nebula: A collection of Gradle plugins, built by Netflix&lt;/em&gt;&lt;/a&gt; (Tool):
The Netflix nebula set of plugins extends the Gradle built tool with a number of nice features&amp;#8201;&amp;#8212;&amp;#8201;better metadata,
a &lt;code&gt;dependency.lock&lt;/code&gt; file that works like Ruby&amp;#8217;s &lt;code&gt;Gemfile.lock&lt;/code&gt;/&lt;code&gt;gems.locked&lt;/code&gt; and enables reproduceable builds via
locking of dependency versions, ways to manage versioning and deployment, etc.&lt;/p&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;This set of plugins is really interesting, and especially the &lt;a href=&quot;https://github.com/nebula-plugins/gradle-dependency-lock-plugin&quot;&gt;version locking features&lt;/a&gt; are something that I never
  quite understood why/how people were getting by without them in the JVM ecosystem. Glad to see that Netflix&amp;#8217;s
  engineering agrees with me ;)&lt;/p&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://performancesummitiv.splashthat.com/&quot;&gt;&lt;em&gt;Performance Summit IV&lt;/em&gt;&lt;/a&gt; (Conference): Upcoming free online conference
with talks from engineers working in the performance profiling space.&lt;/p&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;I&amp;#8217;m particularly interested in seeing the &quot;BPerf: Porting production profiling from Windows to Linux&quot; talk describing
the ongoing work to bring Windows&apos; ETW tooling to Linux, as I&amp;#8217;ve been fascinated in the past months by that toolkit,
that I can describe as similar to Java&amp;#8217;s Flight Recorder tooling, but at the OS level; as well as
&quot;Perflections: Tracking the perf of perf programs&quot; as I&amp;#8217;m also quite curious on how to safely use and deploy perf-based
solutions directly to customers (e.g. when you&amp;#8217;re no longer using it on your local infrastructure).&lt;/p&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://raygun.com/ruby-performance-monitoring&quot;&gt;&lt;em&gt;Raygun&lt;/em&gt;&lt;/a&gt; (Tool): Another hosted Ruby APM; uses flame charts for
visualizing traces.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://www.thoughtworks.com/radar&quot;&gt;&lt;em&gt;Technology Radar, volume 23&lt;/em&gt;&lt;/a&gt; (Magazine): The latest version of Thoughtwork&amp;#8217;s
influential periodic review of techniques, tools, platforms and languages &amp;amp; frameworks in the industry. As always,
a recommended read.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=4SiWL5tULnQ&quot;&gt;&lt;em&gt;eBPF superpowers&lt;/em&gt;&lt;/a&gt; (Talk): Great &quot;hello world&quot; introduction to Linux&amp;#8217;s
eBPF tooling:&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;iframe width=&quot;80%&quot; height=&quot;315&quot; src=&quot;https://www.youtube.com/embed/4SiWL5tULnQ?si=RfOPC9hC3M0YWIvO&quot; title=&quot;YouTube video player&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; referrerpolicy=&quot;strict-origin-when-cross-origin&quot; allowfullscreen&gt;&lt;/iframe&gt;
&lt;/p&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;That&amp;#8217;s it for this round!&lt;/p&gt;
&lt;/div&gt;</description>
        <pubDate>Tue, 03 Nov 2020 00:00:00 +0000</pubDate>
        <link>https://ivoanjo.me/blog/2020/11/03/what-ive-been-reading-october-2020-edition/</link>
        <guid isPermaLink="true">https://ivoanjo.me/blog/2020/11/03/what-ive-been-reading-october-2020-edition/</guid>
        <category>blog</category>
      </item>
      <item>
        <title>Better backtraces in Ruby using TracePoint</title>
        <description>&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;In a previous blog post&amp;#8201;&amp;#8212;&amp;#8201;&lt;a href=&quot;/blog/2020/07/05/ruby-experiment-include-class-names-in-backtraces/&quot;&gt;Ruby Experiment: Include class names in backtraces&lt;/a&gt;&amp;#8201;&amp;#8212;&amp;#8201;I shared the beginning of my experiments into improving Ruby backtraces.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;That got me thinking of a few things:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;What information would I want to show in backtraces?&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;What format would I display that information in?&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Is it possible (and reasonable?) to extract the needed information during backtrace collection?&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;To allow me to iterate faster, I&amp;#8217;ve implemented my next prototype for better backtraces using Ruby&amp;#8217;s &lt;a href=&quot;https://ruby-doc.org/core-2.7.0/TracePoint.html&quot;&gt;&lt;code&gt;TracePoint&lt;/code&gt;&lt;/a&gt; API.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;This means that the current prototype can be run on regular unmodified Ruby, although having it loaded will have a performance impact (so I definitely don&amp;#8217;t recommend it).&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;The result of my experiments is the following:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;CodeRay highlight&quot;&gt;&lt;code&gt;tracepoint-better-backtrace.rb:159:in BetterBacktrace.better_backtrace_locations(thread)
tracepoint-better-backtrace.rb:2:in ClassA#hello()
tracepoint-better-backtrace.rb:11:in ModuleB::ClassB#hello()
tracepoint-better-backtrace.rb:18:in ModuleC.hello()
tracepoint-better-backtrace.rb:24:in ClassWithStaticMethod.hello()
tracepoint-better-backtrace.rb:30:in ModuleD#hello()
tracepoint-better-backtrace.rb:39:in Object$singleton#&amp;lt;main&amp;gt;{block}()
tracepoint-better-backtrace.rb:41:in Object$singleton#&amp;lt;main&amp;gt;{block}()
tracepoint-better-backtrace.rb:47:in ClassD$singleton#hello()
tracepoint-better-backtrace.rb:52:in ClassE#hello()
tracepoint-better-backtrace.rb:73:in Method#call(*)
tracepoint-better-backtrace.rb:72:in ClassG$refinement@ContainsRefinement::RefinesClassG#hello()
tracepoint-better-backtrace.rb:82:in ModuleE.hello()
tracepoint-better-backtrace.rb:88:in ClassH#method_missing(name, *_)
tracepoint-better-backtrace.rb:97:in ClassF#hello{block}()
tracepoint-better-backtrace.rb:97:in Integer#times()
tracepoint-better-backtrace.rb:96:in ClassF#hello(arg1, arg2, test1, test2)
tracepoint-better-backtrace.rb:105:in #&amp;lt;Class:#&amp;lt;Object:0x00005636e9ea3898&amp;gt;&amp;gt;.hello()
tracepoint-better-backtrace.rb:110:in #&amp;lt;Class:0x00005636e9ea35c8&amp;gt;#hello()
tracepoint-better-backtrace.rb:116:in #&amp;lt;Module:0x00005636e9ea32d0&amp;gt;.hello()
tracepoint-better-backtrace.rb:121:in Object#method_with_complex_parameters(a, b, *c, (), f:, g:, **h, &amp;amp;i)
tracepoint-better-backtrace.rb:125:in Object#top_level_hello()
tracepoint-better-backtrace.rb:229:in Kernel#eval(*)
tracepoint-better-backtrace.rb:228:in Object$singleton#&amp;lt;main&amp;gt;{block}()
tracepoint-better-backtrace.rb:228:in Integer#times()
tracepoint-better-backtrace.rb:227:in Object$singleton#&amp;lt;main&amp;gt;{block}()
tracepoint-better-backtrace.rb:227:in Integer#times()&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;The changes are:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;olist arabic&quot;&gt;
&lt;ol class=&quot;arabic&quot;&gt;
&lt;li&gt;
&lt;p&gt;Show class/module names&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Show number and names of arguments next to method names&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Distinguish between instance methods (&lt;code&gt;Foo#bar&lt;/code&gt;) and methods defined on class/method objects (&lt;code&gt;Foo.bar&lt;/code&gt;). The &lt;code&gt;#&lt;/code&gt; vs &lt;code&gt;.&lt;/code&gt; syntax follows from the usual conventions in Ruby documentation.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Display methods defined on specific objects with the &lt;code&gt;$singleton&lt;/code&gt; suffix&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Display refinements as the &lt;code&gt;$refinement&lt;/code&gt; suffix, followed by the name of the module that defined the refinement&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Show blocks as &lt;code&gt;{block}&lt;/code&gt; (instead of &lt;code&gt;block in &amp;#8230;&amp;#8203;&lt;/code&gt;)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The &lt;code&gt;eval&lt;/code&gt; frame (shown below as &lt;code&gt; (eval):1:in `block (2 levels) in &amp;lt;main&amp;gt;&apos;&lt;/code&gt;) was omitted&amp;#8201;&amp;#8212;&amp;#8201;this seems to be a gap in the &lt;code&gt;TracePoint&lt;/code&gt; API&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;It took me quite a while (and a few discussions with friends and colleagues&amp;#8201;&amp;#8212;&amp;#8201;thanks João and Marek for nice points) but I&amp;#8217;m reasonably happy with the current way of encoding all this information in a backtrace.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;All of these data points are stored separately in the &quot;backtrace information&quot; so alternative representations (or just not showing this much information) is doable by just changing the printing bits.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;My test file is a quite artificial example: the usual Ruby conventions would be to have classes defined in a separate file. But, for reference, here&amp;#8217;s how a regular Ruby backtrace looks for the same file:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;CodeRay highlight&quot;&gt;&lt;code&gt;tracepoint-better-backtrace.rb:5:in `backtrace_locations&apos;
tracepoint-better-backtrace.rb:5:in `hello&apos;
tracepoint-better-backtrace.rb:12:in `hello&apos;
tracepoint-better-backtrace.rb:19:in `hello&apos;
tracepoint-better-backtrace.rb:25:in `hello&apos;
tracepoint-better-backtrace.rb:31:in `hello&apos;
tracepoint-better-backtrace.rb:39:in `block in &amp;lt;main&amp;gt;&apos;
tracepoint-better-backtrace.rb:41:in `block in &amp;lt;main&amp;gt;&apos;
tracepoint-better-backtrace.rb:48:in `hello&apos;
tracepoint-better-backtrace.rb:53:in `hello&apos;
tracepoint-better-backtrace.rb:73:in `call&apos;
tracepoint-better-backtrace.rb:73:in `hello&apos;
tracepoint-better-backtrace.rb:83:in `hello&apos;
tracepoint-better-backtrace.rb:91:in `method_missing&apos;
tracepoint-better-backtrace.rb:98:in `block in hello&apos;
tracepoint-better-backtrace.rb:97:in `times&apos;
tracepoint-better-backtrace.rb:97:in `hello&apos;
tracepoint-better-backtrace.rb:106:in `hello&apos;
tracepoint-better-backtrace.rb:111:in `hello&apos;
tracepoint-better-backtrace.rb:117:in `hello&apos;
tracepoint-better-backtrace.rb:122:in `method_with_complex_parameters&apos;
tracepoint-better-backtrace.rb:126:in `top_level_hello&apos;
(eval):1:in `block (2 levels) in &amp;lt;main&amp;gt;&apos;
tracepoint-better-backtrace.rb:229:in `eval&apos;
tracepoint-better-backtrace.rb:229:in `block (2 levels) in &amp;lt;main&amp;gt;&apos;
tracepoint-better-backtrace.rb:228:in `times&apos;
tracepoint-better-backtrace.rb:228:in `block in &amp;lt;main&amp;gt;&apos;
tracepoint-better-backtrace.rb:227:in `times&apos;
tracepoint-better-backtrace.rb:227:in `&amp;lt;main&amp;gt;&apos;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Below, you&amp;#8217;ll find &lt;a href=&quot;https://gitlab.com/snippets/1997038&quot;&gt;&lt;code&gt;tracepoint-better-backtrace.rb&lt;/code&gt;&lt;/a&gt; file, which includes the implementation, as well as the most extensive example for defining classes and methods in different ways in Ruby that I could think of :)&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;The implementation uses a &quot;shadow stack&quot;: it keeps a separate stack as a thread-local variable that simulates the real Ruby stack by pushing and popping information on the current active methods as they are entered and they finish. To generate the backtrace, we just need to access the current state of that variable.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;The key parts of the implementation are which information is gathered on method entry (inside the &lt;code&gt;TracePoint&lt;/code&gt; definition block), as well as how those data points are interpreted to generate the pretty stack (inside &lt;code&gt;to_s&lt;/code&gt; for the &lt;code&gt;Locations&lt;/code&gt; struct).&lt;/p&gt;
&lt;/div&gt;
&lt;script src=&apos;https://gitlab.com/snippets/1997038.js&apos;&gt;&lt;/script&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;What&amp;#8217;s next? I&amp;#8217;ve been experimenting with implementing these improved backtraces in the &lt;a href=&quot;https://github.com/rbspy/rbspy&quot;&gt;rbspy&lt;/a&gt; Ruby profiler.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Because the rbspy profiler works outside of the Ruby VM, it can gather the extra needed information without impacting the performance of the Ruby VM, so it seems like a great place to start with a real-world implementation of these better backtraces.&lt;/p&gt;
&lt;/div&gt;</description>
        <pubDate>Sun, 19 Jul 2020 00:00:00 +0100</pubDate>
        <link>https://ivoanjo.me/blog/2020/07/19/better-backtraces-in-ruby-using-tracepoint/</link>
        <guid isPermaLink="true">https://ivoanjo.me/blog/2020/07/19/better-backtraces-in-ruby-using-tracepoint/</guid>
        <category>blog</category>
      </item>
      <item>
        <title>Snippet: Getting a dynamically-generated method name on the Java stack using Javassist</title>
        <description>&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Have you ever found yourself in need to include a certain string or method name on your stack traces, for debugging or metrics?&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;The following snippet shows how easy that can be done with the &lt;a href=&quot;https://www.javassist.org/&quot;&gt;javassist&lt;/a&gt; library. The snippet is written in Kotlin, but can be easily converted into Java or any other JVM language.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;For the example, we want to see &quot;iLikePie&quot; as one of our method names. Here&amp;#8217;s how it looks:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;pygments highlight&quot; style=&quot;background: #f8f8f8;&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;&lt;span&gt;&lt;/span&gt;Your stack is&lt;span style=&quot;color: #666666&quot;&gt;:&lt;/span&gt;
java&lt;span style=&quot;color: #666666&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #7D9029&quot;&gt;lang&lt;/span&gt;&lt;span style=&quot;color: #666666&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #7D9029&quot;&gt;Exception&lt;/span&gt;&lt;span style=&quot;color: #666666&quot;&gt;:&lt;/span&gt; Stack trace
        at java&lt;span style=&quot;color: #666666&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #7D9029&quot;&gt;lang&lt;/span&gt;&lt;span style=&quot;color: #666666&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #7D9029&quot;&gt;Thread&lt;/span&gt;&lt;span style=&quot;color: #666666&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #7D9029&quot;&gt;dumpStack&lt;/span&gt;&lt;span style=&quot;color: #666666&quot;&gt;(&lt;/span&gt;Thread&lt;span style=&quot;color: #666666&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #7D9029&quot;&gt;java&lt;/span&gt;&lt;span style=&quot;color: #666666&quot;&gt;:1336)&lt;/span&gt;
        at Dynamic_framesKt$main$$inlined$withFrameNamed$1&lt;span style=&quot;color: #666666&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #7D9029&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;color: #666666&quot;&gt;(&lt;/span&gt;dynamic&lt;span style=&quot;color: #666666&quot;&gt;-&lt;/span&gt;frames&lt;span style=&quot;color: #666666&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #7D9029&quot;&gt;kt&lt;/span&gt;&lt;span style=&quot;color: #666666&quot;&gt;:51)&lt;/span&gt;
        at dynamic&lt;span style=&quot;color: #666666&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #7D9029&quot;&gt;iLikePie&lt;/span&gt;&lt;span style=&quot;color: #666666&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #7D9029&quot;&gt;iLikePie&lt;/span&gt;&lt;span style=&quot;color: #666666&quot;&gt;(&lt;/span&gt;iLikePie&lt;span style=&quot;color: #666666&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #7D9029&quot;&gt;java&lt;/span&gt;&lt;span style=&quot;color: #666666&quot;&gt;)&lt;/span&gt;
        at dynamic&lt;span style=&quot;color: #666666&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #7D9029&quot;&gt;iLikePie&lt;/span&gt;&lt;span style=&quot;color: #666666&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #7D9029&quot;&gt;apply&lt;/span&gt;&lt;span style=&quot;color: #666666&quot;&gt;(&lt;/span&gt;iLikePie&lt;span style=&quot;color: #666666&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #7D9029&quot;&gt;java&lt;/span&gt;&lt;span style=&quot;color: #666666&quot;&gt;)&lt;/span&gt;
        at Dynamic_framesKt&lt;span style=&quot;color: #666666&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #7D9029&quot;&gt;main&lt;/span&gt;&lt;span style=&quot;color: #666666&quot;&gt;(&lt;/span&gt;dynamic&lt;span style=&quot;color: #666666&quot;&gt;-&lt;/span&gt;frames&lt;span style=&quot;color: #666666&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #7D9029&quot;&gt;kt&lt;/span&gt;&lt;span style=&quot;color: #666666&quot;&gt;:57)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&amp;#8230;&amp;#8203;and here&amp;#8217;s the code to implement it.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;pygments highlight&quot; style=&quot;background: #f8f8f8;&quot;&gt;&lt;code data-lang=&quot;kotlin&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span style=&quot;border: 1px solid #FF0000&quot;&gt;#&lt;/span&gt;!/usr/bin/env kscript
&lt;span style=&quot;color: #408080; font-style: italic&quot;&gt;//DEPS org.javassist:javassist:3.24.1-GA&lt;/span&gt;

&lt;span style=&quot;color: #008000; font-weight: bold&quot;&gt;import&lt;/span&gt; &lt;span style=&quot;color: #0000FF; font-weight: bold&quot;&gt;javassist.ClassPool&lt;/span&gt;
&lt;span style=&quot;color: #008000; font-weight: bold&quot;&gt;import&lt;/span&gt; &lt;span style=&quot;color: #0000FF; font-weight: bold&quot;&gt;javassist.CtMethod&lt;/span&gt;
&lt;span style=&quot;color: #008000; font-weight: bold&quot;&gt;import&lt;/span&gt; &lt;span style=&quot;color: #0000FF; font-weight: bold&quot;&gt;java.util.function.Function&lt;/span&gt;
&lt;span style=&quot;color: #008000; font-weight: bold&quot;&gt;import&lt;/span&gt; &lt;span style=&quot;color: #0000FF; font-weight: bold&quot;&gt;java.util.function.Supplier&lt;/span&gt;

&lt;span style=&quot;color: #008000; font-weight: bold&quot;&gt;val&lt;/span&gt; classPool = ClassPool.getDefault()
&lt;span style=&quot;color: #008000; font-weight: bold&quot;&gt;val&lt;/span&gt; generatedClasses: MutableMap&amp;lt;String, Function&amp;lt;Supplier&amp;lt;Any&amp;gt;, Any&amp;gt;&amp;gt; = mutableMapOf()

&lt;span style=&quot;color: #008000; font-weight: bold&quot;&gt;fun&lt;/span&gt; &lt;span style=&quot;color: #0000FF&quot;&gt;dynamicFrameNamed&lt;/span&gt;(name: String): Function&amp;lt;Supplier&amp;lt;Any&amp;gt;, Any&amp;gt; {
    &lt;span style=&quot;color: #008000; font-weight: bold&quot;&gt;val&lt;/span&gt; dynamicClass = classPool.makeClass(&lt;span style=&quot;color: #BA2121&quot;&gt;&amp;quot;dynamic.$name&amp;quot;&lt;/span&gt;).apply {
        addInterface(classPool.&lt;span style=&quot;color: #008000; font-weight: bold&quot;&gt;get&lt;/span&gt;(&lt;span style=&quot;color: #BA2121&quot;&gt;&amp;quot;java.util.function.Function&amp;quot;&lt;/span&gt;))

        addMethod(CtMethod.make(&lt;span style=&quot;color: #BA2121&quot;&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span style=&quot;color: #BA2121&quot;&gt;            private Object $name(java.util.function.Supplier block) {&lt;/span&gt;
&lt;span style=&quot;color: #BA2121&quot;&gt;                return block.get();&lt;/span&gt;
&lt;span style=&quot;color: #BA2121&quot;&gt;            }&lt;/span&gt;
&lt;span style=&quot;color: #BA2121&quot;&gt;        &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;, &lt;span style=&quot;color: #008000; font-weight: bold&quot;&gt;this&lt;/span&gt;))

        addMethod(CtMethod.make(&lt;span style=&quot;color: #BA2121&quot;&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span style=&quot;color: #BA2121&quot;&gt;            public Object apply(Object o) {&lt;/span&gt;
&lt;span style=&quot;color: #BA2121&quot;&gt;                java.util.function.Supplier block = (java.util.function.Supplier) o;&lt;/span&gt;
&lt;span style=&quot;color: #BA2121&quot;&gt;                return $name(block);&lt;/span&gt;
&lt;span style=&quot;color: #BA2121&quot;&gt;            }&lt;/span&gt;
&lt;span style=&quot;color: #BA2121&quot;&gt;        &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;, &lt;span style=&quot;color: #008000; font-weight: bold&quot;&gt;this&lt;/span&gt;))

    }

    &lt;span style=&quot;color: #008000; font-weight: bold&quot;&gt;return&lt;/span&gt; dynamicClass.toClass().newInstance() &lt;span style=&quot;color: #008000; font-weight: bold&quot;&gt;as&lt;/span&gt; Function&amp;lt;Supplier&amp;lt;Any&amp;gt;, Any&amp;gt;
}

&lt;span style=&quot;color: #008000; font-weight: bold&quot;&gt;inline fun&lt;/span&gt; &lt;span style=&quot;color: #0000FF&quot;&gt;withFrameNamed&lt;/span&gt;(name: String, &lt;span style=&quot;color: #008000; font-weight: bold&quot;&gt;crossinline&lt;/span&gt; block: () -&amp;gt; Unit) {
    generatedClasses
        .getOrPut(name) { dynamicFrameNamed(name) }
        .apply(&lt;span style=&quot;color: #008000; font-weight: bold&quot;&gt;object&lt;/span&gt; : &lt;span style=&quot;color: #0000FF; font-weight: bold&quot;&gt;java&lt;/span&gt;.util.function.Supplier&amp;lt;Any&amp;gt; {
            &lt;span style=&quot;color: #008000; font-weight: bold&quot;&gt;override&lt;/span&gt; &lt;span style=&quot;color: #008000; font-weight: bold&quot;&gt;fun&lt;/span&gt; &lt;span style=&quot;color: #0000FF&quot;&gt;get&lt;/span&gt;(): Any {
                block()
                &lt;span style=&quot;color: #008000; font-weight: bold&quot;&gt;return&lt;/span&gt; &lt;span style=&quot;color: #BA2121&quot;&gt;&amp;quot;&amp;quot;&lt;/span&gt;
            }
        })
}

&lt;span style=&quot;color: #008000; font-weight: bold&quot;&gt;fun&lt;/span&gt; &lt;span style=&quot;color: #0000FF&quot;&gt;main&lt;/span&gt;(args: Array&amp;lt;String&amp;gt;) {
    withFrameNamed(&lt;span style=&quot;color: #BA2121&quot;&gt;&amp;quot;iLikePie&amp;quot;&lt;/span&gt;) {
        println(&lt;span style=&quot;color: #BA2121&quot;&gt;&amp;quot;Your stack is:&amp;quot;&lt;/span&gt;)
        Thread.dumpStack()
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;</description>
        <pubDate>Sun, 12 Jul 2020 00:00:00 +0100</pubDate>
        <link>https://ivoanjo.me/blog/2020/07/12/snippet-getting-a-dynamically-generated-method-name-on-the-java-stack-using-javassist/</link>
        <guid isPermaLink="true">https://ivoanjo.me/blog/2020/07/12/snippet-getting-a-dynamically-generated-method-name-on-the-java-stack-using-javassist/</guid>
        <category>blog</category>
      </item>
      <item>
        <title>Ruby Experiment: Include class names in backtraces</title>
        <description>&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;As a weekend experiment, I decided to write a few prototypes to answer the following question: Is it possible to improve Ruby backtraces by including the class where a given method was defined, similar to how Java and other languages do it?&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Turns out that it can be done with a handful of changes in the implementation of backtraces: &lt;a href=&quot;https://github.com/ivoanjo/ruby/commit/cfa29197cb9f98866ef9c77662f49ba9fdf351a3&quot; class=&quot;bare&quot;&gt;https://github.com/ivoanjo/ruby/commit/cfa29197cb9f98866ef9c77662f49ba9fdf351a3&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;This allows the following example:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;CodeRay highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;module&lt;/span&gt; &lt;span style=&quot;color:#B06;font-weight:bold&quot;&gt;A&lt;/span&gt;
  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;class&lt;/span&gt; &lt;span style=&quot;color:#B06;font-weight:bold&quot;&gt;Super1&lt;/span&gt;
    &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color:#06B;font-weight:bold&quot;&gt;classes_example&lt;/span&gt;
      print_stack_trace(&lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;Thread&lt;/span&gt;.current.backtrace_locations)
    &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;end&lt;/span&gt;
  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;end&lt;/span&gt;
&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;end&lt;/span&gt;

&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;module&lt;/span&gt; &lt;span style=&quot;color:#B06;font-weight:bold&quot;&gt;B&lt;/span&gt;
  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;class&lt;/span&gt; &lt;span style=&quot;color:#B06;font-weight:bold&quot;&gt;Super2&lt;/span&gt; &amp;lt; &lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;A&lt;/span&gt;::&lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;Super1&lt;/span&gt;
    &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color:#06B;font-weight:bold&quot;&gt;classes_example&lt;/span&gt;
      &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;super&lt;/span&gt;
    &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;end&lt;/span&gt;
  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;end&lt;/span&gt;
&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;end&lt;/span&gt;

&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;module&lt;/span&gt; &lt;span style=&quot;color:#B06;font-weight:bold&quot;&gt;C&lt;/span&gt;
  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;class&lt;/span&gt; &lt;span style=&quot;color:#B06;font-weight:bold&quot;&gt;Super3&lt;/span&gt; &amp;lt; &lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;B&lt;/span&gt;::&lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;Super2&lt;/span&gt;
    &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color:#06B;font-weight:bold&quot;&gt;classes_example&lt;/span&gt;
      &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;super&lt;/span&gt;
    &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;end&lt;/span&gt;
  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;end&lt;/span&gt;
&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;end&lt;/span&gt;

&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;module&lt;/span&gt; &lt;span style=&quot;color:#B06;font-weight:bold&quot;&gt;D&lt;/span&gt;
  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;class&lt;/span&gt; &lt;span style=&quot;color:#B06;font-weight:bold&quot;&gt;Super4&lt;/span&gt; &amp;lt; &lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;C&lt;/span&gt;::&lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;Super3&lt;/span&gt;
    &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color:#06B;font-weight:bold&quot;&gt;classes_example&lt;/span&gt;
      &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;super&lt;/span&gt;
    &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;end&lt;/span&gt;
  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;end&lt;/span&gt;
&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;end&lt;/span&gt;


puts &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;Stack for classes_example:&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;D&lt;/span&gt;::&lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;Super4&lt;/span&gt;.new.classes_example&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&amp;#8230;&amp;#8203;to be printed as:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;CodeRay highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;Thread&lt;/span&gt;.backtrace_locations(rich_stack_trace_example.rb:&lt;span style=&quot;color:#00D&quot;&gt;42&lt;/span&gt;)
&lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;A&lt;/span&gt;::&lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;Super1&lt;/span&gt;.classes_example(rich_stack_trace_example.rb:&lt;span style=&quot;color:#00D&quot;&gt;42&lt;/span&gt;)
&lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;B&lt;/span&gt;::&lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;Super2&lt;/span&gt;.classes_example(rich_stack_trace_example.rb:&lt;span style=&quot;color:#00D&quot;&gt;50&lt;/span&gt;)
&lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;C&lt;/span&gt;::&lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;Super3&lt;/span&gt;.classes_example(rich_stack_trace_example.rb:&lt;span style=&quot;color:#00D&quot;&gt;58&lt;/span&gt;)
&lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;D&lt;/span&gt;::&lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;Super4&lt;/span&gt;.classes_example(rich_stack_trace_example.rb:&lt;span style=&quot;color:#00D&quot;&gt;66&lt;/span&gt;)
&lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;Object&lt;/span&gt;.&amp;lt;main&amp;gt;(rich_stack_trace_example.rb:&lt;span style=&quot;color:#00D&quot;&gt;73&lt;/span&gt;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&amp;#8230;&amp;#8203;instead of the more usual:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;CodeRay highlight&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;rich_stack_trace_example.rb:&lt;span style=&quot;color:#00D&quot;&gt;42&lt;/span&gt;:&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;in&lt;/span&gt; `backtrace_locations&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;
rich_stack_trace_example.rb:&lt;span style=&quot;color:#00D&quot;&gt;42&lt;/span&gt;:&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;in&lt;/span&gt; `classes_example&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;
rich_stack_trace_example.rb:&lt;span style=&quot;color:#00D&quot;&gt;50&lt;/span&gt;:&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;in&lt;/span&gt; `classes_example&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;
rich_stack_trace_example.rb:&lt;span style=&quot;color:#00D&quot;&gt;58&lt;/span&gt;:&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;in&lt;/span&gt; `classes_example&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;
rich_stack_trace_example.rb:&lt;span style=&quot;color:#00D&quot;&gt;66&lt;/span&gt;:&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;in&lt;/span&gt; `classes_example&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;
rich_stack_trace_example.rb:&lt;span style=&quot;color:#00D&quot;&gt;73&lt;/span&gt;:&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;in&lt;/span&gt; `&amp;lt;main&amp;gt;&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;It&amp;#8217;s not completely perfect for other cases (modules, singleton definitions, etc)&amp;#8201;&amp;#8212;&amp;#8201;I hope to look into that in the future.&lt;/p&gt;
&lt;/div&gt;</description>
        <pubDate>Sun, 05 Jul 2020 00:00:00 +0100</pubDate>
        <link>https://ivoanjo.me/blog/2020/07/05/ruby-experiment-include-class-names-in-backtraces/</link>
        <guid isPermaLink="true">https://ivoanjo.me/blog/2020/07/05/ruby-experiment-include-class-names-in-backtraces/</guid>
        <category>blog</category>
      </item>
      <item>
        <title>Quick tip: Unsafe concurrent Ruby hash access</title>
        <description>&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;On my talk on &lt;a href=&quot;/blog/2018/10/13/spotting-unsafe-ruby-patterns/&quot;&gt;spotting unsafe concurrent ruby patterns&lt;/a&gt; I documented a few common Ruby code patterns that may trigger issues when executed concurrently across multiple threads.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;I just bumped into another such example! This specific one seems not to affect MRI Ruby (aka the default Ruby implementation), but I was able to clearly trigger it on both JRuby and TruffleRuby using&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;CodeRay highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;some_hash[key] = value&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;The trigger above is very simple&amp;#8201;&amp;#8212;&amp;#8201;having different threads &lt;strong&gt;writing&lt;/strong&gt; to the same Hash concurrently. Just writing, they don&amp;#8217;t even need to be reading.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Here&amp;#8217;s the full example:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;CodeRay highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;puts &lt;span style=&quot;color:#069&quot;&gt;RUBY_DESCRIPTION&lt;/span&gt;

&lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;PER_THREAD_LIMIT&lt;/span&gt; = &lt;span style=&quot;color:#00D&quot;&gt;1000000&lt;/span&gt;
&lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;THREADS&lt;/span&gt; = &lt;span style=&quot;color:#00D&quot;&gt;8&lt;/span&gt;

&lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;THE_HASH&lt;/span&gt; = {}

(&lt;span style=&quot;color:#00D&quot;&gt;1&lt;/span&gt;..&lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;THREADS&lt;/span&gt;).to_a.map &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;do&lt;/span&gt; |thread_id|
  &lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;Thread&lt;/span&gt;.new &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;do&lt;/span&gt;
    &lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;PER_THREAD_LIMIT&lt;/span&gt;.times &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;do&lt;/span&gt;
      &lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;THE_HASH&lt;/span&gt;[rand(&lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;PER_THREAD_LIMIT&lt;/span&gt;)] = thread_id
    &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;end&lt;/span&gt;
    puts &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;Thread &lt;/span&gt;&lt;span style=&quot;background-color:hsla(0,0%,0%,0.07);color:black&quot;&gt;&lt;span style=&quot;font-weight:bold;color:#666&quot;&gt;#{&lt;/span&gt;thread_id&lt;span style=&quot;font-weight:bold;color:#666&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt; done!&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;end&lt;/span&gt;
&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;end&lt;/span&gt;.map(&amp;amp;&lt;span style=&quot;color:#A60&quot;&gt;:join&lt;/span&gt;)

puts &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;All done!&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;and here&amp;#8217;s the result of running it on JRuby:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;CodeRay highlight&quot;&gt;&lt;code&gt;jruby 9.2.8.0 (2.5.3) 2019-08-12 a1ac7ff OpenJDK 64-Bit Server VM 11.0.3+7-LTS on 11.0.3+7-LTS +jit [linux-x86_64]
warning: thread &amp;quot;Ruby-0-Thread-3: threads.rb:1&amp;quot; terminated with exception (report_on_exception is true):
java.lang.ArrayIndexOutOfBoundsException: Index 18581 out of bounds for length 16427
        at org.jruby.dist/org.jruby.RubyHash.internalPutNoResize(RubyHash.java:561)
        at org.jruby.dist/org.jruby.RubyHash.internalPut(RubyHash.java:535)
        at org.jruby.dist/org.jruby.RubyHash.internalPut(RubyHash.java:525)
        at org.jruby.dist/org.jruby.RubyHash.fastASetCheckString(RubyHash.java:1020)
        at org.jruby.dist/org.jruby.RubyHash.op_aset(RubyHash.java:1055)
        at org.jruby.dist/org.jruby.RubyHash$INVOKER$i$2$0$op_aset.call(RubyHash$INVOKER$i$2$0$op_aset.gen)
        at org.jruby.dist/org.jruby.runtime.callsite.CachingCallSite.call(CachingCallSite.java:203)
        at threads.invokeOther1:\=\{\}=(threads.rb:11)
        at threads.RUBY$block$\=threads\,rb$2(threads.rb:11)
        at org.jruby.dist/org.jruby.runtime.CompiledIRBlockBody.yieldDirect(CompiledIRBlockBody.java:146)
        at org.jruby.dist/org.jruby.runtime.IRBlockBody.yieldSpecific(IRBlockBody.java:85)
        at org.jruby.dist/org.jruby.runtime.Block.yieldSpecific(Block.java:139)
        at org.jruby.dist/org.jruby.RubyFixnum.times(RubyFixnum.java:279)
        at org.jruby.dist/org.jruby.RubyInteger$INVOKER$i$0$0$times.call(RubyInteger$INVOKER$i$0$0$times.gen)
        at org.jruby.dist/org.jruby.runtime.callsite.CachingCallSite.call(CachingCallSite.java:151)
        at org.jruby.dist/org.jruby.runtime.callsite.CachingCallSite.callIter(CachingCallSite.java:160)
        at threads.invokeOther3:times(threads.rb:10)
        at threads.RUBY$block$\=threads\,rb$1(threads.rb:10)
        at org.jruby.dist/org.jruby.runtime.CompiledIRBlockBody.callDirect(CompiledIRBlockBody.java:136)
        at org.jruby.dist/org.jruby.runtime.IRBlockBody.call(IRBlockBody.java:77)
        at org.jruby.dist/org.jruby.runtime.Block.call(Block.java:129)
        at org.jruby.dist/org.jruby.RubyProc.call(RubyProc.java:295)
        at org.jruby.dist/org.jruby.RubyProc.call(RubyProc.java:274)
        at org.jruby.dist/org.jruby.RubyProc.call(RubyProc.java:270)
        at org.jruby.dist/org.jruby.internal.runtime.RubyRunnable.run(RubyRunnable.java:105)
        at java.base/java.lang.Thread.run(Thread.java:834)

Thread 5 done!
Thread 8 done!
Thread 4 done!
Thread 6 done!
Thread 2 done!
Thread 1 done!
Unhandled Java exception: java.lang.ArrayIndexOutOfBoundsException: Index 18581 out of bounds for length 16427
java.lang.ArrayIndexOutOfBoundsException: Index 18581 out of bounds for length 16427
   internalPutNoResize at org/jruby/RubyHash.java:561
           internalPut at org/jruby/RubyHash.java:535
           internalPut at org/jruby/RubyHash.java:525
   fastASetCheckString at org/jruby/RubyHash.java:1020
               op_aset at org/jruby/RubyHash.java:1055
                  call at org/jruby/RubyHash$INVOKER$i$2$0$op_aset.gen:-1
                  call at org/jruby/runtime/callsite/CachingCallSite.java:203
  invokeOther1:\=\{\}= at threads.rb:11
            threads.rb at threads.rb:11
           yieldDirect at org/jruby/runtime/CompiledIRBlockBody.java:146
         yieldSpecific at org/jruby/runtime/IRBlockBody.java:85
         yieldSpecific at org/jruby/runtime/Block.java:139
                 times at org/jruby/RubyFixnum.java:279
                  call at org/jruby/RubyInteger$INVOKER$i$0$0$times.gen:-1
                  call at org/jruby/runtime/callsite/CachingCallSite.java:151
              callIter at org/jruby/runtime/callsite/CachingCallSite.java:160
    invokeOther3:times at threads.rb:10
            threads.rb at threads.rb:10
            callDirect at org/jruby/runtime/CompiledIRBlockBody.java:136
                  call at org/jruby/runtime/IRBlockBody.java:77
                  call at org/jruby/runtime/Block.java:129
                  call at org/jruby/RubyProc.java:295
                  call at org/jruby/RubyProc.java:274
                  call at org/jruby/RubyProc.java:270
                   run at org/jruby/internal/runtime/RubyRunnable.java:105
                   run at java/lang/Thread.java:834&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;as well as on TruffleRuby:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;CodeRay highlight&quot;&gt;&lt;code&gt;truffleruby 19.1.1, like ruby 2.6.2, GraalVM CE Native [x86_64-linux]
Thread 1 done!
threads.rb:11:in `[]=&apos;: &amp;lt;no message&amp;gt; (NullPointerException) (RuntimeError)
        from org.truffleruby.core.hash.PackedArrayStrategy.getHashed(PackedArrayStrategy.java:41)
        from org.truffleruby.core.hash.SetNode.setPackedArray(SetNode.java:80)
        from org.truffleruby.core.hash.SetNodeGen.executeSet(SetNodeGen.java:37)
        from org.truffleruby.core.hash.HashNodes$SetIndexNode.set(HashNodes.java:239)
        from org.truffleruby.core.hash.HashNodesFactory$SetIndexNodeFactory$SetIndexNodeGen.execute(HashNodesFactory.java:632)
        from org.truffleruby.language.control.SequenceNode.execute(SequenceNode.java:34)
        from org.truffleruby.language.methods.ExceptionTranslatingNode.execute(ExceptionTranslatingNode.java:51)
        from org.truffleruby.language.RubyRootNode.execute(RubyRootNode.java:54)
        from org.graalvm.compiler.truffle.runtime.OptimizedCallTarget.callProxy(OptimizedCallTarget.java:328)
        from org.graalvm.compiler.truffle.runtime.OptimizedCallTarget.callRoot(OptimizedCallTarget.java:318)
Translated to internal error
        from threads.rb:11:in `block (3 levels) in &amp;lt;main&amp;gt;&apos;
        from threads.rb:10:in `times&apos;
        from threads.rb:10:in `block (2 levels) in &amp;lt;main&amp;gt;&apos;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;This happens because neither Ruby has synchronization when changing the internal structure of the Hash (which happens when for instance the hash needs to grow), and thus we can run into this issue.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Note also that this won&amp;#8217;t happen every time, as this is a &lt;a href=&quot;https://en.wikipedia.org/wiki/Race_condition&quot;&gt;race condition&lt;/a&gt;, so your results may vary :)&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;How to fix it? Consider replacing the hash with a &lt;a href=&quot;http://ruby-concurrency.github.io/concurrent-ruby/1.1.5/Concurrent/Map.html&quot;&gt;&lt;code&gt;Concurrent::Map&lt;/code&gt;&lt;/a&gt; or wrapping it with a lock.&lt;/p&gt;
&lt;/div&gt;</description>
        <pubDate>Mon, 26 Aug 2019 00:00:00 +0100</pubDate>
        <link>https://ivoanjo.me/blog/2019/08/26/quick-tip-unsafe-concurrent-ruby-hash-access/</link>
        <guid isPermaLink="true">https://ivoanjo.me/blog/2019/08/26/quick-tip-unsafe-concurrent-ruby-hash-access/</guid>
        <category>blog</category>
      </item>
      <item>
        <title>Kotlin Hack: Transparently replace class with interface</title>
        <description>&lt;div id=&quot;preamble&quot;&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;While working on an experiment using Kotlin recently, I ran into the following issue: I had a class&amp;#8201;&amp;#8212;&amp;#8201;let&amp;#8217;s call it &lt;code&gt;FooInteractor&lt;/code&gt;&amp;#8201;&amp;#8212;&amp;#8201;that I wanted to be able to replace with an implementation that did nothing in some cases.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;I had other classes that referenced it, which I did not want to have to change. I also had several places where &lt;code&gt;FooInteractor&lt;/code&gt; was instanced directly, via &lt;code&gt;FooInteractor(&amp;#8230;&amp;#8203;)&lt;/code&gt; which I also did not want to have to change.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;So I had the following challenge: Can I somehow &lt;strong&gt;only&lt;/strong&gt; change &lt;code&gt;FooInteractor&lt;/code&gt;, without touching any other file, and still allow it to be easily replaced?&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;As an example, let&amp;#8217;s use the following definition for &lt;code&gt;FooInteractor&lt;/code&gt;:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;pygments highlight&quot; style=&quot;background: #f8f8f8;&quot;&gt;&lt;code data-lang=&quot;kotlin&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span style=&quot;color: #008000; font-weight: bold&quot;&gt;class&lt;/span&gt; &lt;span style=&quot;color: #0000FF; font-weight: bold&quot;&gt;FooInteractor&lt;/span&gt;(&lt;span style=&quot;color: #008000; font-weight: bold&quot;&gt;private&lt;/span&gt; &lt;span style=&quot;color: #008000; font-weight: bold&quot;&gt;val&lt;/span&gt; repository: FooRepository) {
    &lt;span style=&quot;color: #008000; font-weight: bold&quot;&gt;fun&lt;/span&gt; &lt;span style=&quot;color: #0000FF&quot;&gt;call&lt;/span&gt;(&lt;span style=&quot;color: #008000; font-weight: bold&quot;&gt;val&lt;/span&gt; someArg: String) { &lt;span style=&quot;color: #408080; font-style: italic&quot;&gt;/* ... */&lt;/span&gt; }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;mocking-frameworks&quot;&gt;Mocking frameworks?&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;This use-case also comes up quite often in tests, and there the amazing &lt;a href=&quot;http://mockito.org/&quot;&gt;Mockito framework&lt;/a&gt;, or some similar tool is usually employed to automagically create an instance of &lt;code&gt;FooInteractor&lt;/code&gt; that has no behavior (or that we can attach custom behavior to).&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;But, in this case, I wanted to avoid having to add a dependency to mockito for just this simple use case.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;solution-part-1-introducing-an-interface&quot;&gt;Solution part 1: Introducing an interface&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;The first step was introducing an interface to replace the concrete implementation:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;pygments highlight&quot; style=&quot;background: #f8f8f8;&quot;&gt;&lt;code data-lang=&quot;kotlin&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span style=&quot;color: #008000; font-weight: bold&quot;&gt;interface&lt;/span&gt; &lt;span style=&quot;color: #0000FF; font-weight: bold&quot;&gt;FooInteractor&lt;/span&gt; {
    &lt;span style=&quot;color: #008000; font-weight: bold&quot;&gt;fun&lt;/span&gt; &lt;span style=&quot;color: #0000FF&quot;&gt;call&lt;/span&gt;(someArg: String)
}

&lt;span style=&quot;color: #008000; font-weight: bold&quot;&gt;class&lt;/span&gt; &lt;span style=&quot;color: #0000FF; font-weight: bold&quot;&gt;FooInteractorImpl&lt;/span&gt;(&lt;span style=&quot;color: #008000; font-weight: bold&quot;&gt;private&lt;/span&gt; &lt;span style=&quot;color: #008000; font-weight: bold&quot;&gt;val&lt;/span&gt; repository: FooRepository) : FooInteractor {
    &lt;span style=&quot;color: #008000; font-weight: bold&quot;&gt;override&lt;/span&gt; &lt;span style=&quot;color: #008000; font-weight: bold&quot;&gt;fun&lt;/span&gt; &lt;span style=&quot;color: #0000FF&quot;&gt;call&lt;/span&gt;(someArg: String) { &lt;span style=&quot;color: #408080; font-style: italic&quot;&gt;/* ... */&lt;/span&gt; }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;By renaming &lt;code&gt;FooInteractor&lt;/code&gt; to &lt;code&gt;FooInteractorImpl&lt;/code&gt; and introducing an interface with exactly the same signature for its functions, all of the code that referenced the &lt;code&gt;FooInteractor&lt;/code&gt; type transparently started using this interface.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&amp;#8230;&amp;#8203;and I could now do this:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;pygments highlight&quot; style=&quot;background: #f8f8f8;&quot;&gt;&lt;code data-lang=&quot;kotlin&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span style=&quot;color: #008000; font-weight: bold&quot;&gt;val&lt;/span&gt; emptyFoo = &lt;span style=&quot;color: #008000; font-weight: bold&quot;&gt;object&lt;/span&gt; : &lt;span style=&quot;color: #0000FF; font-weight: bold&quot;&gt;FooInteractor&lt;/span&gt; {
    &lt;span style=&quot;color: #008000; font-weight: bold&quot;&gt;override&lt;/span&gt; &lt;span style=&quot;color: #008000; font-weight: bold&quot;&gt;fun&lt;/span&gt; &lt;span style=&quot;color: #0000FF&quot;&gt;call&lt;/span&gt;(someArg: String) {
        println(&lt;span style=&quot;color: #BA2121&quot;&gt;&amp;quot;Empty foo called with $someArg&amp;quot;&lt;/span&gt;)
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;And I could use this &lt;code&gt;emptyFoo&lt;/code&gt; anywhere that takes a &lt;code&gt;FooInteractor&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;But, there was still an issue: what about places in the codebase that called the &lt;code&gt;FooInteractor&lt;/code&gt; constructors?&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;solution-part-2-faking-the-original-class-constructor&quot;&gt;Solution part 2: Faking the original class&apos; constructor&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Anywhere on my codebase where a &lt;code&gt;FooInteractor&lt;/code&gt; was created via&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;pygments highlight&quot; style=&quot;background: #f8f8f8;&quot;&gt;&lt;code data-lang=&quot;kotlin&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span style=&quot;color: #008000; font-weight: bold&quot;&gt;val&lt;/span&gt; fooInteractor = FooInteractor(repository = someRepository)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;was now failing, because &lt;code&gt;FooInteractor&lt;/code&gt; just became an interface.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;To solve this transparently, we can make use of the &lt;a href=&quot;https://kotlinlang.org/docs/reference/operator-overloading.html#invoke&quot;&gt;Invoke operator&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;The invoke operator allows writing an expression such as &lt;code&gt;someObject(&amp;#8230;&amp;#8203;)&lt;/code&gt; as an alias of &lt;code&gt;someObject.invoke(&amp;#8230;&amp;#8203;)&lt;/code&gt;. And funnily enough, constructors look exactly like that!&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;So yeah, a bit unexpectedly, we can use the invoke operator to make our new interface into a factory of implementation instances, transparently:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;pygments highlight&quot; style=&quot;background: #f8f8f8;&quot;&gt;&lt;code data-lang=&quot;kotlin&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span style=&quot;color: #008000; font-weight: bold&quot;&gt;interface&lt;/span&gt; &lt;span style=&quot;color: #0000FF; font-weight: bold&quot;&gt;FooInteractor&lt;/span&gt; {
    &lt;span style=&quot;color: #008000; font-weight: bold&quot;&gt;companion&lt;/span&gt; &lt;span style=&quot;color: #008000; font-weight: bold&quot;&gt;object&lt;/span&gt; {
        &lt;span style=&quot;color: #008000; font-weight: bold&quot;&gt;operator&lt;/span&gt; &lt;span style=&quot;color: #008000; font-weight: bold&quot;&gt;fun&lt;/span&gt; &lt;span style=&quot;color: #0000FF&quot;&gt;invoke&lt;/span&gt;(repository: FooRepository) =
            FooInteractorImpl(repository)
    }

    &lt;span style=&quot;color: #008000; font-weight: bold&quot;&gt;fun&lt;/span&gt; &lt;span style=&quot;color: #0000FF&quot;&gt;call&lt;/span&gt;(someArg: String)
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;And our example code will now work, even though it is now calling the &lt;code&gt;invoke&lt;/code&gt; function on the interactor interface, rather than the constructor directly:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;pygments highlight&quot; style=&quot;background: #f8f8f8;&quot;&gt;&lt;code data-lang=&quot;kotlin&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span style=&quot;color: #008000; font-weight: bold&quot;&gt;val&lt;/span&gt; fooInteractor = FooInteractor(repository = someRepository)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;And boom, done! We just introduced an interface by only changing the &lt;code&gt;FooInteractor&lt;/code&gt; class, and the rest of the codebase remains 100% unchanged.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Here&amp;#8217;s the full example, if you want to experiment with it:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;pygments highlight&quot; style=&quot;background: #f8f8f8;&quot;&gt;&lt;code data-lang=&quot;kotlin&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span style=&quot;border: 1px solid #FF0000&quot;&gt;#&lt;/span&gt;!/usr/bin/env kscript

&lt;span style=&quot;color: #408080; font-style: italic&quot;&gt;// Save this as example.kts and use https://github.com/holgerbrandl/kscript to run it&lt;/span&gt;

&lt;span style=&quot;color: #008000; font-weight: bold&quot;&gt;class&lt;/span&gt; &lt;span style=&quot;color: #0000FF; font-weight: bold&quot;&gt;FooRepository&lt;/span&gt;() { &lt;span style=&quot;color: #408080; font-style: italic&quot;&gt;/* ... */&lt;/span&gt; }

&lt;span style=&quot;color: #008000; font-weight: bold&quot;&gt;interface&lt;/span&gt; &lt;span style=&quot;color: #0000FF; font-weight: bold&quot;&gt;FooInteractor&lt;/span&gt; {
    &lt;span style=&quot;color: #008000; font-weight: bold&quot;&gt;companion&lt;/span&gt; &lt;span style=&quot;color: #008000; font-weight: bold&quot;&gt;object&lt;/span&gt; {
        &lt;span style=&quot;color: #008000; font-weight: bold&quot;&gt;operator&lt;/span&gt; &lt;span style=&quot;color: #008000; font-weight: bold&quot;&gt;fun&lt;/span&gt; &lt;span style=&quot;color: #0000FF&quot;&gt;invoke&lt;/span&gt;(repository: FooRepository) =
            FooInteractorImpl(repository)
    }

    &lt;span style=&quot;color: #008000; font-weight: bold&quot;&gt;fun&lt;/span&gt; &lt;span style=&quot;color: #0000FF&quot;&gt;call&lt;/span&gt;(someArg: String)
}

&lt;span style=&quot;color: #008000; font-weight: bold&quot;&gt;class&lt;/span&gt; &lt;span style=&quot;color: #0000FF; font-weight: bold&quot;&gt;FooInteractorImpl&lt;/span&gt;(&lt;span style=&quot;color: #008000; font-weight: bold&quot;&gt;private&lt;/span&gt; &lt;span style=&quot;color: #008000; font-weight: bold&quot;&gt;val&lt;/span&gt; repository: FooRepository) : FooInteractor {
    &lt;span style=&quot;color: #008000; font-weight: bold&quot;&gt;override&lt;/span&gt; &lt;span style=&quot;color: #008000; font-weight: bold&quot;&gt;fun&lt;/span&gt; &lt;span style=&quot;color: #0000FF&quot;&gt;call&lt;/span&gt;(someArg: String) {
        println(&lt;span style=&quot;color: #BA2121&quot;&gt;&amp;quot;Real foo called with $someArg&amp;quot;&lt;/span&gt;)
    }
}

&lt;span style=&quot;color: #008000; font-weight: bold&quot;&gt;val&lt;/span&gt; emptyFoo = &lt;span style=&quot;color: #008000; font-weight: bold&quot;&gt;object&lt;/span&gt; : &lt;span style=&quot;color: #0000FF; font-weight: bold&quot;&gt;FooInteractor&lt;/span&gt; {
    &lt;span style=&quot;color: #008000; font-weight: bold&quot;&gt;override&lt;/span&gt; &lt;span style=&quot;color: #008000; font-weight: bold&quot;&gt;fun&lt;/span&gt; &lt;span style=&quot;color: #0000FF&quot;&gt;call&lt;/span&gt;(someArg: String) {
        println(&lt;span style=&quot;color: #BA2121&quot;&gt;&amp;quot;Empty foo called with $someArg&amp;quot;&lt;/span&gt;)
    }
}

&lt;span style=&quot;color: #008000; font-weight: bold&quot;&gt;val&lt;/span&gt; someRepository = FooRepository()
&lt;span style=&quot;color: #008000; font-weight: bold&quot;&gt;val&lt;/span&gt; realFoo = FooInteractor(repository = someRepository)

emptyFoo.call(&lt;span style=&quot;color: #BA2121&quot;&gt;&amp;quot;Hello&amp;quot;&lt;/span&gt;)
realFoo.call(&lt;span style=&quot;color: #BA2121&quot;&gt;&amp;quot;World&amp;quot;&lt;/span&gt;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;And the expected output:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre&gt;Empty foo called with Hello
Real foo called with World&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;</description>
        <pubDate>Sat, 10 Aug 2019 00:00:00 +0100</pubDate>
        <link>https://ivoanjo.me/blog/2019/08/10/kotlin-hack-transparently-replace-class-with-interface/</link>
        <guid isPermaLink="true">https://ivoanjo.me/blog/2019/08/10/kotlin-hack-transparently-replace-class-with-interface/</guid>
        <category>blog</category>
      </item>
      <item>
        <title>Kotlin for Rubyists</title>
        <description>&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Although I&amp;#8217;ve never seen Ruby cited as an inspiration for Kotlin, ever since I first ran into it, I couldn&amp;#8217;t but notice how closely it resembles Ruby.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Kotlin shares many of Ruby&amp;#8217;s niceties: you can do a lot with a very small amount of code; its standard library includes many useful tools that help you express your intent clearly; it can be used to create beautiful domain specific languages; it has an interactive shell; and it includes a number of functional constructs. Even its syntax is very Ruby-like at times&amp;#8201;&amp;#8212;&amp;#8201;it has a block-lookalike!&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;So if they share many similarities, what does Kotlin bring to Rubyists? Quite a bit, actually.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;If you find yourself needing to work or interoperate with a Java environment, Kotlin and its tooling were built to allow easy migration from Java. It&amp;#8217;s very easy to incrementally move a codebase from Java to Kotlin, and there are even automatic translation tools. Yes, this also means that Kotlin can make use of all the niceties of the Java and JVM environment: just-in-time compilation, state-of-the-art garbage collection, first-class concurrency tooling, and its many, many libraries and frameworks.
Additionally, it is also a first-class citizen and officially supported by Google as an alternative to Java when building Android applications.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;For those seeking static validation, Kotlin is both statically typed and null-safe. Static typing ensures that a number of common errors happen at compile-time, when you&amp;#8217;re preparing your code for execution, rather than at runtime (no more mysterious &lt;code&gt;NoMethodError&lt;/code&gt;s!). Null safety means that the compiler can distinguish between nullable and non-nullable types, and is able to enforce that if before calling a method on something that can be &lt;code&gt;null&lt;/code&gt; (or &lt;code&gt;nil&lt;/code&gt;), you&amp;#8217;ve checked if the value is not &lt;code&gt;null&lt;/code&gt;.
Kotlin&amp;#8217;s type system also includes a number of other niceties, such as zero-overhead &lt;strong&gt;inline classes&lt;/strong&gt; that work as a kind of aliases to existing classes&amp;#8201;&amp;#8212;&amp;#8201;e.g. you&amp;#8217;ll be able to get a compile-time error if you try to assign a &lt;code&gt;Password&lt;/code&gt; value to an &lt;code&gt;Username&lt;/code&gt; field, even if both are actually compiled as &lt;code&gt;String&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Kotlin can also be used for front-end development: It can be compiled into javascript code and easily work with common javascript libraries, it can understand TypeScript definitions, and can also by used on Node.js.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Last but not least, Kotlin can also be compiled&amp;#8201;&amp;#8212;&amp;#8201;using LLVM&amp;#8201;&amp;#8212;&amp;#8201;into an optimized machine code executable. This feature is still experimental, and it allows interoperating with compiled languages such as C/C++/Objective-C/Swift.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;In short, although I remain a committed Ruby lover 😉, I believe that Kotlin deserves a place in every Rubyist&amp;#8217;s toolkit.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Curious to check it out? At the 2019 edition of the awesome &lt;a href=&quot;https://rubyonice.com/&quot;&gt;Ruby on Ice&lt;/a&gt; conference, I presented a workshop called &amp;#8220;Kotlin for Rubyists&amp;#8221;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;This workshop covered not only an introduction to the language, but also to the ecosystem: how to install it, which build system to use, testing, performance tooling, etc.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;We also build several example applications (including a nice microservice). I&amp;#8217;ve made available all of the example material &lt;a href=&quot;https://gitlab.com/ivoanjo/kotlin-for-rubyists&quot;&gt;on this git repository&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;You can find the slide deck from the workshop embedded below:&lt;/p&gt;
&lt;/div&gt;
&lt;iframe src=&quot;//slides.com/ianjo/kotlin-for-rubyists/embed&quot; width=&quot;576&quot; height=&quot;420&quot; scrolling=&quot;no&quot; frameborder=&quot;0&quot; notes=&quot;no&quot; webkitallowfullscreen mozallowfullscreen allowfullscreen&gt;&lt;/iframe&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Feedback is very welcome 😁&lt;/p&gt;
&lt;/div&gt;</description>
        <pubDate>Tue, 05 Mar 2019 00:00:00 +0000</pubDate>
        <link>https://ivoanjo.me/blog/2019/03/05/kotlin-for-rubyists/</link>
        <guid isPermaLink="true">https://ivoanjo.me/blog/2019/03/05/kotlin-for-rubyists/</guid>
        <category>blog</category>
      </item>
      <item>
        <title>Spotting unsafe Ruby patterns - Talk recording</title>
        <description>&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Writing Ruby code that uses multiple threads is a great way to get better performance and to take advantage of modern laptops and servers. It can also be quite daunting due to the often-feared “concurrency bugs”.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;In this talk, recorded at the Fullstack LX Ruby meetup, I introduce a number of pitfalls to watch out for, presenting correct (and fast!) alternatives for each.&lt;/p&gt;
&lt;/div&gt;
&lt;iframe width=&quot;736&quot; height=&quot;420&quot; src=&quot;https://www.youtube.com/embed/5VHc27SYAIw&quot; title=&quot;YouTube video player&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; referrerpolicy=&quot;strict-origin-when-cross-origin&quot; allowfullscreen&gt;&lt;/iframe&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Slide deck:&lt;/p&gt;
&lt;/div&gt;
&lt;iframe src=&quot;//slides.com/ianjo/spotting-unsafe-concurrent-ruby-patterns-fullstack-lx/embed&quot; width=&quot;576&quot; height=&quot;420&quot; scrolling=&quot;no&quot; frameborder=&quot;0&quot; webkitallowfullscreen mozallowfullscreen allowfullscreen&gt;&lt;/iframe&gt;</description>
        <pubDate>Sat, 13 Oct 2018 00:00:00 +0100</pubDate>
        <link>https://ivoanjo.me/blog/2018/10/13/spotting-unsafe-ruby-patterns/</link>
        <guid isPermaLink="true">https://ivoanjo.me/blog/2018/10/13/spotting-unsafe-ruby-patterns/</guid>
        <category>blog</category>
      </item>
      <item>
        <title>Writing to a Java TreeMap concurrently can lead to an infinite loop during reads</title>
        <description>&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;The &lt;a href=&quot;https://docs.oracle.com/javase/8/docs/api/java/util/TreeMap.html&quot;&gt;&lt;code&gt;java.util.TreeMap&lt;/code&gt;&lt;/a&gt; documentation warns that the underlying implementation for this &lt;code&gt;Map&lt;/code&gt; is not synchronized&amp;#8201;&amp;#8212;&amp;#8201;and thus it is not thread-safe.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;But have you ever wondered what happens if you ignore that warning and you write an application that concurrently writes to the map from different threads? Intuitively, I&amp;#8217;d probably expect some entries to be lost, or to sometimes get a &lt;code&gt;NullPointerException&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;But did you know that&amp;#8201;&amp;#8212;&amp;#8201;at least with the current implementation shipped on OpenJDK&amp;#8201;&amp;#8212;&amp;#8201;&lt;strong&gt;you can actually corrupt the &lt;code&gt;TreeMap&lt;/code&gt; in such a way that attempts to read the map will result in your code getting stuck on an infinite loop&lt;/strong&gt;?&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;This happens because the &lt;code&gt;TreeMap&lt;/code&gt; is implemented as a &lt;a href=&quot;https://en.wikipedia.org/wiki/Red%E2%80%93black_tree&quot;&gt;red-black tree&lt;/a&gt;, a self-balancing tree algorithm. As new elements are inserted into the tree, the tree is rebalanced&amp;#8201;&amp;#8212;&amp;#8201;elements are moved around so that the tree is kept height-balanced. (See the Wikipedia article for details, as they explain a lot better than I do!)&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;When several threads are adding new entries to a &lt;code&gt;TreeMap&lt;/code&gt; at the same time, those threads also compete to rebalance the tree concurrently. And because rebalancing entails changing several pointers, the result is that the tree may form internal loops&amp;#8201;&amp;#8212;&amp;#8201;thus no longer being a tree.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;The following application is able to show this issue. It repeatedly creates a new &lt;code&gt;TreeMap&lt;/code&gt;, writes to it using two different concurrent threads, and then navigates the internal map structure using reflection to check if the &lt;code&gt;TreeMap&lt;/code&gt; formed a loop.
When it finds a loop, it prints it.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;CodeRay highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;import&lt;/span&gt; &lt;span style=&quot;color:#B44;font-weight:bold&quot;&gt;java.util&lt;/span&gt;.*;
&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;import&lt;/span&gt; &lt;span style=&quot;color:#B44;font-weight:bold&quot;&gt;java.lang.reflect&lt;/span&gt;.*;
&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;import&lt;/span&gt; &lt;span style=&quot;color:#B44;font-weight:bold&quot;&gt;java.util.Map.Entry&lt;/span&gt;;

&lt;span style=&quot;color:#007&quot;&gt;@SuppressWarnings&lt;/span&gt;(&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;unchecked&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;)
&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;public&lt;/span&gt; &lt;span style=&quot;color:#339;font-weight:bold&quot;&gt;class&lt;/span&gt; &lt;span style=&quot;color:#B06;font-weight:bold&quot;&gt;ConcurrentTreeMapLoopReproducer&lt;/span&gt; {
  &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;public&lt;/span&gt; &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;static&lt;/span&gt; &lt;span style=&quot;color:#339;font-weight:bold&quot;&gt;void&lt;/span&gt; main(&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;String&lt;/span&gt; ... args) &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;throws&lt;/span&gt; &lt;span style=&quot;color:#C00;font-weight:bold&quot;&gt;Exception&lt;/span&gt; {
    &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;System&lt;/span&gt;.out.println(&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;Running on Java &lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; + &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;System&lt;/span&gt;.getProperty(&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;java.version&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;));
    &lt;span style=&quot;color:#339;font-weight:bold&quot;&gt;int&lt;/span&gt; insertUpTo = &lt;span style=&quot;color:#00D&quot;&gt;20&lt;/span&gt;;
    &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;if&lt;/span&gt; (args.length &amp;gt; &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;) {
      insertUpTo = &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;Integer&lt;/span&gt;.parseInt(args[&lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;]);
    }
    &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;System&lt;/span&gt;.out.println(&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;Using insertUpTo=&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; + insertUpTo);

    &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;new&lt;/span&gt; ConcurrentTreeMapLoopReproducer(insertUpTo).call();
  }

  &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;TreeMap&lt;/span&gt;&amp;lt;&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;Integer&lt;/span&gt;,&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;Integer&lt;/span&gt;&amp;gt; brokenMap = &lt;span style=&quot;color:#069&quot;&gt;null&lt;/span&gt;;
  &lt;span style=&quot;color:#339;font-weight:bold&quot;&gt;int&lt;/span&gt; insertUpTo;

  ConcurrentTreeMapLoopReproducer(&lt;span style=&quot;color:#339;font-weight:bold&quot;&gt;int&lt;/span&gt; insertUpTo) {
    &lt;span style=&quot;color:#950&quot;&gt;this&lt;/span&gt;.insertUpTo = insertUpTo;
  }

  &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;static&lt;/span&gt; &lt;span style=&quot;color:#339;font-weight:bold&quot;&gt;class&lt;/span&gt; &lt;span style=&quot;color:#B06;font-weight:bold&quot;&gt;LoopStep&lt;/span&gt; {
    Entry&amp;lt;&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;Integer&lt;/span&gt;,&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;Integer&lt;/span&gt;&amp;gt; entry;
    &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;String&lt;/span&gt; direction;
    LoopStep next;

    LoopStep(Entry&amp;lt;&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;Integer&lt;/span&gt;,&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;Integer&lt;/span&gt;&amp;gt; entry) { &lt;span style=&quot;color:#950&quot;&gt;this&lt;/span&gt;(entry, &lt;span style=&quot;color:#069&quot;&gt;null&lt;/span&gt;, &lt;span style=&quot;color:#069&quot;&gt;null&lt;/span&gt;); }
    LoopStep(Entry&amp;lt;&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;Integer&lt;/span&gt;,&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;Integer&lt;/span&gt;&amp;gt; entry, &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;String&lt;/span&gt; direction, LoopStep next) {
      &lt;span style=&quot;color:#950&quot;&gt;this&lt;/span&gt;.entry = entry;
      &lt;span style=&quot;color:#950&quot;&gt;this&lt;/span&gt;.direction = direction;
      &lt;span style=&quot;color:#950&quot;&gt;this&lt;/span&gt;.next = next;
    }

    &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;public&lt;/span&gt; &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;String&lt;/span&gt; toString() {
      &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;if&lt;/span&gt; (next != &lt;span style=&quot;color:#069&quot;&gt;null&lt;/span&gt;) {
        &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;return&lt;/span&gt; &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; + entry.getKey() + &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt; --&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; + direction + &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;--&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; + next;
      } &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;else&lt;/span&gt; {
        &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;return&lt;/span&gt; entry.getKey().toString();
      }
    }
  }

  &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;public&lt;/span&gt; &lt;span style=&quot;color:#339;font-weight:bold&quot;&gt;void&lt;/span&gt; call() &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;throws&lt;/span&gt; &lt;span style=&quot;color:#C00;font-weight:bold&quot;&gt;Exception&lt;/span&gt; {
    LoopStep loopPath = &lt;span style=&quot;color:#069&quot;&gt;null&lt;/span&gt;;
    &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;System&lt;/span&gt;.out.print(&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;Attempting to trigger looping TreeMap&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;);
    &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;for&lt;/span&gt; (&lt;span style=&quot;color:#339;font-weight:bold&quot;&gt;int&lt;/span&gt; attempts = &lt;span style=&quot;color:#00D&quot;&gt;1&lt;/span&gt;; loopPath == &lt;span style=&quot;color:#069&quot;&gt;null&lt;/span&gt;; attempts++) {
      &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;System&lt;/span&gt;.out.print(&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;);
      &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;System&lt;/span&gt;.out.flush();

      brokenMap = tryToTriggerLoopingTreeMap();
      loopPath = findLoop(brokenMap);
    }

    &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;System&lt;/span&gt;.out.println(&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#b0b&quot;&gt;\n&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;Was able to reproduce loop in map: &lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; + loopPath);

    &lt;span style=&quot;color:#777&quot;&gt;// Uncomment this to see the loop in action: This will never finish&lt;/span&gt;
    &lt;span style=&quot;color:#777&quot;&gt;//brokenMap.values().toArray();&lt;/span&gt;
  }

  &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;static&lt;/span&gt; &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;TreeMap&lt;/span&gt;&amp;lt;&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;Integer&lt;/span&gt;,&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;Integer&lt;/span&gt;&amp;gt; tryToTriggerLoopingTreeMap() &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;throws&lt;/span&gt; &lt;span style=&quot;color:#C00;font-weight:bold&quot;&gt;Exception&lt;/span&gt; {
    &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;TreeMap&lt;/span&gt;&amp;lt;&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;Integer&lt;/span&gt;,&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;Integer&lt;/span&gt;&amp;gt; map = &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;new&lt;/span&gt; &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;TreeMap&lt;/span&gt;&amp;lt;&amp;gt;();

    &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;Thread&lt;/span&gt; t1 = &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;new&lt;/span&gt; &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;Thread&lt;/span&gt;(() -&amp;gt; { &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;for&lt;/span&gt; (&lt;span style=&quot;color:#339;font-weight:bold&quot;&gt;int&lt;/span&gt; i = &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;; i &amp;lt; &lt;span style=&quot;color:#00D&quot;&gt;20&lt;/span&gt;; i += &lt;span style=&quot;color:#00D&quot;&gt;2&lt;/span&gt;) &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;try&lt;/span&gt; { map.put(i, i); } &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;catch&lt;/span&gt; (&lt;span style=&quot;color:#C00;font-weight:bold&quot;&gt;Exception&lt;/span&gt; e) { } });
    &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;Thread&lt;/span&gt; t2 = &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;new&lt;/span&gt; &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;Thread&lt;/span&gt;(() -&amp;gt; { &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;for&lt;/span&gt; (&lt;span style=&quot;color:#339;font-weight:bold&quot;&gt;int&lt;/span&gt; i = &lt;span style=&quot;color:#00D&quot;&gt;1&lt;/span&gt;; i &amp;lt; &lt;span style=&quot;color:#00D&quot;&gt;20&lt;/span&gt;; i += &lt;span style=&quot;color:#00D&quot;&gt;2&lt;/span&gt;) &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;try&lt;/span&gt; { map.put(i, i); } &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;catch&lt;/span&gt; (&lt;span style=&quot;color:#C00;font-weight:bold&quot;&gt;Exception&lt;/span&gt; e) { } });
    t1.start();
    t2.start();
    t1.join();
    t2.join();

    &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;return&lt;/span&gt; map;
  }

  &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;static&lt;/span&gt; LoopStep findLoop(&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;TreeMap&lt;/span&gt;&amp;lt;&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;Integer&lt;/span&gt;,&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;Integer&lt;/span&gt;&amp;gt; map) &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;throws&lt;/span&gt; &lt;span style=&quot;color:#C00;font-weight:bold&quot;&gt;Exception&lt;/span&gt; {
    &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;Field&lt;/span&gt; rootField = &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;TreeMap&lt;/span&gt;.class.getDeclaredField(&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;root&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;);
    rootField.setAccessible(&lt;span style=&quot;color:#069&quot;&gt;true&lt;/span&gt;);

    Entry&amp;lt;&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;Integer&lt;/span&gt;,&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;Integer&lt;/span&gt;&amp;gt; rootEntry = (Entry&amp;lt;&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;Integer&lt;/span&gt;,&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;Integer&lt;/span&gt;&amp;gt;) rootField.get(map);

    &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;return&lt;/span&gt; findLoopRecursive(&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;new&lt;/span&gt; &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;ArrayList&lt;/span&gt;&amp;lt;&amp;gt;(), rootEntry);
  }

  &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;static&lt;/span&gt; LoopStep findLoopRecursive(&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;List&lt;/span&gt;&amp;lt;Entry&amp;lt;&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;Integer&lt;/span&gt;,&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;Integer&lt;/span&gt;&amp;gt;&amp;gt; currentPath, Entry&amp;lt;&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;Integer&lt;/span&gt;,&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;Integer&lt;/span&gt;&amp;gt; entry) &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;throws&lt;/span&gt; &lt;span style=&quot;color:#C00;font-weight:bold&quot;&gt;Exception&lt;/span&gt; {
    &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;if&lt;/span&gt; (entry == &lt;span style=&quot;color:#069&quot;&gt;null&lt;/span&gt;) &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;return&lt;/span&gt; &lt;span style=&quot;color:#069&quot;&gt;null&lt;/span&gt;;

    &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;if&lt;/span&gt; (currentPath.contains(entry)) {
      currentPath.add(entry);
      &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;return&lt;/span&gt; &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;new&lt;/span&gt; LoopStep(entry);
    }

    currentPath.add(entry);

    LoopStep result = &lt;span style=&quot;color:#069&quot;&gt;null&lt;/span&gt;;

    result = findLoopRecursive(currentPath, get(&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;left&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, entry));
    &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;if&lt;/span&gt; (result != &lt;span style=&quot;color:#069&quot;&gt;null&lt;/span&gt;) &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;return&lt;/span&gt; &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;new&lt;/span&gt; LoopStep(entry, &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;left&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, result);
    result = findLoopRecursive(currentPath, get(&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;right&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, entry));
    &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;if&lt;/span&gt; (result != &lt;span style=&quot;color:#069&quot;&gt;null&lt;/span&gt;) &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;return&lt;/span&gt; &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;new&lt;/span&gt; LoopStep(entry, &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;right&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, result);

    currentPath.remove(entry);

    &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;return&lt;/span&gt; &lt;span style=&quot;color:#069&quot;&gt;null&lt;/span&gt;;
  }

  &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;static&lt;/span&gt; Entry&amp;lt;&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;Integer&lt;/span&gt;,&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;Integer&lt;/span&gt;&amp;gt; get(&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;String&lt;/span&gt; direction, Entry&amp;lt;&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;Integer&lt;/span&gt;,&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;Integer&lt;/span&gt;&amp;gt; parent) &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;throws&lt;/span&gt; &lt;span style=&quot;color:#C00;font-weight:bold&quot;&gt;Exception&lt;/span&gt; {
    &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;Field&lt;/span&gt; field = parent.getClass().getDeclaredField(direction);
    field.setAccessible(&lt;span style=&quot;color:#069&quot;&gt;true&lt;/span&gt;);
    &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;return&lt;/span&gt; (Entry&amp;lt;&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;Integer&lt;/span&gt;,&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;Integer&lt;/span&gt;&amp;gt;) field.get(parent);
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;(Ufff. Java can get so verbose!)&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Because this is a concurrency issue, this code is not always successful in triggering an issue.&lt;sup class=&quot;footnote&quot;&gt;[&lt;a id=&quot;_footnoteref_1&quot; class=&quot;footnote&quot; href=&quot;#_footnotedef_1&quot; title=&quot;View footnote.&quot;&gt;1&lt;/a&gt;]&lt;/sup&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;On other runs, you may get an infinite loop during a &lt;code&gt;put()&lt;/code&gt; operation.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;But in most cases you&amp;#8217;ll get something like this:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre&gt;$ java ConcurrentTreeMapLoopReproducer
Running on Java 10
Using insertUpTo=20
Attempting to trigger looping TreeMap.WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by ConcurrentTreeMapLoopReproducer (file:/home/knuckles/projects/treemap-blog/) to field java.util.TreeMap.root
WARNING: Please consider reporting this to the maintainers of ConcurrentTreeMapLoopReproducer
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release
..............
Was able to reproduce loop in map: 10 --left--&amp;gt; 5 --right--&amp;gt; 14 --left--&amp;gt; 10&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;What does this mean? It means that internally, the tree has formed a loop.&lt;sup class=&quot;footnote&quot;&gt;[&lt;a id=&quot;_footnoteref_2&quot; class=&quot;footnote&quot; href=&quot;#_footnotedef_2&quot; title=&quot;View footnote.&quot;&gt;2&lt;/a&gt;]&lt;/sup&gt; Here&amp;#8217;s how this one specifically looks like:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;imageblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;img src=&quot;/img/broken-tree.svg&quot; alt=&quot;broken tree&quot;&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;And here&amp;#8217;s a very simple animation of what would happen if you were to call &lt;code&gt;get(9)&lt;/code&gt; on such a tree:&lt;sup class=&quot;footnote&quot;&gt;[&lt;a id=&quot;_footnoteref_3&quot; class=&quot;footnote&quot; href=&quot;#_footnotedef_3&quot; title=&quot;View footnote.&quot;&gt;3&lt;/a&gt;]&lt;/sup&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;imageblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;img src=&quot;/img/broken-tree-animation.gif&quot; alt=&quot;broken tree animation&quot;&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Another way to cause an infinite loop is to uncomment the line containing &lt;code&gt;//brokenMap.values().toArray();&lt;/code&gt;. This operation attempts to iterate the map, and gets stuck on the loop forever.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;As always, be careful when combining concurrency and mutation. And thanks to my awesome colleague Oli for the really interesting debugging session.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&quot;footnotes&quot;&gt;
&lt;hr&gt;
&lt;div class=&quot;footnote&quot; id=&quot;_footnotedef_1&quot;&gt;
&lt;a href=&quot;#_footnoteref_1&quot;&gt;1&lt;/a&gt;. You may want to try increase the &lt;code&gt;insertUpTo&lt;/code&gt; parameter or adding more threads if you&amp;#8217;re having trouble reproducing the issue on your own machine.
&lt;/div&gt;
&lt;div class=&quot;footnote&quot; id=&quot;_footnotedef_2&quot;&gt;
&lt;a href=&quot;#_footnoteref_2&quot;&gt;2&lt;/a&gt;. It&amp;#8217;s no longer a tree. Insert &quot;not being in Kansas&quot; joke.
&lt;/div&gt;
&lt;div class=&quot;footnote&quot; id=&quot;_footnotedef_3&quot;&gt;
&lt;a href=&quot;#_footnoteref_3&quot;&gt;3&lt;/a&gt;. Note that it&amp;#8217;s not always possible to find a key &lt;code&gt;k&lt;/code&gt; such that &lt;code&gt;get(k)&lt;/code&gt; generates a loop. I leave as an exercise to the reader to discover why 😁.
&lt;/div&gt;
&lt;/div&gt;</description>
        <pubDate>Sat, 21 Jul 2018 00:00:00 +0100</pubDate>
        <link>https://ivoanjo.me/blog/2018/07/21/writing-to-a-java-treemap-concurrently-can-lead-to-an-infinite-loop-during-reads/</link>
        <guid isPermaLink="true">https://ivoanjo.me/blog/2018/07/21/writing-to-a-java-treemap-concurrently-can-lead-to-an-infinite-loop-during-reads/</guid>
        <category>blog</category>
      </item>
      <item>
        <title>TIL: Java hides lambda frames in stack traces</title>
        <description>&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;While playing around with Java stack traces today, I noticed something that I had never noticed before: lambda frames do not show up in stack traces!&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;For instance, consider the following pre-Java 8 example:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;CodeRay highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;public&lt;/span&gt; &lt;span style=&quot;color:#339;font-weight:bold&quot;&gt;class&lt;/span&gt; &lt;span style=&quot;color:#B06;font-weight:bold&quot;&gt;VisibleLambda&lt;/span&gt; {
  &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;public&lt;/span&gt; &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;static&lt;/span&gt; &lt;span style=&quot;color:#339;font-weight:bold&quot;&gt;void&lt;/span&gt; main(&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;String&lt;/span&gt;&lt;span style=&quot;color:#339;font-weight:bold&quot;&gt;[]&lt;/span&gt; args) {
    foo(&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;new&lt;/span&gt; &lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;Runnable&lt;/span&gt;() {
      &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;public&lt;/span&gt; &lt;span style=&quot;color:#339;font-weight:bold&quot;&gt;void&lt;/span&gt; run() {
        bar();
      }
    });
  }

  &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;static&lt;/span&gt; &lt;span style=&quot;color:#339;font-weight:bold&quot;&gt;void&lt;/span&gt; foo(&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;Runnable&lt;/span&gt; lambda) {
    lambda.run();
  }

  &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;static&lt;/span&gt; &lt;span style=&quot;color:#339;font-weight:bold&quot;&gt;void&lt;/span&gt; bar() {
    &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;throw&lt;/span&gt; &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;new&lt;/span&gt; &lt;span style=&quot;color:#C00;font-weight:bold&quot;&gt;RuntimeException&lt;/span&gt;();
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;In the &lt;code&gt;main&lt;/code&gt; method, we create an anonymous inner class that implements &lt;code&gt;Runnable&lt;/code&gt; and calls &lt;code&gt;bar&lt;/code&gt; when run.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;The resulting output for this program is as expected:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;CodeRay highlight&quot;&gt;&lt;code&gt;Exception in thread &amp;quot;main&amp;quot; java.lang.RuntimeException
        at VisibleLambda.bar(VisibleLambda.java:15)
        at VisibleLambda$1.run(VisibleLambda.java:5)
        at VisibleLambda.foo(VisibleLambda.java:11)
        at VisibleLambda.main(VisibleLambda.java:3)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Checks out: &lt;code&gt;main&lt;/code&gt; calls &lt;code&gt;foo&lt;/code&gt;, which then calls the &lt;code&gt;Runnable::run&lt;/code&gt; method (here implemented by a class automatically named &lt;code&gt;VisibleLambda$1&lt;/code&gt;), which then calls &lt;code&gt;bar&lt;/code&gt;. So far, so good, and this matched my understanding of how this works together.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;But consider now what happens when we switch to using a Java 8 lambda:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;CodeRay highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;public&lt;/span&gt; &lt;span style=&quot;color:#339;font-weight:bold&quot;&gt;class&lt;/span&gt; &lt;span style=&quot;color:#B06;font-weight:bold&quot;&gt;HiddenLambda&lt;/span&gt; {
  &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;public&lt;/span&gt; &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;static&lt;/span&gt; &lt;span style=&quot;color:#339;font-weight:bold&quot;&gt;void&lt;/span&gt; main(&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;String&lt;/span&gt;&lt;span style=&quot;color:#339;font-weight:bold&quot;&gt;[]&lt;/span&gt; args) {
    foo(() -&amp;gt; bar());
  }

  &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;static&lt;/span&gt; &lt;span style=&quot;color:#339;font-weight:bold&quot;&gt;void&lt;/span&gt; foo(&lt;span style=&quot;color:#0a8;font-weight:bold&quot;&gt;Runnable&lt;/span&gt; lambda) {
    lambda.run();
  }

  &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;static&lt;/span&gt; &lt;span style=&quot;color:#339;font-weight:bold&quot;&gt;void&lt;/span&gt; bar() {
    &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;throw&lt;/span&gt; &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;new&lt;/span&gt; &lt;span style=&quot;color:#C00;font-weight:bold&quot;&gt;RuntimeException&lt;/span&gt;();
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&amp;#8230;&amp;#8203;and the output is:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;CodeRay highlight&quot;&gt;&lt;code&gt;Exception in thread &amp;quot;main&amp;quot; java.lang.RuntimeException
        at HiddenLambda.bar(HiddenLambda.java:11)
        at HiddenLambda.lambda$main$0(HiddenLambda.java:3)
        at HiddenLambda.foo(HiddenLambda.java:7)
        at HiddenLambda.main(HiddenLambda.java:3)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Did you see it? Two interesting things happened here. One is that a new method named &lt;code&gt;lambda$main$0&lt;/code&gt; appeared in the &lt;code&gt;HiddenLambda&lt;/code&gt; class. The other is that our &lt;code&gt;Runnable&lt;/code&gt; is gone&amp;#8201;&amp;#8212;&amp;#8201;nowhere on the stack we can see a &lt;code&gt;run&lt;/code&gt; method being called, although it is definitely there.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;So what&amp;#8217;s the &lt;code&gt;lambda$main$0&lt;/code&gt;? Using &lt;code&gt;javap -p -c HiddenLambda&lt;/code&gt; we can see that it contains the code to our little lambda:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;CodeRay highlight&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;&lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;public&lt;/span&gt; &lt;span style=&quot;color:#339;font-weight:bold&quot;&gt;class&lt;/span&gt; &lt;span style=&quot;color:#B06;font-weight:bold&quot;&gt;HiddenLambda&lt;/span&gt; {
  &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;private&lt;/span&gt; &lt;span style=&quot;color:#088;font-weight:bold&quot;&gt;static&lt;/span&gt; &lt;span style=&quot;color:#339;font-weight:bold&quot;&gt;void&lt;/span&gt; lambda&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;$&lt;/span&gt;main&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;();
    Code:
       &lt;span style=&quot;color:#00D&quot;&gt;0&lt;/span&gt;: invokestatic  &lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;#&lt;/span&gt;&lt;span style=&quot;color:#00D&quot;&gt;7&lt;/span&gt;                  &lt;span style=&quot;color:#777&quot;&gt;// Method bar:()V&lt;/span&gt;
       &lt;span style=&quot;color:#00D&quot;&gt;3&lt;/span&gt;: &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;return&lt;/span&gt;
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;So where&amp;#8217;s our &lt;code&gt;Runnable&lt;/code&gt;? Here the plot thickens. It turns out that Java 8 &lt;a href=&quot;https://github.com/bpupadhyaya/openjdk-8/blob/master/jdk/src/share/classes/java/lang/invoke/LambdaForm.java#L1597-L1604&quot;&gt;introduced a new, internal-only magic annotation called &lt;code&gt;@java.lang.invoke.LambdaForm$Hidden&lt;/code&gt;&lt;/a&gt;. This annotation is used in many methods used by lambdas, and in the lambdas themselves.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;When the JVM &lt;a href=&quot;https://github.com/bpupadhyaya/openjdk-8/blob/master/hotspot/src/share/vm/classfile/classFileParser.cpp#L1825-L1826&quot;&gt;is reading Java classes containing methods that are tagged with this magic annotation&lt;/a&gt;, it sets an internal flag on each method predictably called &lt;code&gt;_hidden&lt;/code&gt;. Then, quite simply, in the code implementing &lt;code&gt;Throwable::fill_in_stack_trace&lt;/code&gt; &lt;a href=&quot;https://github.com/bpupadhyaya/openjdk-8/blob/45af329463a45955ea2759b89cb0ebfe40570c3f/hotspot/src/share/vm/classfile/javaClasses.cpp#L1632-L1633&quot;&gt;this flag is checked&lt;/a&gt; and any methods tagged with it are not included in the stack trace.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;After reading a bit more of the source code, I&amp;#8217;ve discovered that behavior can be controlled with command-line options: &lt;code&gt;-XX:+UnlockDiagnosticVMOptions -XX:+ShowHiddenFrames&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;So finally, here it is in action:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;CodeRay highlight&quot;&gt;&lt;code data-lang=&quot;bash&quot;&gt;$ java -XX:+UnlockDiagnosticVMOptions -XX:+ShowHiddenFrames HiddenLambda
Exception in thread &amp;quot;main&amp;quot; java.lang.RuntimeException
        at HiddenLambda.bar(HiddenLambda.java:11)
        at HiddenLambda.lambda$main$0(HiddenLambda.java:3)
        at HiddenLambda$$Lambda$1/791452441.run(&amp;lt;Unknown&amp;gt;:1000000)
        at HiddenLambda.foo(HiddenLambda.java:7)
        at HiddenLambda.main(HiddenLambda.java:3)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;</description>
        <pubDate>Thu, 21 Jun 2018 00:00:00 +0100</pubDate>
        <link>https://ivoanjo.me/blog/2018/06/21/til-java-hides-lambda-frames-in-stack-traces/</link>
        <guid isPermaLink="true">https://ivoanjo.me/blog/2018/06/21/til-java-hides-lambda-frames-in-stack-traces/</guid>
        <category>blog</category>
      </item>
      <item>
        <title>My thoughts on, and how I approach code reviews</title>
        <description>&lt;div id=&quot;preamble&quot;&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;A few weeks back while I was having very interesting conversations with colleagues about code reviews I sat down and wrote some topics on how (and why) I take them on.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;There are already a lot of awesome articles online on what you should be on the look out when reviewing code&amp;#8201;&amp;#8212;&amp;#8201;such as &lt;a href=&quot;https://github.com/thoughtbot/guides/tree/master/code-review&quot;&gt;this great one by thoughtbot&lt;/a&gt;&amp;#8201;&amp;#8212;&amp;#8201;but my objective on this exercise is to focus on improving the code reviews themselves, not on specific code patterns.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Furthermore, most of my notes below are focused on how I like to approach them from the submitter side---not the reviewer!&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;So, without further ado, here are my thoughts on code reviews, in easy-to-digest bullets:&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;part-i-before-submitting-a-review&quot;&gt;Part I: Before submitting a review&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;1-commits-tell-a-story&quot;&gt;1. Commits tell a story&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;The more complex the change, the more important is to tell a story&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Commits and commit messages &lt;strong&gt;SHOULD explain the why&lt;/strong&gt; in addition to the &lt;strong&gt;what&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Aimed at other team members and your future self&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Can someone explain why in 6 months by reading your message and commit diff?&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;If commit is not interesting to the story, feel free to squash it&lt;/p&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;For instance: &quot;fix typo in variable name&quot;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Be careful about squashing and rewriting commit history AFTER code review starts ➡ may be hard for reviewer to follow&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Feel free to rewrite the way you tell the story &lt;strong&gt;before&lt;/strong&gt; you open the code review&lt;/p&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Don&amp;#8217;t worry too much about it during development on your machine&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;2-review-your-own-code&quot;&gt;2. Review your own code&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;You have the most context on the change&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Be critical:&lt;/p&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Is this part really needed?&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;What would you improve (even if not right now)?&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Are there unrelated changes?&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Are there accidental changes?&lt;/p&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;(Hello temporary files, whitespace and random IDE changes)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;.gitignore&lt;/code&gt; (which can be global for a number of repos!) is a great help here&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Great way to avoid minor comments and to avoid discussion getting too lost in them&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;3-have-a-computer-review-your-code&quot;&gt;3. Have a computer review your code&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;All tests green&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Coverage&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Linting&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Other tools?&lt;/p&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Mutation testing?&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&amp;#8230;&amp;#8203; what else?&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;But! Be careful about impact during development. These tools should not impede debugging/experimentation and only need to be clean/all green &lt;em&gt;before&lt;/em&gt; the review is requested&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;4-be-mindful-of-the-diff-and-diff-noise&quot;&gt;4. Be mindful of the diff and diff noise&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Be careful about renaming/moving lots of things, and then fixing one or two lines in the process:&lt;/p&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Consider renaming first, and then fixing (remember: tell the story)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Consider making separate code reviews&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Consider how easy is it to review a 2k line code review with renames + some sprinkled changes VS&amp;#8230;&amp;#8203;&lt;/p&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Code review #1: 2k lines changed, only renames/moves made with IDE or search and replace; no other changes&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Code review #2: 10 lines changed, &quot;fixed foo&quot;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;But! Don&amp;#8217;t be afraid of constantly improving codebase&lt;/p&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Be careful of &quot;let&amp;#8217;s not touch this to avoid diff noise&quot;. Do touch it! Just submit it on a separate code review or commit! 😄&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;5-be-mindful-of-the-reviewers-timeeffort&quot;&gt;5. Be mindful of the reviewer&amp;#8217;s time/effort&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Avoid skipping steps that you could have done (such as re-running tests) and relying on the reviewer to pick it up&lt;/p&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Unless agreed in advance: Team may decide to help unburden the submitter by being more active and involved in the review (may even pick it up and carry on in her stead)&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;6-can-you-feature-flag-it&quot;&gt;6. Can you feature flag it?&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Working on your own branch for a long time is a pain: there&amp;#8217;s going to be conflicts, painful rebase operations, concerns about merge/deployment timing, etc&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;So, can you &lt;a href=&quot;https://martinfowler.com/articles/feature-toggles.html&quot;&gt;feature flag&lt;/a&gt; it?&lt;/p&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Having new code disabled allows you to break something down into small incremental steps without impacting code stability&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Smaller reviews, merge often&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Only enable when ready and tested&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;It&amp;#8217;s ok to develop in a branch, &lt;strong&gt;if&lt;/strong&gt; they are short-lived&lt;/p&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Definition of short-lived left to the reader and team ;)&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Be careful about leaving behind old code after enabling feature flag&lt;/p&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Feature flags should be short lived and have clear objectives/targets for when they should be removed. &lt;strong&gt;Otherwise they are probably options&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Consider opening a pull request that removes the feature flag that will stay open and only rebased/merged down the line&amp;#8201;&amp;#8212;&amp;#8201;it&amp;#8217;s a great exercise and often reveals hidden dependencies on the old code&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;7-be-comfortable-enough-to-press-the-merge-button-immediately&quot;&gt;7. Be comfortable enough to press the merge button immediately&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;If not, say it. Call it RFC/WIP. Tell people what&amp;#8217;s missing, and what you want feedback for&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Otherwise people will (and should) assume you&amp;#8217;re happy with the current state of the work, and that it does what you set out to do&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;8-remember-that-a-code-review-is-not-something-you-do-after-you-finish-a-task&quot;&gt;8. Remember that a code review is not something you do after you finish a task&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;It ➡ &lt;strong&gt;is&lt;/strong&gt; ⬅ part of the task.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;part-ii-during-a-review&quot;&gt;Part II: During a review&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;9-continue-telling-a-story&quot;&gt;9. Continue telling a story&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;New commits should still tell a story&lt;/p&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Avoid big &quot;fix issues pointed out during review&quot; commits&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Although a small &quot;fix typos/improve naming&quot; is ok too&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;10-lengthy-reviews-with-lots-of-churn-upstream-issue&quot;&gt;10. Lengthy reviews with lots of churn: upstream issue?&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Code review is a &lt;strong&gt;great&lt;/strong&gt; safety net. Sometimes it catches bigger unexpected oversights from previous steps&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;If code review is taking long and a lot of changes are being discussed:&lt;/p&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Maybe the design should have been fleshed out better before development?&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Maybe some mentoring / pairing was needed?&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;It&amp;#8217;s ok for this to happen&lt;/strong&gt;. Quite insightful to look at why and try to improve for next time&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;11-clarify-if-feedback-is-blocking-or-not&quot;&gt;11. Clarify if feedback is blocking or not&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;This is both on the reviewer and on the submitter:&lt;/p&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Is proposed change a must-have?&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Can some addition be pushed to a separate code review?&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Is it just a suggestion?&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;12-its-ok-to-go-back&quot;&gt;12. It&amp;#8217;s ok to go back!&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Feel free to close/split/cancel your code review, if you believe it will have a positive result, such as speeding up the review process&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;13-answer-reviewers-questions-with-code&quot;&gt;13. Answer reviewer&amp;#8217;s questions with code&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;From the &lt;a href=&quot;https://testing.googleblog.com/2017/06/code-health-too-many-comments-on-your.html&quot;&gt;Google Testing Blog&lt;/a&gt;: &quot;Don&amp;#8217;t just reply --- make the code easier to understand or add a comment. Someone else is going to have the same question later on.&quot;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;14-can-a-reviewers-comment-apply-elsewhere-in-this-code-review&quot;&gt;14. Can a reviewer&amp;#8217;s comment apply elsewhere in this code review?&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;A useful comment/insight quite often may apply to multiple places in the same code review&lt;/p&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Do a quick pass over your diff and check if you fixed all similar instances&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;part-iii-during-a-reviewfor-reviewers&quot;&gt;Part III: During a review&amp;#8201;&amp;#8212;&amp;#8201;for reviewers&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;15-build-it-in-your-head&quot;&gt;15: Build it in your head&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Go beyond &quot;looks ok&quot;!&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;16-imagine-how-youd-make-this-change&quot;&gt;16: Imagine how you&amp;#8217;d make this change&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Be careful not to get too attached to your opinion though. But do compare it with solution you see&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;17-prioritize-code-reviews&quot;&gt;17. Prioritize code reviews&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Try to review ASAP&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Try to reply to feedback ASAP&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Timebox if needed&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;part-iv-closing-the-review&quot;&gt;Part IV: Closing the review&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;18-trust-your-team&quot;&gt;18. Trust your team&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Place trust on your team-mates! If remaining changes are small enough, it&amp;#8217;s ok to pre-approve the code review and rely on the submitter to push through the final version&lt;/p&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Instead of requiring a new re-review just for small things&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;If the submitter decides to do bigger changes, it falls on her the responsibility to call them out and ask for a re-review&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;19-shared-responsibility-for&quot;&gt;19. Shared responsibility for 👍&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Be comfortable about giving your &quot;LGTM 👍&quot;, pressing merge, and then going home while you&amp;#8217;re on call&lt;/p&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;It&amp;#8217;s &lt;strong&gt;everyone&amp;#8217;s&lt;/strong&gt; responsibility to make sure the change is in good shape&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;But&amp;#8230;&amp;#8203; Do balance this out with getting shit done: It&amp;#8217;s ok to 👍 even when there are concerns on something WIP as long as this is clearly identified, communicated, and of course there is no negative impact on the users of the service/codebase&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;20-remember-that-its-not-done-until-it-ships&quot;&gt;20. Remember that &quot;it&amp;#8217;s not done until it ships&quot;&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&amp;#8201;&amp;#8212;&amp;#8201;Steve Jobs&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;21-guidelines-not-rules&quot;&gt;21. Guidelines, not rules&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;The above ideas are guidelines that support&lt;/p&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Communication&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Learning&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Collaboration&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Speed&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;etc&amp;#8230;&amp;#8203;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The end goal is delivering a better product through engineering excellence&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;But do skip/ignore/replace any ideas that are not having a positive impact towards our team&amp;#8217;s goals&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;22-team-decides-best-practices&quot;&gt;22. Team decides best practices&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;It&amp;#8217;s up to all members of the team to decide what to allow or not, decide what we want to enforce a set of rules (and which rules) or not, etc&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;</description>
        <pubDate>Sun, 08 Apr 2018 00:00:00 +0100</pubDate>
        <link>https://ivoanjo.me/blog/2018/04/08/my-thoughts-on-and-how-i-approach-code-reviews/</link>
        <guid isPermaLink="true">https://ivoanjo.me/blog/2018/04/08/my-thoughts-on-and-how-i-approach-code-reviews/</guid>
        <category>blog</category>
      </item>
      <item>
        <title>Is this ok…​? Or, spotting unsafe concurrent Ruby patterns</title>
        <description>&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;The past weekend I had the enormous pleasure to speak at the Ruby on Ice 2018 conference in Tegernsee, Germany.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;imageblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;img src=&quot;/img/tegernsee.jpg&quot; alt=&quot;tegernsee&quot;&gt;
&lt;/div&gt;
&lt;div class=&quot;title&quot;&gt;Figure 1. All Ruby conferences should have a view like this 😁&lt;/div&gt;
&lt;/div&gt;
&lt;br&gt;&lt;br&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;I decided to give the talk I wish I had seen about four years ago before I joined Talkdesk, on a number of gotchas and common mistakes one can do when working with Ruby and concurrency.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&lt;strong&gt;You can find the video for this talk, as well as the slides on &lt;a href=&quot;/blog/2018/10/13/spotting-unsafe-ruby-patterns/&quot;&gt;this newer post&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;quoteblock&quot;&gt;
&lt;blockquote&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Concurrency is an extremely powerful technique that should be part of every Rubyist&amp;#8217;s tool belt. But when a lot of people pick up tools such as puma, concurrent-ruby or even JRuby, they are at the same time thrilled by all the power that threads and concurrency gets them, and afraid for the day when a concurrency bug will come and chew their arm (or service) off.&lt;/p&gt;
&lt;/div&gt;
&lt;/blockquote&gt;
&lt;/div&gt;
&lt;div class=&quot;quoteblock&quot;&gt;
&lt;blockquote&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;But what do we normally mean when we talk about a concurrency bug? What do they look like? And how do you fix them, preferably without giving up performance or readability? In this talk, I will show examples of Ruby patterns and techniques that lead to unsafe behavior in the presence of multi-threading, be it in MRI or JRuby. I will then discuss how they can be spotted, why they are problematic, and propose safe alternatives.&lt;/p&gt;
&lt;/div&gt;
&lt;/blockquote&gt;
&lt;/div&gt;</description>
        <pubDate>Wed, 31 Jan 2018 00:00:00 +0000</pubDate>
        <link>https://ivoanjo.me/blog/2018/01/31/is-this-ok-or-spotting-unsafe-concurrent-ruby-patterns/</link>
        <guid isPermaLink="true">https://ivoanjo.me/blog/2018/01/31/is-this-ok-or-spotting-unsafe-concurrent-ruby-patterns/</guid>
        <category>blog</category>
      </item>
      <item>
        <title>Lightning Talk - Warm-Blanket: Goodbye crappy after-boot performance</title>
        <description>&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Back in September, at the EuRuKo 2017 Ruby conference, I decided to submit a lightning talk on the &lt;a href=&quot;/blog/2017/08/20/introducing-warm-blanket-gem/&quot;&gt;&lt;code&gt;warm-blanket&lt;/code&gt;&lt;/a&gt; gem.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;If you&amp;#8217;re curious for a bite-sized introduction and motivation on why you should care about it, you can find the presentation and slides below 😁&lt;/p&gt;
&lt;/div&gt;
&lt;iframe width=&quot;736&quot; height=&quot;420&quot; src=&quot;https://www.youtube.com/embed/NEnZViT581o?rel=0&amp;amp;start=338&quot; title=&quot;YouTube video player&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; referrerpolicy=&quot;strict-origin-when-cross-origin&quot; allowfullscreen&gt;&lt;/iframe&gt;

&lt;br&gt;&lt;br&gt;

&lt;iframe src=&quot;//slides.com/ianjo/warm-blanket-goodby-crappy-afterboot-performance/embed&quot; width=&quot;576&quot; height=&quot;420&quot; scrolling=&quot;no&quot; frameborder=&quot;0&quot; webkitallowfullscreen mozallowfullscreen allowfullscreen&gt;&lt;/iframe&gt;</description>
        <pubDate>Sun, 07 Jan 2018 00:00:00 +0000</pubDate>
        <link>https://ivoanjo.me/blog/2018/01/07/lightning-talk-warm-blanket-goodbye-crappy-afterboot-performance/</link>
        <guid isPermaLink="true">https://ivoanjo.me/blog/2018/01/07/lightning-talk-warm-blanket-goodbye-crappy-afterboot-performance/</guid>
        <category>blog</category>
      </item>
      <item>
        <title>persistent-💎: a new ruby gem for beautiful immutable data structures</title>
        <description>&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;After a few weeks of work, I&amp;#8217;ve just released version 1.0 of my new gem: &lt;a href=&quot;https://gitlab.com/ivoanjo/persistent-dmnd&quot;&gt;persistent-💎&lt;/a&gt;!&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;The objective of this gem is to make programming with immutable data structures in Ruby as joyful and frictionless as using the built-in &lt;code&gt;Array&lt;/code&gt; and &lt;code&gt;Hash&lt;/code&gt; classes. So easy, in fact, that using immutable structures becomes the norm, rather than the exception.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Ruby has no immutable data structures in the standard library, but it is flexible enough that we can add such functionality as a library, and disguise it so it almost looks like the built-in data structures.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;For instance, with persistent-💎 you can create:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Arrays: &lt;code&gt;my_array = a💎[1, 2, 3]&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Hashes: &lt;code&gt;my_hash = h💎[key1: &apos;foo&apos;, key2: &apos;bar&apos;]&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Sets: &lt;code&gt;my_set = s💎[:sephiroth, :kills, :aeris]&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Using an emoji as part of the gem&amp;#8217;s api was an interesting challenge, but with some care it&amp;#8217;s possible to support Ruby 1.9.3 to 2.5.0, and JRuby 1.7 and 9.x, although the latter have some known bugs with unicode handling.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Furthermore, this gem integrates with the &lt;a href=&quot;https://github.com/ruby-concurrency/concurrent-ruby&quot;&gt;concurrent-ruby&lt;/a&gt; and &lt;a href=&quot;https://github.com/hamstergem/hamster&quot;&gt;hamster&lt;/a&gt; gems, so you can easily convert back and forth between instances of these libraries, so you can use the best tool for the job.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;This was a very fun project, and the git history reveals that it took a bit more than I expected to get it just right.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;So&amp;#8230;&amp;#8203; go forth and use it. Feedback is very welcome!&lt;/p&gt;
&lt;/div&gt;</description>
        <pubDate>Wed, 03 Jan 2018 00:00:00 +0000</pubDate>
        <link>https://ivoanjo.me/blog/2018/01/03/persistent-for-beautiful-immutable-data-structures/</link>
        <guid isPermaLink="true">https://ivoanjo.me/blog/2018/01/03/persistent-for-beautiful-immutable-data-structures/</guid>
        <category>blog</category>
      </item>
      <item>
        <title>asciidoc: an awesome markdown alternative</title>
        <description>&lt;div id=&quot;preamble&quot;&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Yesterday while reading through the twitters, I came upon a reference to a markup format called &lt;a href=&quot;http://www.methods.co.nz/asciidoc/&quot;&gt;AsciiDoc&lt;/a&gt; which I had never heard about before.&lt;/p&gt;
&lt;/div&gt;
&lt;blockquote class=&quot;twitter-tweet&quot; data-lang=&quot;en&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;Oh wow. Just read up on asciidoc and asciidoctor and woooow. This just made my life. Mind. Blown.&lt;/p&gt;&amp;mdash; Ivo Anjo (@KnuX) &lt;a href=&quot;https://twitter.com/KnuX/status/921646545644216320?ref_src=twsrc%5Etfw&quot;&gt;October 21, 2017&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src=&quot;//platform.twitter.com/widgets.js&quot; charset=&quot;utf-8&quot;&gt;&lt;/script&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;I started reading about both AsciiDoc and the &lt;a href=&quot;http://asciidoctor.org/&quot;&gt;AsciiDoctor&lt;/a&gt; tool and they completely blew my mind, so I immediately decided that I had to write a blog post about it --- Using AsciiDoc, of course!&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;awesome-asciidocasciidoctor-features&quot;&gt;Awesome AsciiDoc+AsciiDoctor features&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;So if you already are comfortable with Markdown, why should you care?&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Here are some of the features that really impressed me:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;http://asciidoctor.org/docs/user-manual/#user-toc&quot;&gt;Generating a table of contents&lt;/a&gt;: A table of contents can be automatically generated based on your document structure. You can control where a ToC is placed, how many subsection levels to include, and even its title.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;http://asciidoctor.org/docs/asciidoc-syntax-quick-reference/#include-files&quot;&gt;Including files in a document&lt;/a&gt;. You can use this to:&lt;/p&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;http://asciidoctor.org/docs/asciidoc-syntax-quick-reference/#include-files&quot;&gt;Split up your document into multiple files and then include them all to create a single final output&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;http://www.methods.co.nz/asciidoc/newtables.html&quot;&gt;Include data from an external csv and render it as a table&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Including verbatim source code from source files. &lt;a href=&quot;https://mrhaki.blogspot.co.uk/2014/04/awesome-asciidoc-include-partial-parts.html&quot;&gt;You can even slice the file by tags&lt;/a&gt; or &lt;a href=&quot;https://mrhaki.blogspot.co.uk/2014/08/awesome-asciidoc-include-only-certain.html&quot;&gt;by lines&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;For instance, here&amp;#8217;s the source code for this itemized list thus far, directly embedded from the post source file (not copy-pasted!):&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;CodeRay highlight&quot;&gt;&lt;code data-lang=&quot;asciidoc&quot;&gt;* http://asciidoctor.org/docs/asciidoc-syntax-quick-reference/#include-files[Including files in a document]. You can use this to:

** http://asciidoctor.org/docs/asciidoc-syntax-quick-reference/#include-files[Split up your document into multiple files and then include them all to create a single final output]

** http://www.methods.co.nz/asciidoc/newtables.html[Include data from an external csv and render it as a table]

** Including verbatim source code from source files. https://mrhaki.blogspot.co.uk/2014/04/awesome-asciidoc-include-partial-parts.html[You can even slice the file by tags] or https://mrhaki.blogspot.co.uk/2014/08/awesome-asciidoc-include-only-certain.html[by lines].&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;http://www.methods.co.nz/asciidoc/chunked/ch20.html&quot;&gt;Callouts in source code&lt;/a&gt;:&lt;/p&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;CodeRay highlight&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color:#06B;font-weight:bold&quot;&gt;foo&lt;/span&gt;
  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;begin&lt;/span&gt;
    raise &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;Hello, world&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt; # &lt;b class=&quot;conum&quot;&gt;(1)&lt;/b&gt;
  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;rescue&lt;/span&gt; =&amp;gt; e
    puts &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;Rescued!&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt; # &lt;b class=&quot;conum&quot;&gt;(2)&lt;/b&gt;
  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;end&lt;/span&gt;
&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;colist arabic&quot;&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;This will raise a &lt;code&gt;StandardError&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;This will stop the exception from propagating&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;http://asciidoctor.org/docs/asciidoc-writers-guide/#admonitions&quot;&gt;Note/tip/warning/etc blocks&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;http://asciidoctor.org/docs/asciidoc-syntax-quick-reference/#attributes-and-substitutions&quot;&gt;Counters&lt;/a&gt;: Each (1) time (2) you (3) include (4) &lt;code&gt;{counter:some_name}&lt;/code&gt; a number gets printed and incremented.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;http://asciidoctor.org/docs/asciidoc-syntax-quick-reference/#section-footnotes&quot;&gt;Footnotes&lt;/a&gt; &lt;sup class=&quot;footnote&quot;&gt;[&lt;a id=&quot;_footnoteref_1&quot; class=&quot;footnote&quot; href=&quot;#_footnotedef_1&quot; title=&quot;View footnote.&quot;&gt;1&lt;/a&gt;]&lt;/sup&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;http://asciidoctor.org/docs/asciidoc-syntax-quick-reference/#formatted-text&quot;&gt;&lt;sup&gt;Super&lt;/sup&gt; and &lt;sub&gt;sub&lt;/sub&gt;script text&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;http://asciidoctor.org/docs/asciidoc-syntax-quick-reference/#more-delimited-blocks&quot;&gt;Custom substitutions!&lt;/a&gt; You can define a substitution &lt;code&gt;:version: 1.0.0&lt;/code&gt; and then use it in links &lt;code&gt;https://rubygems.org/gems/warm-blanket/versions/{version}&lt;/code&gt; and in the text &amp;#8220;&lt;em&gt;Latest stable version is {version}&lt;/em&gt;&amp;#8221; and then they&amp;#8217;ll get automatically replaced:&lt;/p&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Latest version is 1.0.0, link &lt;a href=&quot;https://rubygems.org/gems/warm-blanket/versions/1.0.0&quot; class=&quot;bare&quot;&gt;https://rubygems.org/gems/warm-blanket/versions/1.0.0&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;http://asciidoctor.org/docs/asciidoc-syntax-quick-reference/#comments&quot;&gt;You can add comments without needing to cheat by using html ;)&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;using-asciidoc&quot;&gt;Using AsciiDoc&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;AsciiDoc documents use the file extension &lt;code&gt;.adoc&lt;/code&gt;. Most text editors already ship with or have third-party plugins to perform syntax highlighting.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;But yeah, so there&amp;#8217;s lots of fancy features, but Markdown is already everywhere&amp;#8230;&amp;#8203; isn&amp;#8217;t it?&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;The best news is that AsciiDoc is the most widely-supported format you&amp;#8217;ve never heard about:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;You can use it &lt;a href=&quot;http://asciidoctor.org/news/2013/01/30/asciidoc-returns-to-github/&quot;&gt;on GitHub&lt;/a&gt; and &lt;a href=&quot;https://news.ycombinator.com/item?id=9208157&quot;&gt;on GitLab&lt;/a&gt;. Yes, really: &lt;a href=&quot;https://github.com/Talkdesk/warm-blanket/blob/master/README.adoc&quot; class=&quot;bare&quot;&gt;https://github.com/Talkdesk/warm-blanket/blob/master/README.adoc&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;You can use it &lt;a href=&quot;https://github.com/asciidoctor/jekyll-asciidoc&quot;&gt;with the jekyll&lt;/a&gt; website generator (&lt;a href=&quot;https://rubygems.org/gems/asciidoctor/reverse_dependencies&quot;&gt;and many others&lt;/a&gt;). In fact, you&amp;#8217;re looking at &lt;code&gt;jekyll-asciidoc&lt;/code&gt;&apos;s output right now!&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;You can use it &lt;a href=&quot;https://toolchain.gitbook.com/syntax/asciidoc.html&quot;&gt;together with gitbook&lt;/a&gt; to write awesome documentation&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;You can &lt;a href=&quot;http://asciidoctor.org/docs/asciidoc-writers-guide/#rendering-your-document&quot;&gt;convert it to html, docbook, and many other formats&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;You can use &lt;a href=&quot;http://asciidoctor.org/docs/asciidoc-syntax-quick-reference/#markdown-compatibility&quot;&gt;asciidoctor&amp;#8217;s markdown compatibility&lt;/a&gt; to ease your transition&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;You can &lt;a href=&quot;https://stackoverflow.com/questions/7323596/is-there-any-way-to-convert-markdown-to-asciidoc-or-be-able-to-produce-the-same&quot;&gt;convert your existing Markdown content&lt;/a&gt; to AsciiDoc automatically&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;http://gist.asciidoctor.org&quot;&gt;You can edit it with live preview online&lt;/a&gt;. And it even supports &lt;strong&gt;collaborative editing&lt;/strong&gt;, woohoo!&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;go-forth-and-explore&quot;&gt;Go forth and explore!&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;I hope I was able to share some of my enthusiasm about AsciiDoc with you!&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;If you want to learn more, I suggest starting with:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;http://asciidoctor.org/docs/what-is-asciidoc/&quot; class=&quot;bare&quot;&gt;http://asciidoctor.org/docs/what-is-asciidoc/&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;http://asciidoctor.org/docs/asciidoc-writers-guide/&quot; class=&quot;bare&quot;&gt;http://asciidoctor.org/docs/asciidoc-writers-guide/&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;footnotes&quot;&gt;
&lt;hr&gt;
&lt;div class=&quot;footnote&quot; id=&quot;_footnotedef_1&quot;&gt;
&lt;a href=&quot;#_footnoteref_1&quot;&gt;1&lt;/a&gt;. This is an example footnote!
&lt;/div&gt;
&lt;/div&gt;</description>
        <pubDate>Sun, 22 Oct 2017 00:00:00 +0100</pubDate>
        <link>https://ivoanjo.me/blog/2017/10/22/asciidoc-an-awesome-markdown-alternative/</link>
        <guid isPermaLink="true">https://ivoanjo.me/blog/2017/10/22/asciidoc-an-awesome-markdown-alternative/</guid>
        <category>blog</category>
      </item>
      <item>
        <title>Why I always use attr_reader to access instance variables</title>
        <description>&lt;p&gt;Ruby’s &lt;a href=&quot;https://ruby-doc.org/core-2.4.0/Module.html#method-i-attr_reader&quot;&gt;&lt;code&gt;attr_reader&lt;/code&gt;&lt;/a&gt; method can be used to automatically generate a “getter” for a given instance variable.&lt;/p&gt;

&lt;p&gt;In simple terms, doing&lt;/p&gt;

&lt;div class=&quot;language-ruby highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;attr_reader &lt;span style=&quot;color:#A60&quot;&gt;:engine&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;is the same as writing&lt;/p&gt;

&lt;div class=&quot;language-ruby highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color:#06B;font-weight:bold&quot;&gt;engine&lt;/span&gt;
  &lt;span style=&quot;color:#33B&quot;&gt;@engine&lt;/span&gt;
&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;end&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;I’ve adopted a programming style where I always try to use &lt;a href=&quot;https://ruby-doc.org/core-2.4.0/Module.html#method-i-attr_reader&quot;&gt;&lt;code&gt;attr_reader&lt;/code&gt;&lt;/a&gt; to access instance variables (or &lt;em&gt;getters&lt;/em&gt;, if you prefer to call them that 😁).
I’ve been asked about the reasons that led me to adopt this style in several PRs, so I wanted to write a quick post motivating my choice.&lt;/p&gt;

&lt;p&gt;As a &lt;s&gt;driving&lt;/s&gt; running example, I will use the following class to represent a car:&lt;/p&gt;

&lt;div class=&quot;language-ruby highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;class&lt;/span&gt; &lt;span style=&quot;color:#B06;font-weight:bold&quot;&gt;Car&lt;/span&gt;

  attr_reader &lt;span style=&quot;color:#A60&quot;&gt;:owner&lt;/span&gt;
  attr_reader &lt;span style=&quot;color:#A60&quot;&gt;:license_plate&lt;/span&gt;

  private

  attr_reader &lt;span style=&quot;color:#A60&quot;&gt;:engine&lt;/span&gt;
  attr_reader &lt;span style=&quot;color:#A60&quot;&gt;:gearbox&lt;/span&gt;

  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color:#06B;font-weight:bold&quot;&gt;initialize&lt;/span&gt;(&lt;span style=&quot;color:#606&quot;&gt;owner&lt;/span&gt;:, &lt;span style=&quot;color:#606&quot;&gt;license_plate&lt;/span&gt;:)
    &lt;span style=&quot;color:#777&quot;&gt;# ...&lt;/span&gt;
  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;end&lt;/span&gt;

  public

  &lt;span style=&quot;color:#777&quot;&gt;# ...&lt;/span&gt;
&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;end&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;&lt;em&gt;💡 Note: An earlier version of this post put the &lt;code&gt;public&lt;/code&gt; before the &lt;code&gt;initialize&lt;/code&gt;. In practice, doing this doesn’t affect the &lt;code&gt;initialize&lt;/code&gt; (try it out for yourself!); but to make it even more clear, I’ve moved the &lt;code&gt;public&lt;/code&gt; below that definition – thanks Victor Goff for an insightful discussion on this matter.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;And here’s my reasoning:&lt;/p&gt;

&lt;h3 id=&quot;placing-all-attr_readers-at-the-top-of-the-class&quot;&gt;Placing all attr_readers at the top of the class&lt;/h3&gt;

&lt;p&gt;This serves as documentation: You can open up a class and immediately spot what its internal state is.&lt;/p&gt;

&lt;p&gt;Furthermore, if your code is well-behaved and there’s no &lt;a href=&quot;https://ruby-doc.org/core-2.1.1/Module.html#method-i-attr_writer&quot;&gt;&lt;code&gt;attr_writer&lt;/code&gt;&lt;/a&gt;s or &lt;a href=&quot;https://ruby-doc.org/core-2.1.1/Module.html#method-i-attr_accessor&quot;&gt;&lt;code&gt;attr_acessor&lt;/code&gt;&lt;/a&gt;s, you can quickly know if a class is &lt;em&gt;mutable&lt;/em&gt; (its internal state can change during its lifetime) or &lt;em&gt;immutable&lt;/em&gt; (its internal state cannot change after initialization — note that this only covers the object itself, and not the objects it references, e.g. if the variable points at an unfrozen array).&lt;/p&gt;

&lt;p&gt;By following this simple code discipline, you can get a lot of useful information at a glance.&lt;/p&gt;

&lt;h3 id=&quot;using-the-attr_readers-to-access-instance-variables-from-inside-the-class&quot;&gt;Using the attr_readers to access instance variables from inside the class&lt;/h3&gt;

&lt;p&gt;This helps avoid typing mistakes. For instance, consider we add the following method to our &lt;code&gt;Car&lt;/code&gt; class, but mistakenly add a typo while writing it (e.g. &lt;code&gt;@eNgine&lt;/code&gt; instead of &lt;code&gt;@engine&lt;/code&gt;):&lt;/p&gt;

&lt;div class=&quot;language-ruby highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color:#06B;font-weight:bold&quot;&gt;start&lt;/span&gt;
    &lt;span style=&quot;color:#33B&quot;&gt;@gearbox&lt;/span&gt;.neutral
    &lt;span style=&quot;color:#33B&quot;&gt;@eNgine&lt;/span&gt;.start
  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;end&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;What happens when we try to run our code?&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;$ ruby car.rb 
car.rb:20:in `start&apos;: undefined method `start&apos; for nil:NilClass (NoMethodError)
        from car.rb:24:in `&amp;lt;main&amp;gt;&apos;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;“What? Why is my engine &lt;code&gt;nil&lt;/code&gt;?” you may ask yourself. And off you go on a wild goose chase trying to hunt down why your engine was not correctly initialized because you haven’t noticed that there’s a typo on your &lt;code&gt;start&lt;/code&gt; method.&lt;/p&gt;

&lt;p&gt;So instead let’s not access the instance variables directly, but let’s use the methods that the &lt;a href=&quot;https://ruby-doc.org/core-2.4.0/Module.html#method-i-attr_reader&quot;&gt;&lt;code&gt;attr_reader&lt;/code&gt;&lt;/a&gt; created:&lt;/p&gt;

&lt;div class=&quot;language-ruby highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color:#06B;font-weight:bold&quot;&gt;start&lt;/span&gt;
    gearbox.neutral
    eNgine.start
  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;end&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;And what happens when we run this version?&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;$ ruby car.rb 
car.rb:20:in `start&apos;: undefined local variable or method `eNgine&apos; for #&amp;lt;Car:0x000000c9d9522d50&amp;gt; (NameError)
Did you mean?  @engine
        from car.rb:24:in `&amp;lt;main&amp;gt;&apos;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Our output is a lot clearer: there’s no &lt;code&gt;eNgine&lt;/code&gt; declared and “did you mean?” &lt;code&gt;engine&lt;/code&gt;. You immediately spot your typo and move on.&lt;/p&gt;

&lt;h3 id=&quot;the-usual-advantages-of-using-a-getter&quot;&gt;The usual advantages of using a getter&lt;/h3&gt;

&lt;p&gt;When you use a method to access your instance variable, it becomes a lot easier to later refactor it, without needing to update all the places where it is used.&lt;/p&gt;

&lt;p&gt;For instance, consider that we wanted to lazily initialize an engine whenever one is not provided when our car object is created. We can easily change our&lt;/p&gt;

&lt;div class=&quot;language-ruby highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;attr_reader &lt;span style=&quot;color:#A60&quot;&gt;:engine&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;into&lt;/p&gt;

&lt;div class=&quot;language-ruby highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color:#06B;font-weight:bold&quot;&gt;engine&lt;/span&gt;
  &lt;span style=&quot;color:#33B&quot;&gt;@engine&lt;/span&gt; ||= &lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;EngineFactory&lt;/span&gt;.create
&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;end&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Done! This saves us from hunting down usages of &lt;code&gt;@engine&lt;/code&gt; in our class and its subclasses.&lt;/p&gt;

&lt;h3 id=&quot;even-for-private-instance-variables&quot;&gt;…Even for private instance variables…&lt;/h3&gt;

&lt;p&gt;Because all of the advantages above are applicable to instance variables that are not exposed to the outside of the class, I recommend using &lt;code&gt;attr_reader&lt;/code&gt; for these variables too, even if you would not usually do so.&lt;/p&gt;
</description>
        <pubDate>Wed, 20 Sep 2017 13:46:00 +0100</pubDate>
        <link>https://ivoanjo.me/blog/2017/09/20/why-i-always-use-attr_reader-to-access-instance-variables/</link>
        <guid isPermaLink="true">https://ivoanjo.me/blog/2017/09/20/why-i-always-use-attr_reader-to-access-instance-variables/</guid>
        <category>blog</category>
      </item>
      <item>
        <title>Introducing the WarmBlanket gem</title>
        <description>&lt;p&gt;Optimizing runtimes are a very hot topic for Ruby development right now: Historically, both &lt;a href=&quot;http://jruby.org/&quot;&gt;JRuby&lt;/a&gt; and &lt;a href=&quot;https://rubinius.com/&quot;&gt;Rubinius&lt;/a&gt; dynamically optimized Ruby code as they ran it, but soon they will soon be joined by the likes of &lt;a href=&quot;https://github.com/graalvm/truffleruby&quot;&gt;TruffleRuby&lt;/a&gt;, &lt;a href=&quot;https://github.com/rubyomr-preview/rubyomr-preview&quot;&gt;ruby+omr&lt;/a&gt;, &lt;a href=&quot;https://github.com/vnmakarov/ruby/tree/rtl_mjit_branch&quot;&gt;mjit&lt;/a&gt;, &lt;a href=&quot;https://github.com/k0kubun/llrb&quot;&gt;llrb&lt;/a&gt; and &lt;a href=&quot;https://github.com/topazproject/topaz&quot;&gt;topaz&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Furthermore, it’s common for Ruby web services to lazily load classes and open connections to dependent systems. This allows for faster system start-up time, and reduces memory usage: unused code is not loaded, and unused connections are not started nor kept active.&lt;/p&gt;

&lt;p&gt;Dynamic optimization and lazy start-up techniques when starting a web service have a big downside: When a Ruby web service boots up, &lt;strong&gt;it will take some time for the service to reach peak performance&lt;/strong&gt;. In my own experience, MRI — the most commonly-used Ruby runtime — takes several seconds to hit peak performance, but more aggressively optimizing runtimes, such as JRuby, take several minutes to reach their highest-performing state.&lt;/p&gt;

&lt;p&gt;This period of reduced performance, if ignored by service operators, is normally observed by service clients as a spike in request latency, with timeouts sometimes kicking in. (Not very unexpectedly, &lt;a href=&quot;https://landing.google.com/sre/book/chapters/load-balancing-datacenter.html#unpredictable-performance-factors-JMs7i7trCj&quot;&gt;this&lt;/a&gt; &lt;a href=&quot;http://www.brendangregg.com/blog/2016-09-28/java-warmup.html&quot;&gt;issue&lt;/a&gt; &lt;a href=&quot;https://devcenter.heroku.com/articles/warming-up-a-java-process&quot;&gt;is not specific&lt;/a&gt; &lt;a href=&quot;https://github.com/Talkdesk/warm-blanket#why-do-we-need-to-warm-up-web-services&quot;&gt;to Ruby&lt;/a&gt;.)&lt;/p&gt;

&lt;p&gt;While working at &lt;a href=&quot;https://github.com/Talkdesk&quot;&gt;Talkdesk&lt;/a&gt; on supporting new web services written using JRuby, &lt;strong&gt;I decided to tackle this problem by creating a new gem: &lt;a href=&quot;https://github.com/Talkdesk/warm-blanket&quot;&gt;WarmBlanket&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;WarmBlanket is targeted at deployment environments where services can be given a warm up period before they start to receive client requests, such as Heroku’s &lt;a href=&quot;https://devcenter.heroku.com/articles/preboot&quot;&gt;preboot&lt;/a&gt; or Kubernetes’ &lt;a href=&quot;https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/#define-readiness-probes&quot;&gt;readiness probes&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;During the warm up period, WarmBlanket connects as an http client to the web service and repeatedly performs a number of pre-configured common requests. By exercising most endpoints, all needed code is loaded, database connections are started, and dynamically optimizing runtimes can optimize the code paths being exercised.&lt;/p&gt;

&lt;p&gt;As a result, when a service starts to receive production traffic, it is at or near its peak performance, and thus ready to provide an awesome service to its clients.&lt;/p&gt;

&lt;p&gt;If this sounds good, you can find WarmBlanket on &lt;a href=&quot;https://rubygems.org/gems/warm-blanket&quot;&gt;rubygems&lt;/a&gt; and on &lt;a href=&quot;https://github.com/Talkdesk/warm-blanket&quot;&gt;github&lt;/a&gt;. All feedback, issues, and contributions are welcome!&lt;/p&gt;
</description>
        <pubDate>Sun, 20 Aug 2017 10:00:57 +0100</pubDate>
        <link>https://ivoanjo.me/blog/2017/08/20/introducing-warm-blanket-gem/</link>
        <guid isPermaLink="true">https://ivoanjo.me/blog/2017/08/20/introducing-warm-blanket-gem/</guid>
        <category>blog</category>
      </item>
      <item>
        <title>Ninjas’ guide to getting started with VisualVM</title>
        <description>&lt;p&gt;&lt;a href=&quot;/img/visualvm.png&quot;&gt;&lt;img src=&quot;/img/visualvm.png&quot; alt=&quot;VisualVM, an awesome JVM-based tool&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;VisualVM is a free Java/JVM tool that ships with most Oracle JDK/OpenJDK installs (if you’ve used Erlang’s &lt;a href=&quot;http://erlang.org/doc/apps/observer/observer_ug.html&quot;&gt;observer&lt;/a&gt; previously, it’s a similar tool). It can be used to both profile and debug applications running on the JVM—including Java, JRuby, and many others.&lt;/p&gt;

&lt;p&gt;I’ve mentioned it &lt;a href=&quot;/blog/2016/07/16/down-the-jruby-rabbit-hole/&quot;&gt;several&lt;/a&gt; &lt;a href=&quot;/blog/2016/07/17/another-round-of-jruby-goodness/&quot;&gt;times&lt;/a&gt; before on this blog as part of my JRuby voyages, as it’s my go-to tool to start investigating any kind of issue in a JVM application.&lt;/p&gt;

&lt;p&gt;Recently, I’ve written a thorough guide on VisualVM’s features (including a special section with cool JRuby goodies) for Talkdesk’s Engineering Blog. You can check it out embedded below or at &lt;a href=&quot;https://engineering.talkdesk.com/ninjas-guide-to-getting-started-with-visualvm-f8bff061f7e7&quot;&gt;https://engineering.talkdesk.com/ninjas-guide-to-getting-started-with-visualvm-f8bff061f7e7&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;what-is-visualvm&quot;&gt;What is VisualVM?&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;/img/ninjas-visualvm/guide1.png&quot;&gt;&lt;img src=&quot;/img/ninjas-visualvm/guide1.png&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://visualvm.github.io/&quot;&gt;VisualVM&lt;/a&gt; is a free Java/JVM tool that ships with most Oracle JDK/OpenJDK installs (if you’ve used Erlang’s &lt;a href=&quot;http://erlang.org/doc/apps/observer/observer_ug.html&quot;&gt;observer&lt;/a&gt; previously, it’s a similar tool).&lt;/p&gt;

&lt;p&gt;This tool can be used:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;in development:&lt;/strong&gt; connecting to applications running on the local machine and on docker&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;in test environments&lt;/strong&gt;: connecting to live Heroku dynos or AWS systems&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;in production environments:&lt;/strong&gt; connecting to live Heroku dynos or AWS systems (with &lt;strong&gt;important caveats&lt;/strong&gt;, discussed below in the &lt;em&gt;Debugging with VisualVM&lt;/em&gt; section)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;VisualVM can be used &lt;strong&gt;with all JVM languages (Java, JRuby, Kotlin, Scala, …)&lt;/strong&gt;. It works at the VM layer which means that high-level concepts from other JVM languages are missing, and instead you’ll see their “under the hood” representation. &lt;em&gt;But don’t let this scare you off&lt;/em&gt;, you can still get plenty of useful information, even with this limitation.&lt;/p&gt;

&lt;p&gt;This guide is divided into several parts:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Getting VisualVM&lt;/strong&gt;: A simple getting started guide.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Connecting VisualVM to a running application&lt;/strong&gt;: How to get VisualVM talking to your application, locally or otherwise.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Debugging with VisualVM&lt;/strong&gt;: What you can do with VisualVM.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Recommended plugins&lt;/strong&gt;: Turbocharge your VisualVM install.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;JRuby goodies&lt;/strong&gt;: JRuby-specific tools and techniques.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Further exploration&lt;/strong&gt;: Other suggested awesome JVM tools.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;getting-visualvm&quot;&gt;Getting VisualVM&lt;/h2&gt;

&lt;p&gt;If you have the &lt;code&gt;javac&lt;/code&gt; command, you should also have &lt;code&gt;visualvm&lt;/code&gt; or &lt;code&gt;jvisualvm&lt;/code&gt;. As of this writing, the latest version is 1.3.9, which I recommend you use.&lt;/p&gt;

&lt;p&gt;If you don’t have the latest version (or any version at all), go to &lt;a href=&quot;https://visualvm.github.io/download.html&quot;&gt;VisualVM’s website&lt;/a&gt; and make some magic happen.&lt;/p&gt;

&lt;h2 id=&quot;connecting-visualvm-to-a-running-application&quot;&gt;Connecting VisualVM to a running application&lt;/h2&gt;

&lt;h3 id=&quot;local-application-running-natively&quot;&gt;Local application running natively&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;/img/ninjas-visualvm/guide2.gif&quot;&gt;&lt;img src=&quot;/img/ninjas-visualvm/guide2.gif&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is a simple one step process.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1&lt;/strong&gt;: Go into the applications tab. There you will find your application.&lt;/p&gt;

&lt;h3 id=&quot;local-application-running-inside-docker&quot;&gt;Local application running inside Docker&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;/img/ninjas-visualvm/guide3.gif&quot;&gt;&lt;img src=&quot;/img/ninjas-visualvm/guide3.gif&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You’ll need to enable the VM remote management extensions by defining an environment variable and expose the management port outside of docker.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1:&lt;/strong&gt; Go to your docker-compose environment and add the &lt;code&gt;JAVA_TOOL_OPTIONS&lt;/code&gt; environment variable with the following configuration:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;JAVA_TOOL_OPTIONS=-Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=9010 -Dcom.sun.management.jmxremote.local.only=false -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Djava.rmi.server.hostname=localhost -Dcom.sun.management.jmxremote.rmi.port=9010
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Step 2:&lt;/strong&gt; Then, when running your docker container, expose port &lt;code&gt;9010&lt;/code&gt; to your local machine:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;$ docker-compose run -p 9010:9010 &amp;lt;your service&amp;gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Step 3:&lt;/strong&gt; Now you’re all set to connect using VisualVM. Go to &lt;strong&gt;File &amp;gt; Add JMX Connection…&lt;/strong&gt; Use &lt;code&gt;localhost:9010&lt;/code&gt; as a target. Don’t touch any of the other options. Then, press &lt;strong&gt;OK&lt;/strong&gt;. A new “&lt;strong&gt;localhost:9010&lt;/strong&gt;” entry should appear on the applications list. Double-click it to get the magic to happen.&lt;/p&gt;

&lt;p&gt;(See also &lt;a href=&quot;https://medium.com/@logbon72/this-was-quite-helpful-34b56ab7b175&quot;&gt;https://medium.com/@logbon72/this-was-quite-helpful-34b56ab7b175&lt;/a&gt; that lists a few extra tweaks to get docker to work)&lt;/p&gt;

&lt;h3 id=&quot;remote-application-running-on-heroku&quot;&gt;Remote application running on Heroku&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;/img/ninjas-visualvm/guide4.gif&quot;&gt;&lt;img src=&quot;/img/ninjas-visualvm/guide4.gif&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1:&lt;/strong&gt; Start by installing the &lt;code&gt;heroku-cli-java&lt;/code&gt; plugin for the Heroku cli. This only needs to be done once because it adds to the Heroku cli, not to any specific app.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;$ heroku plugins:install heroku-cli-java
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;&lt;a href=&quot;/img/ninjas-visualvm/guide5.png&quot;&gt;&lt;img src=&quot;/img/ninjas-visualvm/guide5.png&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 2:&lt;/strong&gt; You’ll also need to add the &lt;a href=&quot;https://github.com/heroku/exec-buildpack&quot;&gt;exec buildpack&lt;/a&gt; to your Heroku application. This will install some extra tooling into the deployed container image that we’ll use to access the remote dyno.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 3:&lt;/strong&gt; As Buildpack changes are only applied after re-deploying, you now need to  re-deploy your application.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 4: &lt;em&gt;AFTER RE-DEPLOYING YOUR APPLICATION&lt;/em&gt;&lt;/strong&gt;, *ahem* you can now use the following command:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;$ heroku java:visualvm --app &amp;lt;your heroku app&amp;gt; --dyno &amp;lt;your dyno&amp;gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;If it all goes well, VisualVM will pop up and start connecting. You may see a warning about the connection being insecure &lt;a href=&quot;https://devcenter.heroku.com/articles/heroku-exec#using-java-debugging-tools&quot;&gt;which you can ignore&lt;/a&gt;. The connection process may also take a while (around 10–15 seconds).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: If you do not specify a dyno, Heroku will default to &lt;strong&gt;web.1&lt;/strong&gt; which will net you a “&lt;em&gt;Could not connect to dyno!&lt;/em&gt;” error on applications without web dynos.&lt;/p&gt;

&lt;h3 id=&quot;heroku-connection-gotchas&quot;&gt;Heroku connection gotchas&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;1. VisualVM error when connecting to remote dyno&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;/img/ninjas-visualvm/guide6.png&quot;&gt;&lt;img src=&quot;/img/ninjas-visualvm/guide6.png&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;
&lt;em&gt;There goes the neighbourhood&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;If you get a “&lt;em&gt;Cannot connect to &amp;lt;foo&amp;gt; using &amp;lt;some url&amp;gt;&lt;/em&gt;” error message, manually configure your proxy settings as shown below:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;/img/ninjas-visualvm/guide7.png&quot;&gt;&lt;img src=&quot;/img/ninjas-visualvm/guide7.png&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; You’ll probably want to undo this setting next time you want to connect to a docker container or a local application.&lt;/p&gt;

&lt;h2 id=&quot;debugging-with-visualvm&quot;&gt;&lt;strong&gt;Debugging with VisualVM&lt;/strong&gt;&lt;/h2&gt;

&lt;p&gt;In this section I’ll go into some of the investigation and debugging tasks you can do with VisualVM. Note that if your VisualVM does not look like mine, you’re probably missing one or more of the plugins I have installed. See the next section for an overview of them.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Production caveats:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Be wary about using these tools and techniques in production.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Some of them can have a big impact on the performance and responsiveness of your running system, thus you may end up making an ongoing problem even worse. I will attempt to indicate where you should be extra careful when using certain mechanisms. If you’re unsure, always plan to monitor closely, and preferably pair on the work before going all rambo into production.&lt;/strong&gt;&lt;/p&gt;

&lt;h3 id=&quot;monitor-panel&quot;&gt;Monitor panel&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;/img/ninjas-visualvm/guide8.png&quot;&gt;&lt;img src=&quot;/img/ninjas-visualvm/guide8.png&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;
&lt;em&gt;This is actually not the same picture as the one in the introduction&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The Monitor panel presents at-a-glance info on the overall state of the VM:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;CPU:&lt;/strong&gt; usage as a percentage of total machine resources, e.g. a fully-loaded thread will be at 25% on a four-core machine&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Heap:&lt;/strong&gt; the main memory arena where objects and arrays are kept&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Metaspace&lt;/strong&gt;: a separate memory arena where classes and other JVM metadata are kept&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Classes&lt;/strong&gt;: number of classes loaded on VM (includes automatically-generated classes)&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Threads:&lt;/strong&gt; number of threads in the VM. Live threads are &lt;a href=&quot;https://stackoverflow.com/questions/2213340/what-is-daemon-thread-in-java&quot;&gt;daemon + non-daemon&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The “&lt;strong&gt;Perform GC&lt;/strong&gt;” button triggers a full garbage collection.&lt;/p&gt;

&lt;p&gt;The “&lt;strong&gt;Heap Dump&lt;/strong&gt;” button requests that the JVM take a heap dump.
&lt;strong&gt;BE CAREFUL: Taking a heap dump means stopping all application threads while a possibly multi-gigabyte file is written. Your Java code will be suspended until this process finishes.&lt;/strong&gt;
One caveat of this functionality is that it only works seamlessly when VisualVM is accessing an app running natively on your machine. If you’re connecting to a Docker container or Heroku dyno, you’ll be asked where to save the file remotely, and you’ll need to manually transfer the heap dump file to your local machine and open it with “&lt;strong&gt;File &amp;gt; Load…&lt;/strong&gt;”.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Update:&lt;/strong&gt; On Heroku you can use the following command to take a heap dump and automatically download it:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;$ heroku java:jmap --app &amp;lt;your heroku app&amp;gt; --dyno &amp;lt;your dyno&amp;gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;h3 id=&quot;thread-panel-and-monitoring-thread-state&quot;&gt;Thread panel and monitoring thread state&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;/img/ninjas-visualvm/guide9.gif&quot;&gt;&lt;img src=&quot;/img/ninjas-visualvm/guide9.gif&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;
&lt;em&gt;Whoa! It scales!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This panel gives a view of the state of every thread in your application. If you expect your system to be fully loaded (e.g. during load testing) and instead of seeing all or mostly running threads (green), you get parking (orange), waiting (yellow), or blocking on a monitor (red), those are strong indicators that something may be off.&lt;/p&gt;

&lt;p&gt;From this panel you can also ask for a &lt;strong&gt;Thread dump&lt;/strong&gt;: a listing of the stack traces of all running threads. Note that for non-Java JVM languages, these stack traces will probably not map 1:1 to the methods you wrote on your IDE (e.g. you’ll be looking at how that language gets translated to JVM bytecode; see below for some language-specific notes).&lt;/p&gt;

&lt;h3 id=&quot;navigating-a-heap-dump&quot;&gt;Navigating a heap dump&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;/img/ninjas-visualvm/guide10.png&quot;&gt;&lt;img src=&quot;/img/ninjas-visualvm/guide10.png&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A heap dump is a snapshot of the state of the Java object/array heap. On the &lt;strong&gt;Summary&lt;/strong&gt; pane you can see information on the dump and the stack traces at creation time. On the right you can immediately search for large objects on the heap.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;/img/ninjas-visualvm/guide11.png&quot;&gt;&lt;img src=&quot;/img/ninjas-visualvm/guide11.png&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;On the &lt;strong&gt;Classes&lt;/strong&gt; pane you can see a summary of the state of the heap, broken down by class: name, number of instances, and size occupied by all of them. You can also press the “&lt;strong&gt;Static Fields&lt;/strong&gt;” button to navigate into the contacts of the classes’ static fields.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;/img/ninjas-visualvm/guide12.png&quot;&gt;&lt;img src=&quot;/img/ninjas-visualvm/guide12.png&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When you double-click on a class, you’ll be taken to the &lt;strong&gt;Instances&lt;/strong&gt; pane, where you can drill down into each instance of that class, individually.&lt;/p&gt;

&lt;p&gt;On the left pane, you can select any one of the objects you want to browse. In this case I’ve picked a &lt;code&gt;java.lang.String&lt;/code&gt; containing my OS. On the top-right, you can see the object’s fields: the &lt;code&gt;String&lt;/code&gt; is backed by a &lt;code&gt;char[]&lt;/code&gt; containing the characters themselves.&lt;/p&gt;

&lt;p&gt;In the bottom-right pane you can see all references to the object. This is a navigable view of the references that are pointing at the object, and we can see that our example object is referenced both in the value field of a &lt;code&gt;HashMap$Node&lt;/code&gt; instance, and in the &lt;code&gt;str&lt;/code&gt; field of a &lt;code&gt;ProcessEnvironment$Value&lt;/code&gt; instance. Interestingly, this also lists references from local variables that are on the stack of currently-active threads.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;/img/ninjas-visualvm/guide13.png&quot;&gt;&lt;img src=&quot;/img/ninjas-visualvm/guide13.png&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Finally, the &lt;strong&gt;OQL Console&lt;/strong&gt;. This provides an SQL-like language for finding things on the heap — for instance, find all strings containing &lt;code&gt;foo&lt;/code&gt;. It’s very powerful, so feel free to explore it.&lt;/p&gt;

&lt;h3 id=&quot;sampler-panel-a-simple-sampling-profiler&quot;&gt;Sampler panel: A simple sampling profiler&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;/img/ninjas-visualvm/guide14.png&quot;&gt;&lt;img src=&quot;/img/ninjas-visualvm/guide14.png&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A &lt;em&gt;sampling profiler&lt;/em&gt; works by taking thread dumps of the system &lt;strong&gt;at some regular interval&lt;/strong&gt; and reporting on where it observes time being spent. This has the advantage of having a smaller performance footprint than a &lt;em&gt;tracing profiler&lt;/em&gt; (introduced below), but it is therefore less accurate.&lt;/p&gt;

&lt;p&gt;You can control the sampling frequency and how often VisualVM updates the visualization. You can either profile CPU or Memory.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key Takeaway: Don’t run a profiler in production.&lt;/strong&gt;&lt;/p&gt;

&lt;h3 id=&quot;cpu-sampling&quot;&gt;CPU Sampling&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;/img/ninjas-visualvm/guide15.gif&quot;&gt;&lt;img src=&quot;/img/ninjas-visualvm/guide15.gif&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;CPU sampling shows you where time is being spent on the application. The key is to know how to read the information:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Self time:&lt;/strong&gt; How much time the profiler observed the listed method spent executing the method’s own code (e.g. if the method calls another method, it will not include that time).
Note that packages configured as “not profiled” (as seen in the first picture of the section) are counted as “a method’s own code”. In practice, this means that if, for instance, you are doing a lot of string manipulation, time spent in JDK string code will be counted as &lt;em&gt;self time&lt;/em&gt; (because JDK classes are configured as “not profiled” by default)&lt;strong&gt;.&lt;/strong&gt;&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Self time (CPU)&lt;/strong&gt;: How much CPU time was actually spent by the method. For instance in the image above, we can see a mostly-idle system that apparently spends a lot of time executing a small number of the methods. In reality, little CPU time is actually spent, because the code is just calling &lt;code&gt;Thread.sleep()&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Total time:&lt;/strong&gt; Sum of all time “spent” with that method active on the stack. E.g. it also includes time in methods called by that method.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Total time (CPU):&lt;/strong&gt; How much CPU time the &lt;em&gt;total time&lt;/em&gt; actually corresponded to. Like &lt;em&gt;self time (CPU)&lt;/em&gt;, a method may be active on the stack but the thread it lives on may actually be sleeping or waiting on I/O, e.g. no CPU is actually being used.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href=&quot;/img/ninjas-visualvm/guide16.gif&quot;&gt;&lt;img src=&quot;/img/ninjas-visualvm/guide16.gif&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the &lt;strong&gt;Thread CPU Time&lt;/strong&gt; sub-panel you can view how much CPU time is being spent by each thread. This allows you to inspect CPU time since the sampling started (&lt;strong&gt;Thread CPU Time [ms]&lt;/strong&gt;) and instantly (&lt;strong&gt;Thread CPU Time [ms/sec]&lt;/strong&gt;, on the far right).&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;/img/ninjas-visualvm/guide17.png&quot;&gt;&lt;img src=&quot;/img/ninjas-visualvm/guide17.png&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can also take a &lt;strong&gt;Snapshot&lt;/strong&gt; of the current data, which will open the &lt;strong&gt;Profiler Snapshot&lt;/strong&gt; tab. This allows you to navigate a call tree visualization that includes both &lt;em&gt;total time&lt;/em&gt; and &lt;em&gt;total time (CPU)&lt;/em&gt;, grouped by thread. The &lt;strong&gt;Hot Spots&lt;/strong&gt; tab below also includes a snapshot of the live table info that the sampler shows.&lt;/p&gt;

&lt;h3 id=&quot;memory-sampling&quot;&gt;Memory Sampling&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;/img/ninjas-visualvm/guide18.png&quot;&gt;&lt;img src=&quot;/img/ninjas-visualvm/guide18.png&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The memory sampler allows you to see a live view of the distribution of objects of the heap, and their footprint.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;/img/ninjas-visualvm/guide19.png&quot;&gt;&lt;img src=&quot;/img/ninjas-visualvm/guide19.png&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;Per thread allocations&lt;/strong&gt; tab further breaks down allocation information per-thread, showing total allocated bytes and allocated bytes per second. This allows you to see which threads are more active in creating new objects.&lt;/p&gt;

&lt;h3 id=&quot;profiler-panel-a-simple-tracing-profiler&quot;&gt;Profiler panel: A simple Tracing Profiler&lt;/h3&gt;

&lt;p&gt;A &lt;em&gt;tracing profiler&lt;/em&gt; works by modifying loaded bytecode in the JVM, adding counters to all methods so that it can accurately measure which methods are called and how much time is spent executing them. Note that this has a huge overhead, and the resulting profile may not reflect the performance of your application at all.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key Takeaway: Don’t run a tracing profiler in any kind of non-local setup.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Other than that, the CPU part of the tracing profiler is very similar to its sampling counterpart.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note for JRuby:&lt;/strong&gt; The CPU part of the tracing profiler seems to break due to the JRuby’s use of automatically-generated bytecode; I was not able to get it to work beyond very simple examples.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;/img/ninjas-visualvm/guide20.png&quot;&gt;&lt;img src=&quot;/img/ninjas-visualvm/guide20.png&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The memory tracing profiler provides a lot more information than its sampling counterpart, such as object counts and how many GC generations they live for.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;/img/ninjas-visualvm/guide21.png&quot;&gt;&lt;img src=&quot;/img/ninjas-visualvm/guide21.png&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Furthermore, when you enable the &lt;strong&gt;Record allocations stack traces&lt;/strong&gt; option, leave the profiler running and then take a snapshot, you’ll be able to explore the stack traces that led to objects being allocated by right-clicking a class and selecting &lt;strong&gt;Show allocations stack traces&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;/img/ninjas-visualvm/guide22.gif&quot;&gt;&lt;img src=&quot;/img/ninjas-visualvm/guide22.gif&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2 id=&quot;recommended-plugins&quot;&gt;Recommended plugins&lt;/h2&gt;

&lt;p&gt;Out of the box, VisualVM already includes quite a lot of functionality, but if you go to &lt;strong&gt;Tools &amp;gt; Plugins&lt;/strong&gt; you can get even more great tools. Below is a quick overview of them.&lt;/p&gt;

&lt;h3 id=&quot;visual-gc&quot;&gt;Visual GC&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;/img/ninjas-visualvm/guide23.png&quot;&gt;&lt;img src=&quot;/img/ninjas-visualvm/guide23.png&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Includes detailed information on GC status, timings, and usage of various memory regions.&lt;/p&gt;

&lt;h3 id=&quot;memory-pools&quot;&gt;Memory Pools&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;/img/ninjas-visualvm/guide24.png&quot;&gt;&lt;img src=&quot;/img/ninjas-visualvm/guide24.png&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Detailed metrics of all JVM memory regions, including things such as the code cache.&lt;/p&gt;

&lt;h3 id=&quot;threads-inspector&quot;&gt;Threads Inspector&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;/img/ninjas-visualvm/guide25.png&quot;&gt;&lt;img src=&quot;/img/ninjas-visualvm/guide25.png&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Adds an extra panel to the Threads tab where you can see the stack traces of the chosen threads.&lt;/p&gt;

&lt;h3 id=&quot;visualvm-mbeans&quot;&gt;VisualVM-MBeans&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;/img/ninjas-visualvm/guide26.png&quot;&gt;&lt;img src=&quot;/img/ninjas-visualvm/guide26.png&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Adds an extra tab that allows browsing and interacting with management beans. Management beans are a mechanism exposed by JVM and application components where they can expose their own metrics, configurations, and even allow live modification of some settings.&lt;/p&gt;

&lt;h3 id=&quot;visualvm-buffermonitor&quot;&gt;VisualVM-BufferMonitor&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;/img/ninjas-visualvm/guide27.png&quot;&gt;&lt;img src=&quot;/img/ninjas-visualvm/guide27.png&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Adds a tab to monitor the JVM’s buffer pools. Note that like other pools discussed above, these are separate from the normal object heap.&lt;/p&gt;

&lt;h3 id=&quot;visualvm-jvmcapabilities&quot;&gt;VisualVM-JvmCapabilities&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;/img/ninjas-visualvm/guide28.png&quot;&gt;&lt;img src=&quot;/img/ninjas-visualvm/guide28.png&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Adds a small panel listing available metrics and monitoring capabilities for the JVM being accessed.&lt;/p&gt;

&lt;h3 id=&quot;oql-syntax-support&quot;&gt;OQL Syntax Support&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;/img/ninjas-visualvm/guide29.png&quot;&gt;&lt;img src=&quot;/img/ninjas-visualvm/guide29.png&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Adds syntax highlighting, indentation help and autocomplete to the OQL language used to perform queries on heap dumps.&lt;/p&gt;

&lt;h3 id=&quot;tracer--probes&quot;&gt;Tracer-* Probes&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;/img/ninjas-visualvm/guide30.png&quot;&gt;&lt;img src=&quot;/img/ninjas-visualvm/guide30.png&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Enables the &lt;strong&gt;Tracer&lt;/strong&gt; tab, adding other metrics that can be monitored and graphed.&lt;/p&gt;

&lt;h2 id=&quot;jruby-goodies&quot;&gt;JRuby goodies&lt;/h2&gt;

&lt;h3 id=&quot;the-jruby-management-bean&quot;&gt;The JRuby Management Bean&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;/img/ninjas-visualvm/guide31.png&quot;&gt;&lt;img src=&quot;/img/ninjas-visualvm/guide31.png&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When using the VisualVM-MBeans plugin you can also enable the JRuby management bean by adding the &lt;code&gt;-Xmanagement.enabled=true&lt;/code&gt; option to your &lt;code&gt;JRUBY_OPTS&lt;/code&gt; environment variable or to the JRuby command line directly.&lt;/p&gt;

&lt;p&gt;This management bean exports a number of very useful operations under the &lt;strong&gt;org.jruby &amp;gt; Runtime &amp;gt; … &amp;gt; Runtime&lt;/strong&gt; item:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;/img/ninjas-visualvm/guide32.png&quot;&gt;&lt;img src=&quot;/img/ninjas-visualvm/guide32.png&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can get a Ruby-level thread dump using the &lt;strong&gt;threadDump&lt;/strong&gt; operation. This displays a stack trace as what you’d expect to see on MRI, instead of the raw Java one you can get with the &lt;strong&gt;Thread dump&lt;/strong&gt; option in the Threads tab.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;/img/ninjas-visualvm/guide33.png&quot;&gt;&lt;img src=&quot;/img/ninjas-visualvm/guide33.png&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can also (and obviously be very careful about what you do here) send Ruby code to be &lt;code&gt;eval()&lt;/code&gt;’d by JRuby using the &lt;strong&gt;executeRuby&lt;/strong&gt; operation.
You may even want to do something like &lt;code&gt;require &quot;pry&quot;; Pry.start&lt;/code&gt;. Use your imagination 😀.&lt;/p&gt;

&lt;h3 id=&quot;reading-raw-jruby-stack-traces&quot;&gt;Reading raw JRuby stack traces&lt;/h3&gt;

&lt;p&gt;Similarly to how a lot of JVMs work internally, JRuby starts off interpreting your Ruby code, and as it warms up and detects hot spots it JITs your Ruby code into automatically-generated Java classes, which function similarly to callables, and contain your Ruby methods (or parts of them). All of this happens behind the scenes, but when you ask for a Java-level thread dump, you’ll see this process in action.&lt;/p&gt;

&lt;p&gt;This means that by default in your stack trace you’ll probably find a mix of JRuby interpreter methods and the JRuby JIT classes, which looks somewhat like this:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;/img/ninjas-visualvm/guide34.png&quot;&gt;&lt;img src=&quot;/img/ninjas-visualvm/guide34.png&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;
&lt;em&gt;Pardon for the raster nature of the example&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;After the JIT callable is generated, the class/method name is rather ugly, but it accurately tells you what code is running, and where it came from.&lt;/p&gt;

&lt;p&gt;For debugging reasons you may want to force JRuby to compile every Ruby method into one of these callables, rather than doing this only for hot methods. You can do so by adding the &lt;code&gt;-Xcompile.mode=FORCE&lt;/code&gt; option to your &lt;code&gt;JRUBY_OPTS&lt;/code&gt; environment variable or to the JRuby command line directly. This has the advantage of allowing you to see every single Ruby method represented on the Java stack — instead of seeing some of the methods only as JRuby interpreter method calls — but has a memory and performance penalty.&lt;/p&gt;

&lt;h3 id=&quot;analyzing-jruby-heap-dumps&quot;&gt;Analyzing JRuby heap dumps&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;/img/ninjas-visualvm/guide35.png&quot;&gt;&lt;img src=&quot;/img/ninjas-visualvm/guide35.png&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;
&lt;em&gt;RubyObjects all the way down&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;By default, all Ruby objects are represented in the Java heap as instances of the class &lt;code&gt;org.jruby.RubyObject&lt;/code&gt;. This means that if you’re after a Ruby object memory leak, this will not help you. You could use OQL to try to identify classes and whatnot, but there’s actually a simpler way:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;/img/ninjas-visualvm/guide36.png&quot;&gt;&lt;img src=&quot;/img/ninjas-visualvm/guide36.png&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you add the &lt;code&gt;-Xreify.classes=true&lt;/code&gt; option to your &lt;code&gt;JRUBY_OPTS&lt;/code&gt; environment variable or to the JRuby command line directly, JRuby will generate JVM classes inside the &lt;code&gt;rubyobj&lt;/code&gt; package corresponding to each Ruby class (with matching Ruby namespace too). Unfortunately, this feature has some &lt;a href=&quot;https://github.com/jruby/jruby/issues/4643&quot;&gt;known bugs&lt;/a&gt;; a workaround is included in the issue report, but you’ll need to patch your JRuby instance, which is a bit more involved.&lt;/p&gt;

&lt;h2 id=&quot;further-exploration&quot;&gt;Further exploration&lt;/h2&gt;

&lt;p&gt;Here are some commercial and free tools you may want to take a look at, if you’re interested in VisualVM:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.ej-technologies.com/products/jprofiler/overview.html&quot;&gt;JProfiler Java Profiler&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.yourkit.com/&quot;&gt;YourKit Java Profiler&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.oracle.com/technetwork/java/javaseproducts/mission-control/java-mission-control-1998576.html&quot;&gt;Java Mission Control&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://icedtea.classpath.org/thermostat/&quot;&gt;Thermostat JVM Instrumentation Tool&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Sat, 12 Aug 2017 23:44:31 +0100</pubDate>
        <link>https://ivoanjo.me/blog/2017/08/12/ninjas-guide-to-visualvm/</link>
        <guid isPermaLink="true">https://ivoanjo.me/blog/2017/08/12/ninjas-guide-to-visualvm/</guid>
        <category>blog</category>
      </item>
      <item>
        <title>adopting tls</title>
        <description>&lt;p&gt;Just a quick note: If you can read this, it means this blog has finally left the internet stone age and is now being successfully served using https/tls via amazon cloudfront.&lt;/p&gt;

&lt;p&gt;Thanks to Oliver Pattison for &lt;a href=&quot;https://olivermak.es/2016/01/aws-tls-certificate-with-jekyll/&quot;&gt;his great guide&lt;/a&gt; on how to do so.&lt;/p&gt;

&lt;p&gt;Join us! We have cookies!&lt;/p&gt;

&lt;p&gt;P.s.: Next step is &lt;a href=&quot;https://medium.com/@tom.cook/edge-lambda-cloudfront-custom-headers-3d134a2c18a2&quot;&gt;getting HSTS and other recommended security headers going&lt;/a&gt;.&lt;/p&gt;
</description>
        <pubDate>Tue, 02 May 2017 23:01:59 +0100</pubDate>
        <link>https://ivoanjo.me/blog/2017/05/02/moving-to-tls/</link>
        <guid isPermaLink="true">https://ivoanjo.me/blog/2017/05/02/moving-to-tls/</guid>
        <category>blog</category>
      </item>
      <item>
        <title>rubies: a look at ruby's shiny future</title>
        <description>&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;I&amp;#8217;m a huge fan of the Ruby programming language, but in terms of implementation Ruby still lags behind other dynamic languages such as Javascript, which have powerful optimizing runtimes capable of delivering blazing performance.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Yet I think Ruby in 2017 is closer to that goal than ever: it seems like everyone in the Ruby runtime game is looking at techniques such as JIT compilation and speculative optimization.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Recently, on the 7th of March, I gave a presentation at the 4th edition of the [sardines.rb](&lt;a href=&quot;https://www.meetup.com/sardinesrb/&quot; class=&quot;bare&quot;&gt;https://www.meetup.com/sardinesrb/&lt;/a&gt;) meetup on the future of Ruby implementations in 2017 and beyond.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;You can find the video and slides of my presentation below, enjoy!&lt;/p&gt;
&lt;/div&gt;
&lt;iframe width=&quot;736&quot; height=&quot;420&quot; src=&quot;https://www.youtube.com/embed/63NzQB9jA8A&quot; title=&quot;YouTube video player&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; referrerpolicy=&quot;strict-origin-when-cross-origin&quot; allowfullscreen&gt;&lt;/iframe&gt;
&lt;iframe width=&quot;736&quot; height=&quot;420&quot; src=&quot;https://www.youtube.com/embed/UElavnvzBAg&quot; title=&quot;YouTube video player&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; referrerpolicy=&quot;strict-origin-when-cross-origin&quot; allowfullscreen&gt;&lt;/iframe&gt;
&lt;iframe src=&quot;//slides.com/ianjo/rubies-a-look-into-rubys-shiny-future/embed?style=light&quot; width=&quot;576&quot; height=&quot;420&quot; scrolling=&quot;no&quot; frameborder=&quot;0&quot; webkitallowfullscreen mozallowfullscreen allowfullscreen&gt;&lt;/iframe&gt;</description>
        <pubDate>Mon, 17 Apr 2017 00:00:00 +0100</pubDate>
        <link>https://ivoanjo.me/blog/2017/04/17/rubies-a-look-at-rubys-shiny-future/</link>
        <guid isPermaLink="true">https://ivoanjo.me/blog/2017/04/17/rubies-a-look-at-rubys-shiny-future/</guid>
        <category>blog</category>
      </item>
      <item>
        <title>quickies: heroku exec and deploying jruby</title>
        <description>&lt;h2 id=&quot;heroku-exec&quot;&gt;heroku exec!&lt;/h2&gt;

&lt;p&gt;A few months back on my &lt;a href=&quot;/blog/2016/07/17/another-round-of-jruby-goodness/&quot;&gt;&lt;em&gt;“another round of jruby goodness”&lt;/em&gt;&lt;/a&gt; post I wrote about a heroku buildpack that, combined with a reverse proxy like ngrok would allow connecting to a heroku node, and that could even be used to open up Java VisualVM and connect to it, live.&lt;/p&gt;

&lt;p&gt;This week I was pleasantly surprised to see heroku introduce this functionality out of the box with the &lt;a href=&quot;https://devcenter.heroku.com/articles/heroku-exec&quot;&gt;heroku exec&lt;/a&gt; add-on.&lt;/p&gt;

&lt;p&gt;After setting up the add-on, opening up VisualVM on a dyno for monitoring a JRuby or Java application is now as simple as&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;$ heroku java:visualvm --dyno web.1
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;A big 👍 to heroku for this feature!&lt;/p&gt;

&lt;h2 id=&quot;deploying-jruby-elsewhere&quot;&gt;deploying jruby elsewhere&lt;/h2&gt;

&lt;p&gt;If heroku isn’t your thing, my colleague Daniel Gomes has also been experimenting and writing about &lt;a href=&quot;https://dcsg.me/posts/2017-03-16-pack-er-and-terra-deploy-a-jruby-application-part-1/&quot;&gt;deploying a JRuby web application on the cloud using Packer and Terraform&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;An interesting read!&lt;/p&gt;
</description>
        <pubDate>Sun, 19 Mar 2017 10:23:00 +0000</pubDate>
        <link>https://ivoanjo.me/blog/2017/03/19/quickies-heroku-exec-and-jruby-deploy/</link>
        <guid isPermaLink="true">https://ivoanjo.me/blog/2017/03/19/quickies-heroku-exec-and-jruby-deploy/</guid>
        <category>blog</category>
      </item>
      <item>
        <title>why you should be using jruby in production</title>
        <description>&lt;p&gt;On February 23rd I gave a presentation at the &lt;a href=&quot;https://twitter.com/fullstacklx&quot;&gt;Fullstack LX&lt;/a&gt; meetup detailing why you should use JRuby and how it helped my team at Talkdesk identify complex bugs and hit our performance goals.&lt;/p&gt;

&lt;p&gt;You can find the presentation and slides below, enjoy!&lt;/p&gt;

&lt;!-- &lt;div style=&quot;position:relative;height:0;padding-bottom:56.25%&quot;&gt;&lt;iframe src=&quot;https://www.youtube.com/embed/nz2-_06OWzM?ecver=2&quot; width=&quot;640&quot; height=&quot;360&quot; frameborder=&quot;0&quot; style=&quot;position:absolute;width:100%;height:100%;left:0&quot; allowfullscreen&gt;&lt;/iframe&gt;&lt;/div&gt; --&gt;

&lt;p&gt;&lt;strong&gt;Update&lt;/strong&gt;: Video went down and I did not have a copy 😢. I’ll update this if I can restore a copy. (Or you can just invite me over to your meetup to present it live 😅)&lt;/p&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;iframe src=&quot;//slides.com/ianjo/why-you-should-be-using-jruby-in-production/embed?style=light&quot; width=&quot;576&quot; height=&quot;420&quot; scrolling=&quot;no&quot; frameborder=&quot;0&quot; webkitallowfullscreen=&quot;&quot; mozallowfullscreen=&quot;&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
</description>
        <pubDate>Thu, 16 Mar 2017 00:19:39 +0000</pubDate>
        <link>https://ivoanjo.me/blog/2017/03/16/why-you-should-be-using-jruby-in-production/</link>
        <guid isPermaLink="true">https://ivoanjo.me/blog/2017/03/16/why-you-should-be-using-jruby-in-production/</guid>
        <category>blog</category>
      </item>
      <item>
        <title>benchmarking jruby invokedynamic with a production application</title>
        <description>&lt;p&gt;As you read JRuby blog posts and other resources around the web, you may find references to JRuby’s &lt;code&gt;compile.invokedynamic&lt;/code&gt; option, that as of 9.1.7.0 continues to ship turned off by default.&lt;/p&gt;

&lt;p&gt;So, why is it off? I asked the JRuby developers and here’s what they had to say about it:&lt;/p&gt;

&lt;blockquote class=&quot;twitter-tweet&quot; data-conversation=&quot;none&quot; data-lang=&quot;en&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/KnuX&quot;&gt;@KnuX&lt;/a&gt; &lt;a href=&quot;https://twitter.com/tom_enebo&quot;&gt;@tom_enebo&lt;/a&gt; Primarily startup and warm-up time: both increase. It has improved somewhat in Java 8.&lt;/p&gt;&amp;mdash; Charles Nutter (@headius) &lt;a href=&quot;https://twitter.com/headius/status/824648190167306241&quot;&gt;January 26, 2017&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async=&quot;&quot; src=&quot;//platform.twitter.com/widgets.js&quot; charset=&quot;utf-8&quot;&gt;&lt;/script&gt;

&lt;blockquote class=&quot;twitter-tweet&quot; data-conversation=&quot;none&quot; data-lang=&quot;en&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;&lt;a href=&quot;https://twitter.com/KnuX&quot;&gt;@knux&lt;/a&gt; &lt;a href=&quot;https://twitter.com/headius&quot;&gt;@headius&lt;/a&gt; It is only for warmup reasons.   Eventual performance is generally better (or at least as good).&lt;/p&gt;&amp;mdash; tom_enebo (@tom_enebo) &lt;a href=&quot;https://twitter.com/tom_enebo/status/824632197781028864&quot;&gt;January 26, 2017&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async=&quot;&quot; src=&quot;//platform.twitter.com/widgets.js&quot; charset=&quot;utf-8&quot;&gt;&lt;/script&gt;

&lt;p&gt;…and here’s what Joe Kutner’s “&lt;a href=&quot;https://pragprog.com/book/jkdepj2/deploying-with-jruby-9k&quot;&gt;&lt;em&gt;Deploying with JRuby 9k&lt;/em&gt;&lt;/a&gt;” has to say about it:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;The &lt;code&gt;invokedynamic&lt;/code&gt; instruction promised great performance
improvements for JRuby, but it turned out to improve only a few specific
cases. […] for now, JRuby keeps this feature off by default.
You may find it worthwhile to test your application with &lt;code&gt;invokedynamic&lt;/code&gt; turned
on. It’s possible you’ll see some performance gains depending on the kind of
logic you have in your app.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So &lt;a href=&quot;https://pragtob.wordpress.com/2017/01/24/benchmarking-a-go-ai-in-ruby-cruby-vs-rubinius-vs-jruby-vs-truffle-a-year-later/&quot;&gt;in some benchmarks it seems rather relevant&lt;/a&gt;, but others suggest than on production applications it may not be the way to go. So which is it?&lt;/p&gt;

&lt;p&gt;To test it out, I decided to benchmark it with one of &lt;a href=&quot;https://github.com/talkdesk/&quot;&gt;Talkdesk&lt;/a&gt;’s internal JRuby applications. This application (dubbed &lt;em&gt;ciw&lt;/em&gt;) reads tasks from rabbitmq message queue, and communicates with another internal microservice in order to update or create new records based on the received data.&lt;/p&gt;

&lt;p&gt;After warming up the application, I loaded 6000 tasks on the rabbitmq message queue and measured how long (in seconds) the application took to go through all the tasks and empty the queue. The tests were performed on a Core i7-6500U (2.5 GHz) with 8GB of RAM running Ubuntu Linux 16.10, and the JVM used was the &lt;code&gt;Oracle Java(TM) SE Runtime Environment (build 1.8.0_121-b13) / Java HotSpot(TM) 64-Bit Server VM (build 25.121-b13, mixed mode)&lt;/code&gt;. The application was configured to use 16 threads to process tasks.&lt;/p&gt;

&lt;p&gt;I tested four different configurations: both JRuby 9.0.5.0 and 9.1.7.0 are tested on their default configurations (&lt;code&gt;compile.invokedynamic&lt;/code&gt; turned off) and with the option turned on.&lt;/p&gt;

&lt;p&gt;The results are shown below:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;/img/ciw-invokedynamic.png&quot;&gt;&lt;img src=&quot;/img/ciw-invokedynamic.png&quot; alt=&quot;Benchmarking results&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Turning &lt;code&gt;compile.invokedynamic&lt;/code&gt; on yields a &lt;strong&gt;26% speedup&lt;/strong&gt; for JRuby 9.1.7.0, shaving more than a minute from the time needed to execute the workload!&lt;/p&gt;

&lt;p&gt;Furthermore, we can also see how JRuby performance has slightly improved in a year, between JRuby 9.0.5.0 (released in January of 2016) and JRuby 9.1.7.0 (released in January of 2017).&lt;/p&gt;

&lt;p&gt;So what’s the verdict? If you’re not impacted by having longer start-up and warm-up times for your application, you &lt;strong&gt;should really be adding &lt;span style=&quot;white-space: nowrap;&quot;&gt;&lt;code&gt;-Xcompile&lt;/code&gt;&lt;/span&gt;&lt;code&gt;.invokedynamic=true&lt;/code&gt;&lt;/strong&gt; to your &lt;code&gt;JRUBY_OPTS&lt;/code&gt; or application startup scripts.&lt;/p&gt;

&lt;p&gt;As for JRuby it may be time to enable this option by default again. Or at least rename it to something more awesome-sounding, like &lt;code&gt;--production-booster&lt;/code&gt; ;)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Update, 11th May 2017&lt;/strong&gt;: Recently, while I was benchmarking a web application using JRuby, I discovered a use case where code using &lt;code&gt;compile.invokedynamic&lt;/code&gt; ran noticeably slower than when that option was disabled.&lt;/p&gt;

&lt;p&gt;Turns out it was a &lt;a href=&quot;https://github.com/jruby/jruby/issues/4596&quot;&gt;bug&lt;/a&gt;, which the JRuby developers fixed awesomely quickly, making &lt;code&gt;compile.invokedynamic&lt;/code&gt; again faster than the non-invokedynamic code path. So, if you find any such instances, do report!&lt;/p&gt;
</description>
        <pubDate>Sun, 29 Jan 2017 22:55:02 +0000</pubDate>
        <link>https://ivoanjo.me/blog/2017/01/29/benchmarking-jruby-invokedynamic/</link>
        <guid isPermaLink="true">https://ivoanjo.me/blog/2017/01/29/benchmarking-jruby-invokedynamic/</guid>
        <category>blog</category>
      </item>
      <item>
        <title>pry-debugger-jruby gem now on rubygems!</title>
        <description>&lt;p&gt;As a followup from my &lt;a href=&quot;/blog/2016/10/12/psa-you-can-now-debug-with-pry-on-jruby/&quot;&gt;psa: you can now debug with pry on jruby&lt;/a&gt; I have finally uploaded my fork of &lt;code&gt;pry-debugger&lt;/code&gt; — the &lt;a href=&quot;https://gitlab.com/ivoanjo/pry-debugger-jruby&quot;&gt;&lt;code&gt;pry-debugger-jruby&lt;/code&gt;&lt;/a&gt; gem — onto &lt;a href=&quot;https://rubygems.org/gems/pry-debugger-jruby&quot;&gt;rubygems&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;The original post has been updated, but as a reminder, using it is as simple as adding&lt;/p&gt;

&lt;div class=&quot;language-ruby highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;gem &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;pry-debugger-jruby&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;to your gemfile, and then starting pry on JRuby.&lt;/p&gt;

&lt;p&gt;Feedback and issues are very welcome! :)&lt;/p&gt;
</description>
        <pubDate>Fri, 02 Dec 2016 09:14:32 +0000</pubDate>
        <link>https://ivoanjo.me/blog/2016/12/02/pry-debugger-jruby-gem-now-on-rubygems/</link>
        <guid isPermaLink="true">https://ivoanjo.me/blog/2016/12/02/pry-debugger-jruby-gem-now-on-rubygems/</guid>
        <category>blog</category>
      </item>
      <item>
        <title>weekend hacking: enviado gem</title>
        <description>&lt;p&gt;On friday I started reading up on lyft’s recently-announced &lt;a href=&quot;https://lyft.github.io/envoy/&quot;&gt;envoy&lt;/a&gt; proxy/communication bus/general awesome piece of kit.&lt;/p&gt;

&lt;p&gt;Envoy can be used in &lt;a href=&quot;https://lyft.github.io/envoy/docs/intro/deployment_types/deployment_types.html&quot;&gt;many different ways&lt;/a&gt;:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;As a reverse proxy in front of some service&lt;/li&gt;
  &lt;li&gt;As a service-to-service communication provider (including service discovery)&lt;/li&gt;
  &lt;li&gt;As a local proxy to some remote service&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This last configuration piqued my interest, as I have been interested in solutions for doing circuit breaking ever since I learned of netflix’s &lt;a href=&quot;https://github.com/Netflix/Hystrix&quot;&gt;hysterix&lt;/a&gt; library.&lt;/p&gt;

&lt;p&gt;But retrofitting a circuit breaking onto an existing and rather diverse architecture can be a challenge. So, could envoy act as a low-level component that allowed circuit breaking, request resilience and service discovery to be slowly introduced into an existing architecture without much effort?&lt;/p&gt;

&lt;p&gt;To try it out, I built the &lt;a href=&quot;https://gitlab.com/ivoanjo/enviado&quot;&gt;&lt;code&gt;enviado&lt;/code&gt; gem&lt;/a&gt;. Enviado can be used to quickly start an envoy service along side a normal ruby application, and then make requests using envoy’s many features.&lt;/p&gt;

&lt;p&gt;I’ve also developed a small example testing some of envoy’s resilience features:&lt;/p&gt;

&lt;script src=&quot;https://gitlab.com/ivoanjo/enviado/snippets/1722315.js&quot;&gt;&lt;/script&gt;

&lt;p&gt;And the resulting sample output:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;Starting web server...
Doing 100 requests WITHOUT enviado...
Results: {500=&amp;gt;44, 200=&amp;gt;56}
Starting enviado
[2016-11-19 13:14:58.039][211][warning][main] initializing epoch 0 (hot restart version=3.2490504)
[2016-11-19 13:14:58.041][211][warning][main] all clusters initialized. starting workers
[2016-11-19 13:14:58.041][211][warning][main] starting main dispatch loop
Doing 100 requests WITH enviado...
Results: {200=&amp;gt;100}
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;This was just a quick hack, so feedback is very welcome. It currently ships only with an envoy binary for linux, but you can either run it via docker or PRs that add binaries for other platforms are very welcome!&lt;/p&gt;

&lt;p&gt;P.s.: If you want to play with envoy, but prefer elixir, the awesome &lt;a href=&quot;https://twitter.com/tjsousa&quot;&gt;Tiago Sousa&lt;/a&gt; has got you covered with &lt;a href=&quot;https://github.com/tjsousa/elixado&quot;&gt;elixado&lt;/a&gt;. Kudos to him!&lt;/p&gt;

&lt;p&gt;Addendum: If you’re interested on learning more about hysterix, I really recommend the Joker conf talk below by Tomasz Nurkiewicz:&lt;/p&gt;

&lt;iframe width=&quot;80%&quot; height=&quot;315&quot; src=&quot;https://www.youtube.com/embed/-gL-nO2cqwU?si=XCQKRocX5cX5yf1t&quot; title=&quot;YouTube video player&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; referrerpolicy=&quot;strict-origin-when-cross-origin&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
</description>
        <pubDate>Tue, 22 Nov 2016 09:03:57 +0000</pubDate>
        <link>https://ivoanjo.me/blog/2016/11/22/weekend-hacking-enviado-gem/</link>
        <guid isPermaLink="true">https://ivoanjo.me/blog/2016/11/22/weekend-hacking-enviado-gem/</guid>
        <category>blog</category>
      </item>
      <item>
        <title>jruby&apos;s Charles Nutter on the jvm as a language platform</title>
        <description>&lt;p&gt;I just finished listening to a recent episode of the &lt;a href=&quot;http://www.se-radio.net&quot;&gt;Software Engineering Radio podcast&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.se-radio.net/2016/08/se-radio-episode-266-charles-nutter-on-the-jvm-as-a-language-platform/&quot;&gt;SE-Radio Episode 266: Charles Nutter on the JVM as a Language Platform&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this podcast Charles Nutter—one of JRuby’s maintainers—discusses the relationship between non-Java languages that run on the JVM and Java/the Java platform; some history on JRuby and on the recently-released 9k version, and even touches a very interesting programming language which I’d never heard about: &lt;a href=&quot;http://www.mirah.org/&quot;&gt;Mirah&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you’re interested on the JVM platform or on JRuby, I really recommend this episode.&lt;/p&gt;

&lt;p&gt;P.s.: Hopefully next time I’ll write something about Mirah ;)&lt;/p&gt;
</description>
        <pubDate>Tue, 15 Nov 2016 19:45:00 +0000</pubDate>
        <link>https://ivoanjo.me/blog/2016/11/15/jrubys-charles-nutter-on-the-jvm-as-a-language-platform/</link>
        <guid isPermaLink="true">https://ivoanjo.me/blog/2016/11/15/jrubys-charles-nutter-on-the-jvm-as-a-language-platform/</guid>
        <category>blog</category>
      </item>
      <item>
        <title>peek and pick at mri&apos;s heap, part 2</title>
        <description>&lt;p&gt;In &lt;a href=&quot;/blog/2016/10/10/peek-and-pick-at-mris-heap/&quot;&gt;part 1&lt;/a&gt; of this overview I looked at a gui tool to monitor and analyze a live application’s memory usage. This time, let’s turn to a command-line tools that can look at things after-the-fact: the &lt;a href=&quot;https://github.com/schneems/heapy&quot;&gt;heapy gem&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://tmm1.net/ruby21-objspace/&quot;&gt;Ruby version 2.1 introduced the ability to take heap memory dumps using the &lt;code&gt;ObjectSpace&lt;/code&gt; module&lt;/a&gt;. To do so, just add:&lt;/p&gt;

&lt;div class=&quot;language-ruby highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;require &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;objspace&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;

&lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;ObjectSpace&lt;/span&gt;.trace_object_allocations_start
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;…to your application boot. Later on, when you want to take a heap memory dump, you can use:&lt;/p&gt;

&lt;div class=&quot;language-ruby highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;GC&lt;/span&gt;.start
&lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;ObjectSpace&lt;/span&gt;.dump_all(
  &lt;span style=&quot;color:#606&quot;&gt;output&lt;/span&gt;: &lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;File&lt;/span&gt;.open(&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;heap-dump.json&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;, &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;w&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;)).close
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;You will find a &lt;code&gt;heap-dump.json&lt;/code&gt; in your project folder (in production you could upload this file to S3 for later analysis). To analyze it with heapy, just do:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;$ gem install heapy
$ heapy read heap-dump.json
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;By default heapy will show you a list of all GC generations:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;Analyzing Heap
==============
Generation: nil object count: 11978
Generation:   6 object count: 74
Generation:   7 object count: 604
Generation:   8 object count: 1778
Generation:   9 object count: 1403
Generation:  10 object count: 3651
Generation:  11 object count: 3047
...
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;You can look at stats for a specific generation:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;$ heapy read heap-dump.json 6

Analyzing Heap (Generation: 6)
-------------------------------

allocated by memory (3867) (in bytes)
==============================
  600  ~/.rvm/rubies/ruby-2.3.1/lib/ruby/2.3.0/rubygems/specification.rb:2040
  456  ~/.rvm/gems/ruby-2.3.1/specifications/pry-0.10.4.gemspec:4
  320  ~/.rvm/rubies/ruby-2.3.1/lib/ruby/2.3.0/rubygems/requirement.rb:107
...

object count (74)
==============================
  11  ~/.rvm/rubies/ruby-2.3.1/lib/ruby/2.3.0/rubygems/specification.rb:2040
   8  ~/.rvm/rubies/ruby-2.3.1/lib/ruby/2.3.0/rubygems/requirement.rb:107
   5  ~/.rvm/rubies/ruby-2.3.1/lib/ruby/2.3.0/rubygems/specification.rb:1164
...

High Ref Counts
==============================

  33  ~/.rvm/gems/ruby-2.3.1/specifications/pry-0.10.4.gemspec:4
  12  ~/.rvm/rubies/ruby-2.3.1/lib/ruby/2.3.0/rubygems/specification.rb:1525
   8  ~/.rvm/rubies/ruby-2.3.1/lib/ruby/2.3.0/rubygems/requirement.rb:107
...

Duplicate strings
==============================

 4  &amp;quot;~&amp;gt;&amp;quot;
 4  ~/.rvm/rubies/ruby-2.3.1/lib/ruby/2.3.0/rubygems/requirement.rb:107

 2  &amp;quot;method_source&amp;quot;
 1  ~/.rvm/rubies/ruby-2.3.1/lib/ruby/2.3.0/rubygems/specification.rb:1164
 1  ~/.rvm/gems/ruby-2.3.1/specifications/pry-0.10.4.gemspec:29
...
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Or you can ask for stats for all generations with:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;$ heapy read heap-dump.json all
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;That’s it for heapy, short and sweet!&lt;/p&gt;
</description>
        <pubDate>Sun, 13 Nov 2016 19:47:44 +0000</pubDate>
        <link>https://ivoanjo.me/blog/2016/11/13/peek-and-pick-at-mris-heap-part2/</link>
        <guid isPermaLink="true">https://ivoanjo.me/blog/2016/11/13/peek-and-pick-at-mris-heap-part2/</guid>
        <category>blog</category>
      </item>
      <item>
        <title>finding dead ruby code with debride</title>
        <description>&lt;p&gt;My recent web adventures led me to the &lt;a href=&quot;https://github.com/seattlerb/debride&quot;&gt;&lt;code&gt;debride&lt;/code&gt;&lt;/a&gt; gem: &lt;code&gt;debride&lt;/code&gt; statically analyzes your ruby code, trying to find methods which are never referenced.&lt;/p&gt;

&lt;p&gt;As ruby is a very dynamic language, you’ll get some amount of false positives, but I was successful in finding several unused methods on several of our years-old codebases at Talkdesk.&lt;/p&gt;

&lt;p&gt;The output of running debride is a list of methods (and which class or module they belong to) that debride cannot find a reference to in the code.&lt;/p&gt;

&lt;p&gt;My workflow to remove unused code is to run debride, and for each method:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;grep the codebase to confirm that the method is not called or referenced in any way (e.g. invoked using :send or registered with a framework)&lt;/li&gt;
  &lt;li&gt;use the &lt;a href=&quot;http://www.philandstuff.com/2014/02/09/git-pickaxe.html&quot;&gt;git pickaxe&lt;/a&gt; to discover when the method was introduced and its last user removed&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;During my quick experiment of about an hour I was able to delete about a hundred LoC—and I didn’t even get through the whole list!&lt;/p&gt;

&lt;p&gt;&lt;code&gt;debride&lt;/code&gt; is another interesting tool I’ve just added to my toolkit, and I hope it fits yours too.&lt;/p&gt;
</description>
        <pubDate>Sat, 29 Oct 2016 13:25:42 +0100</pubDate>
        <link>https://ivoanjo.me/blog/2016/10/29/finding-dead-ruby-code-with-debride/</link>
        <guid isPermaLink="true">https://ivoanjo.me/blog/2016/10/29/finding-dead-ruby-code-with-debride/</guid>
        <category>blog</category>
      </item>
      <item>
        <title>psa: you can now debug with pry on jruby</title>
        <description>&lt;p&gt;I’ve been wanting to write this blog post for about a month now, but amongst the fixes for JRuby &lt;a href=&quot;http://jruby.org/2016/08/30/jruby-9-1-3-0.html&quot;&gt;version 9.1.3.0&lt;/a&gt; are a pair of fixes to backtrace line generation during debugging.&lt;/p&gt;

&lt;p&gt;Why is this relevant? Because it means that you can now debug interactively from a pry console on JRuby too!&lt;/p&gt;

&lt;p&gt;To do so, you can use either &lt;a href=&quot;https://gitlab.com/ivoanjo/pry-debugger-jruby&quot;&gt;my fork of the &lt;code&gt;pry-debugger&lt;/code&gt; gem, &lt;code&gt;pry-debugger-jruby&lt;/code&gt;&lt;/a&gt; or the slightly simpler &lt;a href=&quot;https://github.com/nixme/pry-nav&quot;&gt;&lt;code&gt;pry-nav&lt;/code&gt; gem&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;You can include either of them in your &lt;code&gt;Gemfile&lt;/code&gt; — I recommend &lt;code&gt;pry-debugger-jruby&lt;/code&gt; as it has support for breakpoints:&lt;/p&gt;

&lt;div class=&quot;language-ruby highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span style=&quot;color:#777&quot;&gt;# Gemfile&lt;/span&gt;
source &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;https://rubygems.org&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;

gem &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;pry-debugger-jruby&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Here’s a quick example which I’ll use to demonstrate its usage:&lt;/p&gt;

&lt;div class=&quot;language-ruby highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;require &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;pry&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;

&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color:#06B;font-weight:bold&quot;&gt;some_other_method&lt;/span&gt;
  puts &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;Hello,&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
  puts &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;...stranger!&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;end&lt;/span&gt;

&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color:#06B;font-weight:bold&quot;&gt;some_method&lt;/span&gt;
  binding.pry          &lt;span style=&quot;color:#777&quot;&gt;# Execution will stop here.&lt;/span&gt;
  puts &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;Hello, World!&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt; &lt;span style=&quot;color:#777&quot;&gt;# Run &apos;step&apos; or &apos;next&apos; in the&lt;/span&gt;
                       &lt;span style=&quot;color:#777&quot;&gt;# console to move here.&lt;/span&gt;

  some_other_method
&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;end&lt;/span&gt;

some_method
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;And here’s an example execution:&lt;/p&gt;

&lt;div class=&quot;language-ruby highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;$&lt;/span&gt; &lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;JRUBY_OPTS&lt;/span&gt;=--debug bundle exec ruby foo.rb

&lt;span style=&quot;color:#606&quot;&gt;From&lt;/span&gt;: foo.rb &lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;@&lt;/span&gt; line &lt;span style=&quot;color:#00D&quot;&gt;9&lt;/span&gt; &lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;Object&lt;/span&gt;&lt;span style=&quot;color:#777&quot;&gt;#some_method:&lt;/span&gt;

     &lt;span style=&quot;color:#00D&quot;&gt;8&lt;/span&gt;: &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color:#06B;font-weight:bold&quot;&gt;some_method&lt;/span&gt;
 =&amp;gt;  &lt;span style=&quot;color:#00D&quot;&gt;9&lt;/span&gt;:   binding.pry          &lt;span style=&quot;color:#777&quot;&gt;# Execution will stop here.&lt;/span&gt;
    &lt;span style=&quot;color:#00D&quot;&gt;10&lt;/span&gt;:   puts &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;Hello, World!&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt; &lt;span style=&quot;color:#777&quot;&gt;# Run &apos;step&apos; or &apos;next&apos; in the&lt;/span&gt;
    &lt;span style=&quot;color:#00D&quot;&gt;11&lt;/span&gt;:                        &lt;span style=&quot;color:#777&quot;&gt;# console to move here.&lt;/span&gt;
    &lt;span style=&quot;color:#00D&quot;&gt;12&lt;/span&gt;:
    &lt;span style=&quot;color:#00D&quot;&gt;13&lt;/span&gt;:   some_other_method
    &lt;span style=&quot;color:#00D&quot;&gt;14&lt;/span&gt;: &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;end&lt;/span&gt;

[&lt;span style=&quot;color:#00D&quot;&gt;1&lt;/span&gt;] pry(main)&amp;gt; &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;break&lt;/span&gt; foo.rb:&lt;span style=&quot;color:#00D&quot;&gt;5&lt;/span&gt;
&lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;Breakpoint&lt;/span&gt; &lt;span style=&quot;color:#00D&quot;&gt;1&lt;/span&gt;: foo.rb &lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;@&lt;/span&gt; line &lt;span style=&quot;color:#00D&quot;&gt;5&lt;/span&gt; (&lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;Enabled&lt;/span&gt;) :

    &lt;span style=&quot;color:#00D&quot;&gt;2&lt;/span&gt;:
    &lt;span style=&quot;color:#00D&quot;&gt;3&lt;/span&gt;: &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color:#06B;font-weight:bold&quot;&gt;some_other_method&lt;/span&gt;
    &lt;span style=&quot;color:#00D&quot;&gt;4&lt;/span&gt;:   puts &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;Hello,&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
 =&amp;gt; &lt;span style=&quot;color:#00D&quot;&gt;5&lt;/span&gt;:   puts &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;...stranger!&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
    &lt;span style=&quot;color:#00D&quot;&gt;6&lt;/span&gt;: &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;end&lt;/span&gt;
    &lt;span style=&quot;color:#00D&quot;&gt;7&lt;/span&gt;:
    &lt;span style=&quot;color:#00D&quot;&gt;8&lt;/span&gt;: &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color:#06B;font-weight:bold&quot;&gt;some_method&lt;/span&gt;

[&lt;span style=&quot;color:#00D&quot;&gt;2&lt;/span&gt;] pry(main)&amp;gt; &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;next&lt;/span&gt;
&lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;Hello&lt;/span&gt;, World!
&lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;Hello&lt;/span&gt;,

&lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;Breakpoint&lt;/span&gt; &lt;span style=&quot;color:#00D&quot;&gt;1&lt;/span&gt;. First hit.

From: foo.rb &lt;span style=&quot;color:#F00;background-color:#FAA&quot;&gt;@&lt;/span&gt; line &lt;span style=&quot;color:#00D&quot;&gt;5&lt;/span&gt; &lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;Object&lt;/span&gt;&lt;span style=&quot;color:#777&quot;&gt;#some_other_method:&lt;/span&gt;

    &lt;span style=&quot;color:#00D&quot;&gt;3&lt;/span&gt;: &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color:#06B;font-weight:bold&quot;&gt;some_other_method&lt;/span&gt;
    &lt;span style=&quot;color:#00D&quot;&gt;4&lt;/span&gt;:   puts &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;Hello,&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
 =&amp;gt; &lt;span style=&quot;color:#00D&quot;&gt;5&lt;/span&gt;:   puts &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;...stranger!&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
    &lt;span style=&quot;color:#00D&quot;&gt;6&lt;/span&gt;: &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;end&lt;/span&gt;

[&lt;span style=&quot;color:#00D&quot;&gt;2&lt;/span&gt;] pry(main)&amp;gt; finish
...stranger!
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Note that you have to either pass the &lt;code&gt;--debug&lt;/code&gt; flag onto the &lt;code&gt;jruby&lt;/code&gt; executable, or add it to the &lt;code&gt;JRUBY_OPTS&lt;/code&gt; environment variable to enable debugging, otherwise you’ll just get an error when you try to use the debugging facilities.&lt;/p&gt;

&lt;p&gt;Also note that I recommend you use &lt;code&gt;--debug&lt;/code&gt; only when needed, as it slows down application (and spec) execution by quite a lot!&lt;/p&gt;

&lt;p&gt;Hope this was helpful, and happy debugging!&lt;/p&gt;
</description>
        <pubDate>Wed, 12 Oct 2016 22:05:41 +0100</pubDate>
        <link>https://ivoanjo.me/blog/2016/10/12/psa-you-can-now-debug-with-pry-on-jruby/</link>
        <guid isPermaLink="true">https://ivoanjo.me/blog/2016/10/12/psa-you-can-now-debug-with-pry-on-jruby/</guid>
        <category>blog</category>
      </item>
      <item>
        <title>peek and pick at mri&apos;s heap, part 1</title>
        <description>&lt;p&gt;While I’ve been spending a lot more time on JRuby-land, over the past year a number of very interesting tools have sprung up to analyze and debug MRI memory usage which are not very known but are rather kick-ass.&lt;/p&gt;

&lt;p&gt;So without further ado, here is the first of three tools you can use to look at your MRI heap, rather than just banging your head against the table when you have to investigate memory problems: Rbkit.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;/img/rbkit.png&quot;&gt;&lt;img src=&quot;/img/rbkit.png&quot; alt=&quot;Rbkit main UI&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Rbkit is composed of two components: the &lt;code&gt;rbkit&lt;/code&gt; gem, which you include as usual in your &lt;code&gt;Gemfile&lt;/code&gt;, and a desktop client application which connects to your ruby app and allows you to interact with it—and that you’ll have to download and install separately from &lt;a href=&quot;http://rbkit.codemancers.com/&quot;&gt;Rbkit’s website&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;To use it, just&lt;/p&gt;

&lt;div class=&quot;language-ruby highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;require &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;rbkit&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;Rbkit&lt;/span&gt;.start_profiling
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;and start your application. Then just open up the rbkit desktop application and use the default connection settings to connect to your application.&lt;/p&gt;

&lt;p&gt;Besides the real-time memory charts, Rbkit also allows you to monitor the multiple GC generations…&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;/img/rbkit-generations.png&quot;&gt;&lt;img src=&quot;/img/rbkit-generations.png&quot; alt=&quot;Rbkit GC generations&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;…take heap dumps…&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;/img/rbkit-heap-dump.png&quot;&gt;&lt;img src=&quot;/img/rbkit-heap-dump.png&quot; alt=&quot;Rbkit heap dump&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;…and compare heap dumps.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;/img/rbkit-compare-heap-dump.png&quot;&gt;&lt;img src=&quot;/img/rbkit-compare-heap-dump.png&quot; alt=&quot;Rbkit comparing heap dumps&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Unfortunately, I wasn’t able to get Rbkit to work with ruby 2.3.1, but it works without issues on 2.2.5, so even if you normally run 2.3.1, it’s probably not very hard to get your app on 2.2.5 while you’re debugging some issue.&lt;/p&gt;

&lt;p&gt;You also cannot save heap dumps for later analysis (or with other tools), so hopefully that’s an improvement that will soon be contributed to the gem.&lt;/p&gt;

&lt;p&gt;Overall, Rbkit is a very interesting tool to add to any rubyst’s toolbelt. Stay tuned for parts 2 and 3, where I’ll look at more awesome tools to peek and pick at mri’s heap!&lt;/p&gt;
</description>
        <pubDate>Mon, 10 Oct 2016 22:20:28 +0100</pubDate>
        <link>https://ivoanjo.me/blog/2016/10/10/peek-and-pick-at-mris-heap/</link>
        <guid isPermaLink="true">https://ivoanjo.me/blog/2016/10/10/peek-and-pick-at-mris-heap/</guid>
        <category>blog</category>
      </item>
      <item>
        <title>why you should regenerate your spec_helper</title>
        <description>&lt;p&gt;If your project is like most ruby projects, your &lt;code&gt;spec_helper.rb&lt;/code&gt; looks something like &lt;a href=&quot;https://github.com/dry-rb/dry-container/blob/5a91264351ce89abf7deca346342f5497e6f34f9/spec/spec_helper.rb&quot;&gt;this&lt;/a&gt;:&lt;/p&gt;

&lt;div class=&quot;language-ruby highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span style=&quot;color:#777&quot;&gt;# encoding: utf-8&lt;/span&gt;

&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;if&lt;/span&gt; &lt;span style=&quot;color:#069&quot;&gt;RUBY_ENGINE&lt;/span&gt; == &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;rbx&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;
  require &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;codeclimate-test-reporter&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;
  &lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;CodeClimate&lt;/span&gt;::&lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;TestReporter&lt;/span&gt;.start
&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;end&lt;/span&gt;

require &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;dry/container&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;
require &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;dry/container/stub&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;

&lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;Dir&lt;/span&gt;[Pathname(&lt;span style=&quot;color:#069&quot;&gt;__FILE__&lt;/span&gt;).dirname.join(&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;support/**/*.rb&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;).to_s].each &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;do&lt;/span&gt; |file|
  require file
&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;end&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Pretty straightforward, and also missing on a lot of cool rspec features.&lt;/p&gt;

&lt;p&gt;Modern rspec versions (as I’m writing this, the latest version is 3.5.4) have a lot of cool features that are not enabled by default, so as not to break backwards compatibility. What this means is that in practice, unless you turn them on, you’re missing out on a lot of goodies and cool features that could help you spot potential issues in your code and specs.&lt;/p&gt;

&lt;p&gt;The quickest way to enable them is to ask &lt;code&gt;rspec&lt;/code&gt; to generate a pair of new &lt;code&gt;spec_helper.rb&lt;/code&gt; and &lt;code&gt;.rspec&lt;/code&gt; files for your project.&lt;/p&gt;

&lt;h2 id=&quot;generating-a-new-rspec-and-spec_helper&quot;&gt;generating a new &lt;code&gt;.rspec&lt;/code&gt; and &lt;code&gt;.spec_helper&lt;/code&gt;&lt;/h2&gt;

&lt;p&gt;Make sure you’re using the latest rspec: &lt;a href=&quot;https://rubygems.org/gems/rspec-core&quot;&gt;&lt;img src=&quot;https://badge.fury.io/rb/rspec-core.svg&quot; class=&quot;img-simple-valign&quot; alt=&quot;rspec-core latest version&quot; height=&quot;18&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;$ bundle update rspec
# ... bundler output ...
Bundle updated!
$ rspec -v
3.5.4
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Save your existing files (if any) by renaming them&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;$ mv .rspec old_dot_rspec
$ mv spec/spec_helper.rb spec/old_spec_helper.rb
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;…then ask rspec to generate you a new set of files.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;$ rspec --init
  create   .rspec
  create   spec/spec_helper.rb
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Let’s take a look at these files to see what they get you.&lt;/p&gt;

&lt;h2 id=&quot;the-newly-generated-rspec&quot;&gt;The newly-generated &lt;code&gt;.rspec&lt;/code&gt;&lt;/h2&gt;

&lt;div class=&quot;language-bash highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;--color
--require spec_helper
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;The &lt;code&gt;.rspec&lt;/code&gt; file specifies default flags that get passed to the &lt;code&gt;rspec&lt;/code&gt; command when you run your tests. So if you want one of the options you see listed on &lt;code&gt;rspec --help&lt;/code&gt; to apply by default, you can add them here.&lt;/p&gt;

&lt;p&gt;The two flags that are added by default are &lt;code&gt;--color&lt;/code&gt;, that enables coloring in the rspec output, and &lt;code&gt;--require spec_helper&lt;/code&gt;, that automatically requires the &lt;code&gt;spec_helper&lt;/code&gt; file whenever you run rspec, rather than you have to manually add &lt;code&gt;require &apos;spec_helper&apos;&lt;/code&gt; at the top of your specs.&lt;/p&gt;

&lt;p&gt;The latter option is more important than it seems. The &lt;code&gt;spec_helper.rb&lt;/code&gt; we just generated (and that I’ll go into detail below) sets a number of options, but you only get them if, obviously, the &lt;code&gt;spec_helper.rb&lt;/code&gt; is loaded by your specs. Forgetting the require may mean that when a spec is executed in isolation it may give a different result than when you execute your whole spec suite, which is troubling.&lt;/p&gt;

&lt;p&gt;So rather than worrying about the next time you’ll forget to include the magic require, just let the &lt;code&gt;.rspec&lt;/code&gt; always do it for you, and never worry about this again!&lt;/p&gt;

&lt;h2 id=&quot;the-newly-generated-specspec_helperrb&quot;&gt;The newly-generated &lt;code&gt;spec/spec_helper.rb&lt;/code&gt;&lt;/h2&gt;

&lt;p&gt;So we arrive at last to the meaty part. So what are these newfangled features that we get by regenerating the &lt;code&gt;spec_helper&lt;/code&gt;, then?&lt;/p&gt;

&lt;h3 id=&quot;the-include_chain_clauses_in_custom_matcher_descriptions-option&quot;&gt;The &lt;code&gt;include_chain_clauses_in_custom_matcher_descriptions&lt;/code&gt; option&lt;/h3&gt;

&lt;div class=&quot;language-ruby highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;config.expect_with &lt;span style=&quot;color:#A60&quot;&gt;:rspec&lt;/span&gt; &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;do&lt;/span&gt; |expectations|
  &lt;span style=&quot;color:#777&quot;&gt;# This option will default to `true` in RSpec 4. It&lt;/span&gt;
  &lt;span style=&quot;color:#777&quot;&gt;# makes the `description` and `failure_message` of&lt;/span&gt;
  &lt;span style=&quot;color:#777&quot;&gt;# custom matchers include text for helper methods&lt;/span&gt;
  &lt;span style=&quot;color:#777&quot;&gt;# defined using `chain`, e.g.:&lt;/span&gt;
  &lt;span style=&quot;color:#777&quot;&gt;#   be_bigger_than(2).and_smaller_than(4).description&lt;/span&gt;
  &lt;span style=&quot;color:#777&quot;&gt;#     # =&amp;gt; &amp;quot;be bigger than 2 and smaller than 4&amp;quot;&lt;/span&gt;
  &lt;span style=&quot;color:#777&quot;&gt;#   ...rather than:&lt;/span&gt;
  &lt;span style=&quot;color:#777&quot;&gt;#     # =&amp;gt; &amp;quot;be bigger than 2&amp;quot;&lt;/span&gt;
  expectations
    .include_chain_clauses_in_custom_matcher_descriptions =
      &lt;span style=&quot;color:#069&quot;&gt;true&lt;/span&gt;
&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;end&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;The &lt;code&gt;include_chain_clauses_in_custom_matcher_descriptions&lt;/code&gt; option gets you improved descriptions and failure messages when you’re using multiple custom matchers, and you can find a handy example in &lt;a href=&quot;https://relishapp.com/rspec/rspec-expectations/docs/custom-matchers/define-matcher-with-fluent-interface#include-chain-clauses-in-custom-matcher-descriptions-configured-to-true,-and-chained-method-with-argument&quot;&gt;rspec’s documentation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Of course, this one only applies if you’re using your own matchers, so let’s move on to bigger fish.&lt;/p&gt;

&lt;h3 id=&quot;the-verify_partial_doubles-option&quot;&gt;The &lt;code&gt;verify_partial_doubles&lt;/code&gt; option&lt;/h3&gt;

&lt;div class=&quot;language-ruby highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;config.mock_with &lt;span style=&quot;color:#A60&quot;&gt;:rspec&lt;/span&gt; &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;do&lt;/span&gt; |mocks|
  &lt;span style=&quot;color:#777&quot;&gt;# Prevents you from mocking or stubbing a method that does&lt;/span&gt;
  &lt;span style=&quot;color:#777&quot;&gt;# not exist on a real object. This is generally&lt;/span&gt;
  &lt;span style=&quot;color:#777&quot;&gt;# recommended, and will default to `true` in RSpec 4.&lt;/span&gt;
  mocks.verify_partial_doubles = &lt;span style=&quot;color:#069&quot;&gt;true&lt;/span&gt;
&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;end&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;This option is truly awesome. When you enable it, rspec also checks during the test suite execution that any mocks you setup are consistent with the original class being mocked.&lt;/p&gt;

&lt;p&gt;What does this mean in practice? Well, consider that you’re mocking the &lt;code&gt;:delete&lt;/code&gt; operation on the &lt;code&gt;File&lt;/code&gt; class because you don’t want your test suite to be deleting real files during its execution, but you end up mistyping &lt;code&gt;:delete&lt;/code&gt; as &lt;code&gt;:delte&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;language-ruby highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;allow(&lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;File&lt;/span&gt;).to receive(&lt;span style=&quot;color:#A60&quot;&gt;:delte&lt;/span&gt;)
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;If you then exercise your code, your specs may still pass, but instead of mocking the &lt;code&gt;delete&lt;/code&gt; operation, you may be doing real deletes!&lt;/p&gt;

&lt;p&gt;When you enable this option you’ll instead get as an output of your test run:&lt;/p&gt;

&lt;div class=&quot;language-ruby highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt; &lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;Failure&lt;/span&gt;/&lt;span style=&quot;color:#606&quot;&gt;Error&lt;/span&gt;: allow(&lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;File&lt;/span&gt;).to receive(&lt;span style=&quot;color:#A60&quot;&gt;:delte&lt;/span&gt;)
   &lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;File&lt;/span&gt; does &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;not&lt;/span&gt; &lt;span style=&quot;color:#606&quot;&gt;implement&lt;/span&gt;: delte
 &lt;span style=&quot;color:#777&quot;&gt;# ./spec/foo_spec.rb:4:in `block (2 levels) in &amp;lt;top (required)&amp;gt;&apos;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Another big benefit of this option is when mocking external libraries. Whenever you upgrade to a new major version a library, you may be led to believe that your code still works if you ran your specs and you’re still all green. But, however, if you’re mocking methods that no longer exist in the new library version, you can be in for a big surprise when you deploy your changes.&lt;/p&gt;

&lt;p&gt;Using the verified doubles, your specs will fail right away if you’re using mocked objects wrongly. So upgrading major versions just got easier and your test suite leaves you more confident!&lt;/p&gt;

&lt;p&gt;Note that these verified doubles check not only that a method exists, but also the number of arguments, and whenever keyword arguments are in use, if the proper required and optional keyword arguments are being used. So a whole lot of awesome 🎉!&lt;/p&gt;

&lt;h3 id=&quot;the-shared_context_metadata_behavior-option&quot;&gt;The &lt;code&gt;shared_context_metadata_behavior&lt;/code&gt; option&lt;/h3&gt;

&lt;div class=&quot;language-ruby highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span style=&quot;color:#777&quot;&gt;# This option will default to `:apply_to_host_groups`&lt;/span&gt;
&lt;span style=&quot;color:#777&quot;&gt;# in RSpec 4 (and will have no way to turn it off --&lt;/span&gt;
&lt;span style=&quot;color:#777&quot;&gt;# the option exists only for backwards compatibility&lt;/span&gt;
&lt;span style=&quot;color:#777&quot;&gt;# in RSpec 3). It causes shared context metadata to&lt;/span&gt;
&lt;span style=&quot;color:#777&quot;&gt;# be inherited by the metadata hash of host groups&lt;/span&gt;
&lt;span style=&quot;color:#777&quot;&gt;# and examples, rather than triggering implicit&lt;/span&gt;
&lt;span style=&quot;color:#777&quot;&gt;# auto-inclusion in groups with matching metadata.&lt;/span&gt;
config
  .shared_context_metadata_behavior = &lt;span style=&quot;color:#A60&quot;&gt;:apply_to_host_groups&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;This is also a very minor change to behavior of shared contexts, but the new behavior will be the default and only option in rspec 4, so enabling this today helps makes your specs forward-compatible with the next major rspec release.&lt;/p&gt;

&lt;p&gt;For more details on this option see &lt;a href=&quot;http://rspec.info/blog/2016/07/rspec-3-5-has-been-released/&quot;&gt;the rspec 3.5 release announcement&lt;/a&gt; and the &lt;a href=&quot;http://www.rubydoc.info/gems/rspec-core/RSpec%2FCore%2FConfiguration%3Ashared_context_metadata_behavior&quot;&gt;api documentation&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;suggested-settings-in-specspec_helperrb&quot;&gt;Suggested settings in &lt;code&gt;spec/spec_helper.rb&lt;/code&gt;&lt;/h2&gt;

&lt;p&gt;If you’re following along an automatically-generated &lt;code&gt;spec_helper.rb&lt;/code&gt; as I suggested above, you’ll now get to a section of suggested options that are by default commented out.&lt;/p&gt;

&lt;div class=&quot;language-ruby highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span style=&quot;color:#777&quot;&gt;# The settings below are suggested to provide a good&lt;/span&gt;
&lt;span style=&quot;color:#777&quot;&gt;# initial experience with RSpec, but feel free to customize&lt;/span&gt;
&lt;span style=&quot;color:#777&quot;&gt;# to your heart&apos;s content.&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;I believe most of them are rather useful, so let’s start turning them on!&lt;/p&gt;

&lt;h3 id=&quot;the-filter_run_when_matching-option&quot;&gt;The &lt;code&gt;filter_run_when_matching&lt;/code&gt; option&lt;/h3&gt;

&lt;div class=&quot;language-ruby highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span style=&quot;color:#777&quot;&gt;# This allows you to limit a spec run to individual&lt;/span&gt;
&lt;span style=&quot;color:#777&quot;&gt;# examples or groups you care about by tagging them with&lt;/span&gt;
&lt;span style=&quot;color:#777&quot;&gt;# `:focus` metadata. When nothing is tagged with&lt;/span&gt;
&lt;span style=&quot;color:#777&quot;&gt;# `:focus`, all examples get run. RSpec also provides&lt;/span&gt;
&lt;span style=&quot;color:#777&quot;&gt;# aliases for `it`, `describe`, and `context` that include&lt;/span&gt;
&lt;span style=&quot;color:#777&quot;&gt;# `:focus` metadata: `fit`, `fdescribe` and `fcontext`,&lt;/span&gt;
&lt;span style=&quot;color:#777&quot;&gt;# respectively.&lt;/span&gt;
config.filter_run_when_matching &lt;span style=&quot;color:#A60&quot;&gt;:focus&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;The &lt;code&gt;filter_run_when_matching&lt;/code&gt; option allows you to easily restrict your test suite execution to a specific subset of specs. This is helpful when you’re working on a number of classes and don’t want any other specs to run for now.&lt;/p&gt;

&lt;p&gt;To trigger this behavior, just add the &lt;code&gt;:focus&lt;/code&gt; option after &lt;code&gt;describe&lt;/code&gt;, &lt;code&gt;context&lt;/code&gt; or &lt;code&gt;it&lt;/code&gt; to any specs or groups of specs you want to select:&lt;/p&gt;

&lt;div class=&quot;language-ruby highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;RSpec&lt;/span&gt;.describe &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;Foo&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;, &lt;span style=&quot;color:#A60&quot;&gt;:focus&lt;/span&gt; &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;do&lt;/span&gt;
  &lt;span style=&quot;color:#777&quot;&gt;# ...&lt;/span&gt;
&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;end&lt;/span&gt;

&lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;RSpec&lt;/span&gt;.describe &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;Bar&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt; &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;do&lt;/span&gt;
  context &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;when made out of iron&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;, &lt;span style=&quot;color:#A60&quot;&gt;:focus&lt;/span&gt; &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;do&lt;/span&gt;
    &lt;span style=&quot;color:#777&quot;&gt;# ...&lt;/span&gt;
  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;end&lt;/span&gt;
&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;end&lt;/span&gt;

&lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;RSpec&lt;/span&gt;.describe &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;Baz&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt; &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;do&lt;/span&gt;
  it &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;does stuff&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;, &lt;span style=&quot;color:#A60&quot;&gt;:focus&lt;/span&gt; &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;do&lt;/span&gt;
    &lt;span style=&quot;color:#777&quot;&gt;# ...&lt;/span&gt;
  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;end&lt;/span&gt;
&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;end&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;In the above example, all specs tagged with &lt;code&gt;:focus&lt;/code&gt; will be executed, and any other specs in the test suite will be left out.&lt;/p&gt;

&lt;p&gt;As a shorthand, you can also prepend an &lt;code&gt;f&lt;/code&gt; to &lt;code&gt;describe&lt;/code&gt; (&lt;code&gt;fdescribe&lt;/code&gt;), &lt;code&gt;context&lt;/code&gt; (&lt;code&gt;fcontext&lt;/code&gt;), or &lt;code&gt;it&lt;/code&gt; (&lt;code&gt;fit&lt;/code&gt;) to get the same effect:&lt;/p&gt;

&lt;div class=&quot;language-ruby highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;RSpec&lt;/span&gt;.fdescribe &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;Foo&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt; &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;do&lt;/span&gt;
  &lt;span style=&quot;color:#777&quot;&gt;# ...&lt;/span&gt;
&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;end&lt;/span&gt;

&lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;RSpec&lt;/span&gt;.describe &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;Bar&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt; &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;do&lt;/span&gt;
  fcontext &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;when made out of iron&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt; &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;do&lt;/span&gt;
    &lt;span style=&quot;color:#777&quot;&gt;# ...&lt;/span&gt;
  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;end&lt;/span&gt;
&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;end&lt;/span&gt;

&lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;RSpec&lt;/span&gt;.describe &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;Baz&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt; &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;do&lt;/span&gt;
  fit &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;does stuff&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt; &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;do&lt;/span&gt;
    &lt;span style=&quot;color:#777&quot;&gt;# ...&lt;/span&gt;
  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;end&lt;/span&gt;
&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;end&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Personally, I favor adding &lt;code&gt;:focus&lt;/code&gt; as it’s harder to accidentally forget one in a commit ;)&lt;/p&gt;

&lt;h3 id=&quot;the-example_status_persistence_file_path-option&quot;&gt;The &lt;code&gt;example_status_persistence_file_path&lt;/code&gt; option&lt;/h3&gt;

&lt;div class=&quot;language-ruby highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span style=&quot;color:#777&quot;&gt;# Allows RSpec to persist some state between runs in order&lt;/span&gt;
&lt;span style=&quot;color:#777&quot;&gt;# to support the `--only-failures` and `--next-failure` CLI&lt;/span&gt;
&lt;span style=&quot;color:#777&quot;&gt;# options. We recommend you configure your source control&lt;/span&gt;
&lt;span style=&quot;color:#777&quot;&gt;# system to ignore this file.&lt;/span&gt;
config.example_status_persistence_file_path =
  &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;spec/examples.txt&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;The &lt;code&gt;example_status_persistence_file_path&lt;/code&gt; makes rspec remember which specs failed from your test suite.&lt;/p&gt;

&lt;p&gt;This allows you to focus on fixing each failing spec one-by-one by running &lt;code&gt;rspec --next-failure&lt;/code&gt;, or to just limit the test suite execution to the failing specs with &lt;code&gt;rspec --only-failures&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;As an example, consider the following execution:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;$ rspec

Foo
  should not fail (FAILED - 1)
  when you really want to Foo
    really should not fail (FAILED - 2)

Bar
  works nicely

Failures:

  1) Foo should not fail
     Failure/Error: fail
     RuntimeError:
     # ./spec/foo_spec.rb:3:in `block (2 levels) in &amp;lt;top (required)&amp;gt;&apos;

  2) Foo when you really want to Foo really should not fail
     Failure/Error: fail
     RuntimeError:
     # ./spec/foo_spec.rb:8:in `block (3 levels) in &amp;lt;top (required)&amp;gt;&apos;

Finished in 0.00085 seconds (files took 0.07439 seconds to load)
3 examples, 2 failures

Failed examples:

rspec ./spec/foo_spec.rb:2 # Foo should not fail
rspec ./spec/foo_spec.rb:7 # Foo when you really want to Foo really should not fail
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;In this case, I ran the test suite, and it resulted in 2 failed specs.&lt;/p&gt;

&lt;p&gt;Now, if I run again with &lt;code&gt;rspec --only-failures&lt;/code&gt;, rspec will only retry the failed specs, in this case, those for &lt;code&gt;Foo&lt;/code&gt;, and will not run the spec for &lt;code&gt;Bar&lt;/code&gt;, which was working correctly.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;$ rspec --only-failures
Run options: include {:last_run_status=&amp;gt;&amp;quot;failed&amp;quot;}

Foo
  should not fail (FAILED - 1)
  when you really want to Foo
    really should not fail (FAILED - 2)

Failures:

  1) Foo should not fail
     Failure/Error: fail
     RuntimeError:
     # ./spec/foo_spec.rb:3:in `block (2 levels) in &amp;lt;top (required)&amp;gt;&apos;

  2) Foo when you really want to Foo really should not fail
     Failure/Error: fail
     RuntimeError:
     # ./spec/foo_spec.rb:8:in `block (3 levels) in &amp;lt;top (required)&amp;gt;&apos;

Finished in 0.00074 seconds (files took 0.07481 seconds to load)
2 examples, 2 failures

Failed examples:

rspec ./spec/foo_spec.rb:2 # Foo should not fail
rspec ./spec/foo_spec.rb:7 # Foo when you really want to Foo really should not fail
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Finally, if you really want to focus and tackle failing specs one-by-one, you can use &lt;code&gt;rspec --next-failure&lt;/code&gt; and only the first of the failing specs will be executed.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;$ rspec --next-failure
Run options: include {:last_run_status=&amp;gt;&amp;quot;failed&amp;quot;}

Foo
  should not fail (FAILED - 1)

Failures:

  1) Foo should not fail
     Failure/Error: fail
     RuntimeError:
     # ./spec/foo_spec.rb:3:in `block (2 levels) in &amp;lt;top (required)&amp;gt;&apos;

Finished in 0.00055 seconds (files took 0.07577 seconds to load)
1 example, 1 failure

Failed examples:

rspec ./spec/foo_spec.rb:2 # Foo should not fail
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;This option is somewhat like &lt;code&gt;:focus&lt;/code&gt; above, but rspec automatically focuses you on failing specs.&lt;/p&gt;

&lt;h3 id=&quot;the-disable_monkey_patching-option&quot;&gt;The &lt;code&gt;disable_monkey_patching!&lt;/code&gt; option&lt;/h3&gt;

&lt;div class=&quot;language-ruby highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span style=&quot;color:#777&quot;&gt;# Limits the available syntax to the non-monkey patched&lt;/span&gt;
&lt;span style=&quot;color:#777&quot;&gt;# syntax that is recommended. For more details, see:&lt;/span&gt;
&lt;span style=&quot;color:#777&quot;&gt;#   - http://rspec.info/blog/2012/06/rspecs-new-expectation-syntax/&lt;/span&gt;
&lt;span style=&quot;color:#777&quot;&gt;#   - http://www.teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/&lt;/span&gt;
&lt;span style=&quot;color:#777&quot;&gt;#   - http://rspec.info/blog/2014/05/notable-changes-in-rspec-3/#zero-monkey-patching-mode&lt;/span&gt;
config.disable_monkey_patching!
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Monkey-patching, e.g. the practice of extending or changing system or external library code during runtime, is both a blessing and a curse in Ruby.&lt;/p&gt;

&lt;p&gt;Earlier versions of rspec employed a number of monkey patches to provide the DSL syntax used in tests. Unfortunately, &lt;a href=&quot;http://rspec.info/blog/2012/06/rspecs-new-expectation-syntax/&quot;&gt;this collided with ruby’s delegation mechanisms&lt;/a&gt; and thus a few releases ago the rspec developers came up with a new matching syntax (the &lt;code&gt;expect&lt;/code&gt;-based one) that avoids the need for monkey patching.&lt;/p&gt;

&lt;p&gt;For compatibility reasons, some of the monkey patches are still enabled by default, but their use is no longer recommended, and the &lt;code&gt;disable_monkey_patching!&lt;/code&gt; option disables them for good.&lt;/p&gt;

&lt;p&gt;In most projects I’ve found that the only monkey patches still in use are top-level &lt;code&gt;describe&lt;/code&gt; and &lt;code&gt;context&lt;/code&gt; blocks:&lt;/p&gt;

&lt;div class=&quot;language-ruby highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;describe &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;Foo&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt; &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;do&lt;/span&gt;
  context &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;when fooing&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt; &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;do&lt;/span&gt;
    &lt;span style=&quot;color:#777&quot;&gt;# ...&lt;/span&gt;
  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;end&lt;/span&gt;
&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;end&lt;/span&gt;

context &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;when the current planet is the earth&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt; &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;do&lt;/span&gt;
  describe &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;clouds&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt; &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;do&lt;/span&gt;
    &lt;span style=&quot;color:#777&quot;&gt;# ...&lt;/span&gt;
  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;end&lt;/span&gt;
&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;end&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Running these specs with &lt;code&gt;disable_monkey_patching!&lt;/code&gt; will yield something like:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;$ rspec
spec/foo_spec.rb:1:in `&amp;lt;top (required)&amp;gt;&apos;: undefined method `describe&apos; for main:Object (NoMethodError)
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;To fix this, just prefix any top-level &lt;code&gt;describe&lt;/code&gt; and &lt;code&gt;context&lt;/code&gt; with the &lt;code&gt;RSpec&lt;/code&gt; class:&lt;/p&gt;

&lt;div class=&quot;language-ruby highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;RSpec&lt;/span&gt;.describe &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;Foo&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt; &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;do&lt;/span&gt;
  context &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;when fooing&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt; &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;do&lt;/span&gt;
    &lt;span style=&quot;color:#777&quot;&gt;# ...&lt;/span&gt;
  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;end&lt;/span&gt;
&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;end&lt;/span&gt;

&lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;RSpec&lt;/span&gt;.context &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;when the current planet is the earth&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt; &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;do&lt;/span&gt;
  describe &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;clouds&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt; &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;do&lt;/span&gt;
    &lt;span style=&quot;color:#777&quot;&gt;# ...&lt;/span&gt;
  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;end&lt;/span&gt;
&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;end&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;In most cases adding &lt;code&gt;RSpec.&lt;/code&gt; to top-level blocks should be enough. Notice that &lt;code&gt;context&lt;/code&gt;s and &lt;code&gt;describe&lt;/code&gt;s nested inside the top-level blocks do not need to be modified.&lt;/p&gt;

&lt;p&gt;If, however, some of your specs still make use of the old &lt;code&gt;should&lt;/code&gt; matching syntax, consider using the &lt;a href=&quot;http://yujinakayama.me/transpec/&quot;&gt;&lt;code&gt;transpec&lt;/code&gt;&lt;/a&gt; gem to automatically update your code to the newer &lt;code&gt;expect&lt;/code&gt; syntax—no manual work needed!&lt;/p&gt;

&lt;h3 id=&quot;the-warnings-option&quot;&gt;The &lt;code&gt;warnings&lt;/code&gt; option&lt;/h3&gt;

&lt;div class=&quot;language-ruby highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span style=&quot;color:#777&quot;&gt;# This setting enables warnings. It&apos;s recommended, but in&lt;/span&gt;
&lt;span style=&quot;color:#777&quot;&gt;# some cases may be too noisy due to issues in dependencies.&lt;/span&gt;
config.warnings = &lt;span style=&quot;color:#069&quot;&gt;true&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;This is one of the options I recommend the most. By default, even when running rspec, ruby does not emit warnings for valid, but possibly buggy code, such as:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Require loops (file &lt;code&gt;foo.rb&lt;/code&gt; requires &lt;code&gt;bar.rb&lt;/code&gt;, which requires &lt;code&gt;foo.rb&lt;/code&gt;)&lt;/li&gt;
  &lt;li&gt;Unused variables&lt;/li&gt;
  &lt;li&gt;Using the value of an uninitialized variable&lt;/li&gt;
  &lt;li&gt;Redefining a method in the same scope as the original definition&lt;/li&gt;
  &lt;li&gt;Obsolete library usage&lt;/li&gt;
  &lt;li&gt;…&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This option enables these warnings while running your test suite. You may find interesting things, not only on your suite, but on your own dependences—many of which also have warnings disabled on their own test suites and thus never noticed that these potential issues were there (see also &lt;a href=&quot;#easiest-open-source-contribution-ever&quot;&gt;below&lt;/a&gt; for a discussion on this).&lt;/p&gt;

&lt;h3 id=&quot;enable-detailed-rspec-output-when-running-only-for-a-single-file&quot;&gt;Enable detailed rspec output when running only for a single file&lt;/h3&gt;

&lt;div class=&quot;language-ruby highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span style=&quot;color:#777&quot;&gt;# Many RSpec users commonly either run the entire suite or&lt;/span&gt;
&lt;span style=&quot;color:#777&quot;&gt;# an individual file, and it&apos;s useful to allow more verbose&lt;/span&gt;
&lt;span style=&quot;color:#777&quot;&gt;# output when running an individual spec file.&lt;/span&gt;
&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;if&lt;/span&gt; config.files_to_run.one?
  &lt;span style=&quot;color:#777&quot;&gt;# Use the documentation formatter for detailed output,&lt;/span&gt;
  &lt;span style=&quot;color:#777&quot;&gt;# unless a formatter has already been configured&lt;/span&gt;
  &lt;span style=&quot;color:#777&quot;&gt;# (e.g. via a command-line flag).&lt;/span&gt;
  config.default_formatter = &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;doc&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;end&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;For larger test suites, it’s usual to use the default rspec output where you print a dot for a passed spec, and an &lt;code&gt;F&lt;/code&gt; for a failed one.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;$ rspec
................

Finished in 0.00192 seconds (files took 0.07474 seconds to load)
16 examples, 0 failures
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;This tweak changes rspec’s behavior to output a detailed description of the tests when you run it with a single file (or only a single file is in &lt;code&gt;:focus&lt;/code&gt;):&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;$ rspec spec/foo_spec.rb

Foo
  should not fail
  when you really want to Foo
    really should not fail

Finished in 0.0006 seconds (files took 0.07574 seconds to load)
2 examples, 0 failures
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Simple, but useful :)&lt;/p&gt;

&lt;h3 id=&quot;the-profile_examples-option&quot;&gt;The &lt;code&gt;profile_examples&lt;/code&gt; option&lt;/h3&gt;

&lt;div class=&quot;language-ruby highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span style=&quot;color:#777&quot;&gt;# Print the 10 slowest examples and example groups at the&lt;/span&gt;
&lt;span style=&quot;color:#777&quot;&gt;# end of the spec run, to help surface which specs are&lt;/span&gt;
&lt;span style=&quot;color:#777&quot;&gt;# running particularly slow.&lt;/span&gt;
config.profile_examples = &lt;span style=&quot;color:#00D&quot;&gt;10&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Remember the golden days of your project, when the entire test suite ran in under 10 seconds? The &lt;code&gt;profile_examples&lt;/code&gt; option lists the slowest-running specs in your suite, which really highlights where time is being spent—perhaps the &lt;code&gt;sleep&lt;/code&gt; you just added isn’t that innocent after all.&lt;/p&gt;

&lt;p&gt;Personally, I find that 10 examples is a bit too noisy, and set it to either 3 or 5, but I find this option really useful to spot slow specs that are candidates for simplification, allowing your test suite to be blazingly-fast again.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;$ rspec

Foo
  should not fail
  when you really want to Foo
    really should not fail

Bar
  works nicely

Top 3 slowest examples (0.00019 seconds, 20.5% of total time):
  Foo should not fail
    0.00009 seconds ./spec/foo_spec.rb:2
  Bar works nicely
    0.00005 seconds ./spec/foo_spec.rb:14
  Foo when you really want to Foo really should not fail
    0.00005 seconds ./spec/foo_spec.rb:7

Top 2 slowest example groups:
  Foo
    0.00023 seconds average (0.00045 seconds / 2 examples) ./spec/foo_spec.rb:1
  Bar
    0.00015 seconds average (0.00015 seconds / 1 example) ./spec/foo_spec.rb:13

Finished in 0.00092 seconds (files took 0.07551 seconds to load)
3 examples, 0 failures
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;h3 id=&quot;random-spec-ordering&quot;&gt;Random spec ordering&lt;/h3&gt;

&lt;div class=&quot;language-ruby highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span style=&quot;color:#777&quot;&gt;# Run specs in random order to surface order dependencies.&lt;/span&gt;
&lt;span style=&quot;color:#777&quot;&gt;# If you find an order dependency and want to debug it, you&lt;/span&gt;
&lt;span style=&quot;color:#777&quot;&gt;# can fix the order by providing the seed, which is printed&lt;/span&gt;
&lt;span style=&quot;color:#777&quot;&gt;# after each run.&lt;/span&gt;
&lt;span style=&quot;color:#777&quot;&gt;#     --seed 1234&lt;/span&gt;
config.order = &lt;span style=&quot;color:#A60&quot;&gt;:random&lt;/span&gt;

&lt;span style=&quot;color:#777&quot;&gt;# Seed global randomization in this process using the&lt;/span&gt;
&lt;span style=&quot;color:#777&quot;&gt;# `--seed` CLI option.&lt;/span&gt;
&lt;span style=&quot;color:#777&quot;&gt;# Setting this allows you to use `--seed` to&lt;/span&gt;
&lt;span style=&quot;color:#777&quot;&gt;# deterministically reproduce test failures related to&lt;/span&gt;
&lt;span style=&quot;color:#777&quot;&gt;# randomization by passing the same `--seed` value as the&lt;/span&gt;
&lt;span style=&quot;color:#777&quot;&gt;# one that triggered the failure.&lt;/span&gt;
&lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;Kernel&lt;/span&gt;.srand config.seed
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;By default, rspec runs your specs in the order that they are defined (and your specs in alphabetic order). This helps during development—and I find myself temporarily enabling in-order execution when writing specs with &lt;code&gt;rspec --order defined&lt;/code&gt; often—but may be hiding bugs.&lt;/p&gt;

&lt;p&gt;How so? Consider a very simple example from my &lt;a href=&quot;/blog/2016/05/14/did-you-know-ruby/&quot;&gt;did_you_know.ruby?&lt;/a&gt; presentation:&lt;/p&gt;

&lt;div class=&quot;language-ruby highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;class&lt;/span&gt; &lt;span style=&quot;color:#B06;font-weight:bold&quot;&gt;Bar&lt;/span&gt;
  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color:#069&quot;&gt;self&lt;/span&gt;.&lt;span style=&quot;color:#06B;font-weight:bold&quot;&gt;hello&lt;/span&gt;
    message =
      &lt;span style=&quot;color:#069&quot;&gt;ENV&lt;/span&gt;[&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;MESSAGE&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;] || &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;hello&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;
    puts message
  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;end&lt;/span&gt;
&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;end&lt;/span&gt;

&lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;RSpec&lt;/span&gt;.describe &lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;Bar&lt;/span&gt; &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;do&lt;/span&gt;
  describe &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;#hello&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt; &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;do&lt;/span&gt;
    it &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;prints hello&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt; &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;do&lt;/span&gt;
      expect(&lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;Bar&lt;/span&gt;).to receive(&lt;span style=&quot;color:#A60&quot;&gt;:puts&lt;/span&gt;).with(&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;hello&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;)
      &lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;Bar&lt;/span&gt;.hello
    &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;end&lt;/span&gt;

    it &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;is set prints the message in ENV[&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;MESSAGE&lt;/span&gt;&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;]&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt; &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;do&lt;/span&gt;
      &lt;span style=&quot;color:#069&quot;&gt;ENV&lt;/span&gt;[&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;MESSAGE&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;] = &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;hello world&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;
      expect(&lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;Bar&lt;/span&gt;).to receive(&lt;span style=&quot;color:#A60&quot;&gt;:puts&lt;/span&gt;).with(&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;hello world&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;)
      &lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;Bar&lt;/span&gt;.hello
    &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;end&lt;/span&gt;
  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;end&lt;/span&gt;
&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;end&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;These specs pass when executed in order, but fail whenever the spec that sets the &lt;code&gt;ENV[&apos;MESSAGE&apos;]&lt;/code&gt; runs before the one that tests that it prints hello.&lt;/p&gt;

&lt;p&gt;Now this example is pretty trivial, but in a big test suite it’s possible that quite accidentally one spec is leaving behind state that makes other tests either pass when they shouldn’t, or fail mysteriously.&lt;/p&gt;

&lt;p&gt;Thus, the rspec &lt;code&gt;order&lt;/code&gt; option enables random spec ordering, making rspec pick a randomized order for executing your specs, making sure that sooner or later code or specs that fail sporadically is found.&lt;/p&gt;

&lt;p&gt;Whenever rspec runs with a randomized test ordering it prints a random seed—a value which you can use to repeat that exact ordering, when something files.&lt;/p&gt;

&lt;p&gt;To run your specs with that seed, just run &lt;code&gt;rspec --seed seed_value&lt;/code&gt;. And if you find yourself scratching your head finding which specs are interfering with each other, you can see an example of using rspec’s &lt;code&gt;--bisect&lt;/code&gt; option &lt;a href=&quot;/blog/2016/05/14/did-you-know-ruby/&quot;&gt;on my presentation&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;my-test-suite-was-green-and-now-it-fails-&quot;&gt;My test suite was green and now it fails! :(&lt;/h2&gt;

&lt;p&gt;Some of the options I suggest above may uncover issues in your code (in the case of verified partial doubles or random spec ordering) or on your test suite when you still used outdated rspec syntax (in the case of the disable monkey patching option).&lt;/p&gt;

&lt;p&gt;If you find yourself in this situation, I recommend disabling the options again and enabling them one-by-one until you see the culprit. And when you do, I recommend looking into it, as you may have just uncovered a bug somewhere in your code.&lt;/p&gt;

&lt;h2 id=&quot;easiest-open-source-contribution-ever&quot;&gt;Easiest open-source contribution ever!&lt;/h2&gt;

&lt;p&gt;As I’ve alluded to above, many existing gems also have outdated rspec configurations and cause lots of warnings when executed.&lt;/p&gt;

&lt;p&gt;This means that contributing updated rspec configurations and fixes for warnings is one of the easiest ways you can start contributing to a project.&lt;/p&gt;

&lt;p&gt;So that’s exactly what I’ve been doing:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/ruby-amqp/march_hare/pull/99&quot;&gt;https://github.com/ruby-amqp/march_hare/pull/99&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/dry-rb/dry-container/pull/24&quot;&gt;https://github.com/dry-rb/dry-container/pull/24&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/pezra/hal-client/pull/54&quot;&gt;https://github.com/pezra/hal-client/pull/54&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/beatrichartz/configurations/pull/15&quot;&gt;https://github.com/beatrichartz/configurations/pull/15&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So if you’ve been eyeing a project, here’s your chance! And if you just enabled warnings in your own code, and see that everyone else’s is causing warnings, help fix them! :)&lt;/p&gt;

&lt;p&gt;Thanks for reading thus far!&lt;/p&gt;
</description>
        <pubDate>Sun, 25 Sep 2016 14:32:23 +0100</pubDate>
        <link>https://ivoanjo.me/blog/2016/09/25/why-you-should-regenerate-your-spec-helper/</link>
        <guid isPermaLink="true">https://ivoanjo.me/blog/2016/09/25/why-you-should-regenerate-your-spec-helper/</guid>
        <category>blog</category>
      </item>
      <item>
        <title>explaining git</title>
        <description>&lt;p&gt;Recently I have a quick presentation on how git works during Talkdesk’s TGIF presentation slot.&lt;/p&gt;

&lt;p&gt;I find that knowing some of these details really makes git “click” and easy to understand, as most (very awesome) git functionality can be simply mapped a bunch of operations on commit graphs and on plain text files that store commit hashes.&lt;/p&gt;

&lt;p&gt;Here it is, in all its badly-illustrated glory:&lt;/p&gt;

&lt;iframe src=&quot;//slides.com/ianjo/explaining_git/embed?style=light&quot; width=&quot;576&quot; height=&quot;420&quot; scrolling=&quot;no&quot; frameborder=&quot;0&quot; webkitallowfullscreen=&quot;&quot; mozallowfullscreen=&quot;&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;

&lt;p&gt;&lt;br /&gt;
Feel free to leave some kick-ass git tool suggestions in the comments. Or not :)&lt;/p&gt;
</description>
        <pubDate>Sat, 03 Sep 2016 19:44:15 +0100</pubDate>
        <link>https://ivoanjo.me/blog/2016/09/03/explaining-git/</link>
        <guid isPermaLink="true">https://ivoanjo.me/blog/2016/09/03/explaining-git/</guid>
        <category>blog</category>
      </item>
      <item>
        <title>another round of jruby goodness</title>
        <description>&lt;p&gt;That was fast! Another?&lt;/p&gt;

&lt;p&gt;Indeed. I have to confess that I spent the weekend reading through “&lt;a href=&quot;https://pragprog.com/book/jkdepj2/deploying-with-jruby-9k&quot;&gt;&lt;em&gt;Deploying with JRuby 9k&lt;/em&gt;&lt;/a&gt;” by Joe Kutner and following some of the links in the book, which led to a lot of cool discoveries.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://pragprog.com/book/jkdepj2/deploying-with-jruby-9k&quot;&gt;&lt;img src=&quot;https://imagery.pragprog.com/products/468/jkdepj2_xlargebeta.jpg?1462218121&quot; alt=&quot;book cover&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you’re looking at JRuby for more than a small test app, I do recommend it, although as it has a lot of examples and commands I fear may become outdated fast as tools evolve. So that’s why you should get it while it’s hot (no commission here, just a happy camper)!&lt;/p&gt;

&lt;p&gt;So without further ado…&lt;/p&gt;

&lt;h2 id=&quot;jruby-lint-see-how-ready-your-ruby-code-is-for-the-j&quot;&gt;jruby-lint: see how ready your ruby code is for the &lt;strong&gt;J&lt;/strong&gt;&lt;/h2&gt;

&lt;p&gt;The &lt;a href=&quot;https://github.com/jruby/jruby-lint&quot;&gt;&lt;code&gt;jruby-lint&lt;/code&gt;&lt;/a&gt; gem—also maintained by the JRuby developers—looks at your code and &lt;code&gt;Gemfile&lt;/code&gt; and warns you of things that may pose issues when using JRuby:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;./Gemfile:24: [gems, warning] Found gem &apos;oj&apos; which is reported to have some issues:
Try gson, json or json_pure instead.
Try any one of the following JRuby-based servers: Trinidad, Mizuno, Kirk or Puma (though make sure to use the JRuby-native version of the gem).
./Gemfile:43: [gems, warning] Found gem &apos;bson_ext&apos; which is reported to have some issues:
bson_ext isn&apos;t used with JRuby. Instead, some native Java extensions are bundled with the bson gem.
./Gemfile:59: [gems, warning] Found gem &apos;nokogiri&apos; which is reported to have some issues:
For best results, use the pure-Java version of Nokogiri (default after v1.5).
./app/controllers/api/user_controller.rb:25: [nonatomic, warning] Non-local operator assignment is not guaranteed to be atomic
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;The developers are still hoping to further improve this gem, but it’s a good starting point for a project looking at going the JRuby way.&lt;/p&gt;

&lt;h2 id=&quot;bundler-install---binstubs-or-having-your-cake-and-eating-it-too&quot;&gt;&lt;code&gt;bundler install --binstubs&lt;/code&gt;, or having your cake and eating it too&lt;/h2&gt;

&lt;p&gt;In &lt;a href=&quot;/blog/2016/07/16/down-the-jruby-rabbit-hole/&quot;&gt;my previous post on JRuby&lt;/a&gt; I mentioned that running commands with &lt;code&gt;bundle exec&lt;/code&gt; meant longer start-up times, as that meant booting up a JVM with JRuby for bundler, which would then fork another JVM with JRuby for the target command.&lt;/p&gt;

&lt;p&gt;I suggested as a workaround to not run the commands inside bundler, but by doing that you’re giving up a lot of bundler’s goodness.&lt;/p&gt;

&lt;p&gt;But little did I know that there was an alternative, even better solution: the &lt;code&gt;--binstubs&lt;/code&gt; option! When running &lt;code&gt;bundle install --binstubs&lt;/code&gt;, bundler creates small ruby wrappers for each command supplied by the installed gems (e.g. &lt;code&gt;rspec&lt;/code&gt;, &lt;code&gt;pry&lt;/code&gt;, &lt;code&gt;puma&lt;/code&gt;, etc) in a &lt;code&gt;bin/&lt;/code&gt; folder inside your project directory.&lt;/p&gt;

&lt;p&gt;Using these wrappers to run commands from gems, you get the same environment and setup you’d get from bundler, but avoid the slow behavior that you’d get from using &lt;code&gt;bundle exec&lt;/code&gt;. So you get a correct environment—check ✔—and speed—check ✔.&lt;/p&gt;

&lt;p&gt;You do have to remember to run, e.g. &lt;code&gt;bin/rspec&lt;/code&gt; instead of &lt;code&gt;bundle exec rspec&lt;/code&gt;. But for that I suggest having your shell do the work for you:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;# Example code for .bashrc

functionBer() {
  if command -v bin/rspec; then
    bin/rspec $*
  else
    bundle exec rspec $*
  fi
}

alias ber=functionBer
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;This creates a &lt;code&gt;ber&lt;/code&gt; alias for running &lt;code&gt;rspec&lt;/code&gt; that will run the command using the binstub if possible, and fall back to bundler if there isn’t one (e.g. maybe you don’t want to have binstubs on all your ruby projects… yet).&lt;/p&gt;

&lt;h2 id=&quot;jruby-has-its-own-built-in-profiler&quot;&gt;jruby has its own built-in profiler&lt;/h2&gt;

&lt;p&gt;You can run JRuby with the &lt;code&gt;--profile&lt;/code&gt;, &lt;code&gt;--profile.graph&lt;/code&gt; or &lt;code&gt;--profile.html&lt;/code&gt; options to get a performance report at the end of the application run.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;$ JRUBY_OPTS=&amp;quot;--profile --dev&amp;quot; pry -e &amp;quot;puts &apos;hello&apos;; exit&amp;quot;
[1] pry(main)&amp;gt; puts &apos;hello&apos;; exit
hello

main profile results:
Total time: 2.11

total   self children calls  method
---------------------------------------------
 1.48   0.02     1.46   894  Kernel.require
 1.23   0.01     1.22  4060  Array#each
 1.00   0.00     1.00     1  Gem::ExecutableHooks.run
 1.00   0.00     0.99   839  Proc#call
 0.95   0.07     0.88    26  Kernel.load
 0.93   0.00     0.93   159  Kernel.require
 0.78   0.00     0.78     1  Noexec#check
 0.78   0.00     0.78     1  Noexec#setup
 0.64   0.08     0.56   151  Kernel.eval
 0.48   0.08     0.40  4840  Class#new
 0.39   0.00     0.39     1  Noexec#candidate?
 0.31   0.01     0.31   158  Gem::Specification.load
...
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;You can also use &lt;code&gt;--profile.api&lt;/code&gt; to get access to an api to selectively turn profiling on and off in certain parts of your code.&lt;/p&gt;

&lt;p&gt;See the &lt;a href=&quot;https://github.com/jruby/jruby/wiki/Profiling-jruby&quot;&gt;JRuby wiki&lt;/a&gt; for more details on these options.&lt;/p&gt;

&lt;h2 id=&quot;getting-some-jruby-magic-in-jconsole&quot;&gt;getting some jruby magic in jconsole&lt;/h2&gt;

&lt;p&gt;By running JRuby with the &lt;code&gt;--manage&lt;/code&gt; option, you’ll enable several JRuby jmx extensions, allowing you to do things such as executing ruby code on a running JRuby instance, or getting a full ruby stack trace for all running ruby threads.&lt;/p&gt;

&lt;p&gt;You can then access them using &lt;a href=&quot;http://openjdk.java.net/tools/svc/jconsole/&quot;&gt;jconsole&lt;/a&gt;, a tool already included with most JDK installs.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;/img/jconsole-ruby.png&quot;&gt;&lt;img src=&quot;/img/jconsole-ruby.png&quot; alt=&quot;Running jconsole with the JRuby --manage option&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2 id=&quot;you-can-also-use-good-olvisualvm&quot;&gt;you can also use good ol’visualvm&lt;/h2&gt;

&lt;p&gt;The &lt;a href=&quot;https://visualvm.java.net/&quot;&gt;VisualVM&lt;/a&gt; tool is also installed by default on most JDK distributions (start it with &lt;code&gt;visualvm&lt;/code&gt; or &lt;code&gt;jvisualvm&lt;/code&gt;) and allows you to inspect a running VM, trigger garbage collection or heap dumps, and analyze cpu and memory consumption both via a profiler and a sampler.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;/img/jvisualvm-ruby.png&quot;&gt;&lt;img src=&quot;/img/jvisualvm-ruby.png&quot; alt=&quot;Inspecting JRuby application with JVisualVM&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Furthermore, if you include &lt;code&gt;-J-Djruby.reify.classes=true&lt;/code&gt; as one of your &lt;code&gt;JRUBY_OPTS&lt;/code&gt; then JRuby will generate a Java class for each ruby class, resulting on this very beautiful result from a sample application using sidekiq:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;/img/jvisualvm-reifyclasses.png&quot;&gt;&lt;img src=&quot;/img/jvisualvm-reifyclasses.png&quot; alt=&quot;Inspecting JRuby heap dymp with reify.classes enabled&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Just… amazing…&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Update, 17th January 2017&lt;/strong&gt;: Note that the &lt;code&gt;reify.classes&lt;/code&gt; option is &lt;a href=&quot;https://github.com/jruby/jruby/issues/4444#issuecomment-273252523&quot;&gt;experimental&lt;/a&gt; so carefully test it before using it in a production environment.&lt;/p&gt;

&lt;h2 id=&quot;thats-all-very-great-old-chap-but-i-deploy-using-heroku&quot;&gt;that’s all very great, old chap, but i deploy using heroku&lt;/h2&gt;

&lt;p&gt;Hey, what a coincidence, I do too. &lt;a href=&quot;/blog/2017/03/19/quickies-heroku-exec-and-jruby-deploy/&quot;&gt;The heroku exec plugin has you covered.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You read that right. You can connect tools such as &lt;code&gt;visualvm&lt;/code&gt; to a running heroku dyno and monitor it. And take heap dumps. And execute ruby snippets. Securely.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;**mindblown**&lt;/code&gt; &lt;code&gt;**manly tears**&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Obviously, with great power comes great responsibility, but every tool is welcome on my toolkit when debugging hard production issues.&lt;/p&gt;

&lt;h2 id=&quot;and-finally-somewhat-related&quot;&gt;and finally, somewhat related&lt;/h2&gt;

&lt;p&gt;Did you know you can deploy &lt;code&gt;.war&lt;/code&gt; files (generated with &lt;code&gt;warbler&lt;/code&gt;) &lt;a href=&quot;https://devcenter.heroku.com/articles/war-deployment&quot;&gt;directly to heroku&lt;/a&gt;?&lt;/p&gt;

&lt;p&gt;And did you know you can deploy docker images to heroku? See the &lt;a href=&quot;https://github.com/heroku/heroku-container-tools&quot;&gt;heroku-container-tools&lt;/a&gt; and &lt;a href=&quot;https://blog.heroku.com/introducing_heroku_docker_release_build_deploy_heroku_apps_with_docker&quot;&gt;documentation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;– I didn’t.&lt;/p&gt;

&lt;p&gt;Until next time!&lt;/p&gt;
</description>
        <pubDate>Sun, 17 Jul 2016 17:36:10 +0100</pubDate>
        <link>https://ivoanjo.me/blog/2016/07/17/another-round-of-jruby-goodness/</link>
        <guid isPermaLink="true">https://ivoanjo.me/blog/2016/07/17/another-round-of-jruby-goodness/</guid>
        <category>blog</category>
      </item>
      <item>
        <title>down the jruby rabbit hole</title>
        <description>&lt;p&gt;So recently at work we finally decided (after some prodding from me) to go with JRuby for a new production system.&lt;/p&gt;

&lt;p&gt;I had no real experience with JRuby other than looking at some documentation and playing with it for five minutes, so here’s some JRuby-related topics I bumped into and I’ve been wanting to write about.&lt;/p&gt;

&lt;h2 id=&quot;start-up-time-during-development&quot;&gt;start-up time during development&lt;/h2&gt;

&lt;p&gt;Since the system hasn’t yet been deployed, I don’t have deployment stories to share, but for development I have some tips:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;export JRUBY_OPTS=&apos;--dev&apos;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;Do define the magic &lt;code&gt;--dev&lt;/code&gt; default option in your local development environment!&lt;/p&gt;

    &lt;p&gt;With this flag active, JRuby optimizes for startup time, so your fast &lt;code&gt;rspec&lt;/code&gt; cycles and &lt;code&gt;pry&lt;/code&gt; usage stops being painful.&lt;/p&gt;

    &lt;p&gt;(Of course, do note that steady-state performance will drop, so don’t use this for long-running code.)&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Use binaries directly (or with &lt;code&gt;jruby -S&lt;/code&gt;) rather than with &lt;code&gt;bundle exec&lt;/code&gt; whenever possible.
On my machine running &lt;code&gt;rspec&lt;/code&gt; or &lt;code&gt;jruby -S rspec&lt;/code&gt; instead of &lt;code&gt;bundle exec rspec&lt;/code&gt; slices start-up time in about half.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These tips are documented in the &lt;a href=&quot;https://github.com/jruby/jruby/wiki/Improving-startup-time&quot;&gt;JRuby wiki&lt;/a&gt; but I can’t stress enough the difference they make between JRuby being painful and a pleasure to use during development.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Edit&lt;/strong&gt;: &lt;a href=&quot;/blog/2016/07/17/another-round-of-jruby-goodness/&quot;&gt;I suggest also looking at the &lt;code&gt;--binstubs&lt;/code&gt; bundler option.&lt;/a&gt;&lt;/p&gt;

&lt;h2 id=&quot;easy-interop-with-java-code&quot;&gt;easy interop with java code&lt;/h2&gt;

&lt;p&gt;Don’t abuse it, but I must say it’s really easy to call Java code:&lt;/p&gt;

&lt;div class=&quot;language-ruby highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;[&lt;span style=&quot;color:#00D&quot;&gt;1&lt;/span&gt;] pry(main)&amp;gt; require &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;java&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;
=&amp;gt; &lt;span style=&quot;color:#069&quot;&gt;false&lt;/span&gt;
[&lt;span style=&quot;color:#00D&quot;&gt;2&lt;/span&gt;] pry(main)&amp;gt; l = java.util.ArrayList.new()
=&amp;gt; &lt;span style=&quot;color:#777&quot;&gt;#&amp;lt;Java::JavaUtil::ArrayList:0x7c24b813&amp;gt;&lt;/span&gt;
[&lt;span style=&quot;color:#00D&quot;&gt;3&lt;/span&gt;] pry(main)&amp;gt; l.add(&lt;span style=&quot;color:#A60&quot;&gt;:foo&lt;/span&gt;)
=&amp;gt; &lt;span style=&quot;color:#069&quot;&gt;true&lt;/span&gt;
[&lt;span style=&quot;color:#00D&quot;&gt;4&lt;/span&gt;] pry(main)&amp;gt; l.add(&lt;span style=&quot;color:#A60&quot;&gt;:bar&lt;/span&gt;)
=&amp;gt; &lt;span style=&quot;color:#069&quot;&gt;true&lt;/span&gt;
[&lt;span style=&quot;color:#00D&quot;&gt;5&lt;/span&gt;] pry(main)&amp;gt; l.to_string
=&amp;gt; &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;[foo, bar]&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;h2 id=&quot;bonus-warbler-and-the-magical-jar&quot;&gt;bonus: warbler and the magical jar&lt;/h2&gt;

&lt;p&gt;While you can use &lt;code&gt;bundler&lt;/code&gt; and many of the same techniques and platforms you are used to with mri (such as the puma webserver), an interesting tool I’ve recently discovered that is also developed by the JRuby team is &lt;a href=&quot;https://github.com/jruby/warbler&quot;&gt;&lt;code&gt;warbler&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Warbler allows you to package a ruby application as a single jar or war file, that can be executed like any other java code standalone or (if applicable) on an application server. If needed, it can even bundle in a Java webserver that will call your ruby code.&lt;/p&gt;

&lt;p&gt;Turning a simple ruby script into an inconspicuous jar is as simple as:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;$ gem install warbler
Fetching: jruby-jars-9.1.2.0.gem (100%)
Successfully installed jruby-jars-9.1.2.0
Fetching: jruby-rack-1.1.20.gem (100%)
Successfully installed jruby-rack-1.1.20
Fetching: rubyzip-1.2.0.gem (100%)
Successfully installed rubyzip-1.2.0
Fetching: warbler-2.0.3.gem (100%)
Successfully installed warbler-2.0.3
Parsing documentation for jruby-jars-9.1.2.0
Installing ri documentation for jruby-jars-9.1.2.0
Parsing documentation for jruby-rack-1.1.20
Installing ri documentation for jruby-rack-1.1.20
Parsing documentation for rubyzip-1.2.0
Installing ri documentation for rubyzip-1.2.0
Parsing documentation for warbler-2.0.3
Installing ri documentation for warbler-2.0.3
Done installing documentation for jruby-jars, jruby-rack, rubyzip, warbler after 1 seconds
4 gems installed

$ cat bin/test.rb
puts &amp;quot;hello, world!&amp;quot;

$ cat config/warble.rb
Warbler::Config.new do |config|
  config.features = %w(executable)
  config.jar_name = &amp;quot;test&amp;quot;
end

$ warble jar
rm -f test.jar
Creating test.jar

$ java -jar test.jar
hello, world!
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;And that’s all there is to it, and you now have a single jar that anyone will be able to easily run on their local machine.&lt;/p&gt;

&lt;p&gt;Big kudos to the JRuby team for this one!&lt;/p&gt;

&lt;h2 id=&quot;dealing-with-java-jar-dependencies&quot;&gt;dealing with java jar dependencies&lt;/h2&gt;

&lt;p&gt;So one of my colleagues asked: what about jars? Do you have to break out &lt;code&gt;maven&lt;/code&gt;? How does that work?&lt;/p&gt;

&lt;p&gt;The answer turns out to be no, you can just use &lt;a href=&quot;https://github.com/mkristian/jbundler&quot;&gt;&lt;code&gt;jbundler&lt;/code&gt;&lt;/a&gt; to do that work for you. It looks and feels like bundler, and you feed it with a &lt;code&gt;Jarfile&lt;/code&gt; and magic happens.&lt;/p&gt;

&lt;p&gt;Of course, approach this with care, as when you start depending on Java code you cannot go back to MRI or other ruby implementations.&lt;/p&gt;

&lt;h2 id=&quot;a-shout-out-to-jrubytruffle&quot;&gt;a shout out to jruby+truffle&lt;/h2&gt;

&lt;p&gt;I’m really looking forward to what I believe is the next big thing in the ruby implementation arena: &lt;strong&gt;JRuby+Truffle&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Its name can be somewhat misleading, as it’s a very different beast from vanilla JRuby. JRuby+Truffle instead uses a self-optimizing AST interpreter that basically teaches the JVM (via the truffle api and the graal compiler) how ruby works and how to optimize its execution.&lt;/p&gt;

&lt;p&gt;The resulting benchmarks are looking very good, although a few sharp edges still stand before it can really be rolled out to production.&lt;/p&gt;

&lt;p&gt;Chris Seaton, its creator, gave an awesome talk about it recently at &lt;a href=&quot;http://soft-dev.org/events/vmss16/&quot;&gt;VMSS16&lt;/a&gt;, which I really recommend watching:&lt;/p&gt;

&lt;iframe width=&quot;80%&quot; height=&quot;315&quot; src=&quot;https://www.youtube.com/embed/b1NTaVQPt1E?si=quwSO5H3ZjstVy_7&quot; title=&quot;YouTube video player&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; referrerpolicy=&quot;strict-origin-when-cross-origin&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;

&lt;p&gt;P.s.: There are a lot of other great talks from that event, such as &lt;a href=&quot;https://www.youtube.com/watch?v=Hqw57GJSrac&amp;amp;list=PLJq3XDLIJkib2h2fObomdFRZrQeJg4UIW&quot;&gt;Cliff Click’s&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;crystal-i-am-disappoint&quot;&gt;crystal, I am disappoint&lt;/h2&gt;

&lt;p&gt;A few months ago I was really getting interested in the &lt;a href=&quot;https://crystal-lang.org/&quot;&gt;Crystal&lt;/a&gt; programming language but after discovering that &lt;a href=&quot;https://github.com/crystal-lang/crystal/issues/1967&quot;&gt;it doesn’t have multi-threading&lt;/a&gt; it became kind-of meh.&lt;/p&gt;

&lt;p&gt;As a shared-memory concurrency junkie, it really seems weird to have a new language being created that doesn’t properly consider concurrency. Hopefully in the future this will be fixed, but until then, it seems like JRuby and Elixir are where the parallel party’s at!&lt;/p&gt;
</description>
        <pubDate>Sat, 16 Jul 2016 22:24:51 +0100</pubDate>
        <link>https://ivoanjo.me/blog/2016/07/16/down-the-jruby-rabbit-hole/</link>
        <guid isPermaLink="true">https://ivoanjo.me/blog/2016/07/16/down-the-jruby-rabbit-hole/</guid>
        <category>blog</category>
      </item>
      <item>
        <title>did_you_know.ruby?</title>
        <description>&lt;p&gt;Yesterday I did a small presentation on some awesome ruby tricks and tools, touching a bit on&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;why and when to use keyword arguments&lt;/li&gt;
  &lt;li&gt;splat and double splat&lt;/li&gt;
  &lt;li&gt;rspec’s verified doubles&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;rspec --bisect&lt;/code&gt; and random spec ordering&lt;/li&gt;
  &lt;li&gt;pry&lt;/li&gt;
  &lt;li&gt;ruby 2.3 &lt;code&gt;dig&lt;/code&gt; and safe navigation&lt;/li&gt;
  &lt;li&gt;ruby threading and implementations&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;as part of &lt;a href=&quot;https://github.com/talkdesk&quot;&gt;talkdesk&lt;/a&gt;’s TGIF engineering presentations.&lt;/p&gt;

&lt;p&gt;Nothing groundbreaking, but still interesting, I’d say ;)&lt;/p&gt;

&lt;p&gt;You can find the slides below:&lt;/p&gt;

&lt;iframe src=&quot;//slides.com/ianjo/did_you_know_ruby/embed?style=light&quot; width=&quot;576&quot; height=&quot;420&quot; scrolling=&quot;no&quot; frameborder=&quot;0&quot; webkitallowfullscreen=&quot;&quot; mozallowfullscreen=&quot;&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
</description>
        <pubDate>Sat, 14 May 2016 17:16:00 +0100</pubDate>
        <link>https://ivoanjo.me/blog/2016/05/14/did-you-know-ruby/</link>
        <guid isPermaLink="true">https://ivoanjo.me/blog/2016/05/14/did-you-know-ruby/</guid>
        <category>blog</category>
      </item>
      <item>
        <title>asciinema: shell recording done right!</title>
        <description>&lt;!--
Hello there!

On my last post I embedded a screencast which was a real shell recording, not just a video recording of a shell.

That got me curious about the service used, and my quest led me to &lt;https://asciinema.org&gt;! It&apos;s a really neat tool for making screencasts like this one in no time at all :)

So there you go. See you next time!
--&gt;

&lt;script type=&quot;text/javascript&quot; src=&quot;https://asciinema.org/a/31006.js&quot; id=&quot;asciicast-31006&quot; data-autoplay=&quot;1&quot; data-loop=&quot;1&quot; data-t=&quot;16&quot; data-size=&quot;small&quot; async=&quot;&quot;&gt;&lt;/script&gt;

</description>
        <pubDate>Tue, 01 Dec 2015 22:19:07 +0000</pubDate>
        <link>https://ivoanjo.me/blog/2015/12/01/asciinema-shell-recording-done-right/</link>
        <guid isPermaLink="true">https://ivoanjo.me/blog/2015/12/01/asciinema-shell-recording-done-right/</guid>
        <category>blog</category>
      </item>
      <item>
        <title>Whoa! Java has a REPL now!</title>
        <description>&lt;p&gt;As part of my weekend reading I just discovered that an official REPL is planned for Java 9!&lt;/p&gt;

&lt;p&gt;It’s spec’d in &lt;a href=&quot;http://openjdk.java.net/jeps/222&quot;&gt;JEP 222&lt;/a&gt;, and there’s a very neat demo by &lt;a href=&quot;http://blog.takipi.com/java-9-early-access-a-hands-on-session-with-jshell-the-java-repl/&quot;&gt;Alex Zhitnitsky&lt;/a&gt;:&lt;/p&gt;

&lt;script type=&quot;text/javascript&quot; src=&quot;https://asciinema.org/a/23030.js&quot; id=&quot;asciicast-23030&quot; async=&quot;&quot;&gt;&lt;/script&gt;

&lt;p&gt;Even better, there’s even a &lt;a href=&quot;https://hub.docker.com/r/ensignprojects/javarepl/&quot;&gt;docker image&lt;/a&gt; for testing it. Just run&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;$ docker run -it ensignprojects/javarepl
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;And before long you’ll be staring at the new jshell REPL!&lt;/p&gt;
</description>
        <pubDate>Sat, 28 Nov 2015 22:32:59 +0000</pubDate>
        <link>https://ivoanjo.me/blog/2015/11/28/whoa-java-has-a-repl-now/</link>
        <guid isPermaLink="true">https://ivoanjo.me/blog/2015/11/28/whoa-java-has-a-repl-now/</guid>
        <category>blog</category>
      </item>
      <item>
        <title>Ruby meets weak memory models</title>
        <description>&lt;p&gt;I just finished watching a very interesting presentation from RubyConf 2015 entitled &lt;em&gt;“&lt;a href=&quot;https://www.youtube.com/watch?v=r5kwIm3Q6Y0&quot;&gt;Writing concurrent libraries for all Ruby runtimes&lt;/a&gt;”&lt;/em&gt; by Petr Chalupa.&lt;/p&gt;

&lt;p&gt;This presentation explores the challenges of implementing a Future in ruby VMs that offer true concurrency, such as JRuby and Rubinius, and how the &lt;a href=&quot;https://github.com/ruby-concurrency/concurrent-ruby&quot;&gt;concurrent-ruby&lt;/a&gt; gem can make your life easier in this point.&lt;/p&gt;

&lt;p&gt;If you’re interested in low-level concurrency and what happens to ruby code when run under these alternative VMs, it’s a great watch, even if the speaker &lt;em&gt;can&lt;/em&gt; be slightly monotone at times ;) ;) ;)&lt;/p&gt;

&lt;iframe width=&quot;736&quot; height=&quot;420&quot; src=&quot;https://www.youtube-nocookie.com/embed/r5kwIm3Q6Y0?rel=0&quot; title=&quot;YouTube video player&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; referrerpolicy=&quot;strict-origin-when-cross-origin&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
</description>
        <pubDate>Sat, 28 Nov 2015 20:14:23 +0000</pubDate>
        <link>https://ivoanjo.me/blog/2015/11/28/ruby-meets-weak-memory-models/</link>
        <guid isPermaLink="true">https://ivoanjo.me/blog/2015/11/28/ruby-meets-weak-memory-models/</guid>
        <category>blog</category>
      </item>
      <item>
        <title>Ruby features i&apos;m looking forward to</title>
        <description>&lt;p&gt;I’ve been exploring what’s next for ruby, and now that &lt;a href=&quot;https://www.ruby-lang.org/en/news/2015/11/11/ruby-2-3-0-preview1-released/&quot;&gt;ruby 2.3.0-preview1&lt;/a&gt; is out, here’s a quick look at what caught my eye.&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;$ ruby --version
ruby 2.3.0dev (2015-11-11 trunk 52540) [x86_64-linux]
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;h2 id=&quot;the-safe-navigation--operator&quot;&gt;the “safe navigation” &amp;amp; operator&lt;/h2&gt;

&lt;p&gt;The &lt;a href=&quot;https://bugs.ruby-lang.org/issues/11537&quot;&gt;safe navigation operator&lt;/a&gt; was inspired by groovy, and allows you to simplify code such as&lt;/p&gt;

&lt;div class=&quot;language-ruby highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;zoo = &lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;Zoo&lt;/span&gt;.new
zoo &amp;amp;&amp;amp; zoo.animals &amp;amp;&amp;amp; zoo.animals.first
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;into&lt;/p&gt;

&lt;div class=&quot;language-ruby highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;zoo&amp;amp;.animals&amp;amp;.first
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;If any of the return values in the “chain” are &lt;code&gt;nil&lt;/code&gt;, then &lt;code&gt;nil&lt;/code&gt; is returned, otherwise, ruby continues sending the next message.&lt;/p&gt;

&lt;p&gt;Simple, and to the point. I like it!&lt;/p&gt;

&lt;p&gt;Note that the safe navigation it does not interact with &lt;code&gt;[]&lt;/code&gt; syntax sugar, for instance when indexing an hash:&lt;/p&gt;

&lt;div class=&quot;language-ruby highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;values&amp;amp;.[&lt;span style=&quot;color:#A60&quot;&gt;:foo&lt;/span&gt;] &lt;span style=&quot;color:#777&quot;&gt;# error&lt;/span&gt;
&lt;span style=&quot;color:#606&quot;&gt;SyntaxError&lt;/span&gt;: unexpected &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;, expecting &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;
values&amp;amp;.[&lt;span style=&quot;color:#A60&quot;&gt;:foo&lt;/span&gt;]
         ^
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;You’ll have to unsugar the method call:&lt;/p&gt;

&lt;div class=&quot;language-ruby highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;values&amp;amp;.[](&lt;span style=&quot;color:#A60&quot;&gt;:foo&lt;/span&gt;) &lt;span style=&quot;color:#777&quot;&gt;# works&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;h2 id=&quot;frozen-string-literals&quot;&gt;frozen string literals&lt;/h2&gt;

&lt;p&gt;In ruby 3.0, the plan is for strings to be &lt;a href=&quot;https://bugs.ruby-lang.org/issues/11473&quot;&gt;immutable by default&lt;/a&gt;. The first step towards that path is a command-line option that optionally enables that behavior for ruby 2.3:&lt;/p&gt;

&lt;div class=&quot;language-ruby highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;hello = &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;hello world&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
hello[&lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;world&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;] = &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;ruby&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;
puts hello
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Running the example:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;$ ruby immutable.rb
hello ruby

$ ruby --enable=frozen-string-literal immutable.rb
immutable.rb:2:in `[]=&apos;: can&apos;t modify frozen String (RuntimeError)
        from immutable.rb:2:in `&amp;lt;main&amp;gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Immutable strings have a number of concurrency and efficiency advantages, and are the standard in many other programming languages (such as Java), so it’s nice to see them make an appearance in ruby.&lt;/p&gt;

&lt;h2 id=&quot;did_you_mean-enabled-by-default&quot;&gt;did_you_mean enabled by default&lt;/h2&gt;

&lt;p&gt;The &lt;a href=&quot;https://github.com/yuki24/did_you_mean&quot;&gt;did_you_mean&lt;/a&gt; gem is now bundled and should be enabled by default. It did not load for me, but after a manual installation I was greeted with success:&lt;/p&gt;

&lt;div class=&quot;language-ruby highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;class&lt;/span&gt; &lt;span style=&quot;color:#B06;font-weight:bold&quot;&gt;Zoo&lt;/span&gt;
  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color:#06B;font-weight:bold&quot;&gt;animals&lt;/span&gt;
    [&lt;span style=&quot;color:#A60&quot;&gt;:penguin&lt;/span&gt;, &lt;span style=&quot;color:#A60&quot;&gt;:lion&lt;/span&gt;]
  &lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;end&lt;/span&gt;
&lt;span style=&quot;color:#080;font-weight:bold&quot;&gt;end&lt;/span&gt;

&lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;Zoo&lt;/span&gt;.new.animalZ
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Running the example:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;$ ruby zoo.rb
zoo.rb:7:in `&amp;lt;main&amp;gt;&apos;: undefined method `animalZ&apos; for #&amp;lt;Zoo:0x00000000c97a70&amp;gt; (NoMethodError)

    Did you mean? animals
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;It’s a very minor addition, but it’s one of those small niceties that can draw a smile during your daily ruby adventures.&lt;/p&gt;

&lt;h2 id=&quot;hash-comparison&quot;&gt;hash comparison&lt;/h2&gt;

&lt;p&gt;In previous ruby versions, you could check if two hashes were the same:&lt;/p&gt;

&lt;div class=&quot;language-ruby highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;{&lt;span style=&quot;color:#606&quot;&gt;lions&lt;/span&gt;: &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;enough&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;, &lt;span style=&quot;color:#606&quot;&gt;penguins&lt;/span&gt;: &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;lots&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;} ==
  {&lt;span style=&quot;color:#606&quot;&gt;lions&lt;/span&gt;: &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;enough&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;, &lt;span style=&quot;color:#606&quot;&gt;penguins&lt;/span&gt;: &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;lots&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;}
=&amp;gt; &lt;span style=&quot;color:#069&quot;&gt;true&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;But what if you wanted to check if a hash contained another? Well, previously you’d have to convert them into sets:&lt;/p&gt;

&lt;div class=&quot;language-ruby highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;Set&lt;/span&gt;.new({&lt;span style=&quot;color:#606&quot;&gt;lions&lt;/span&gt;: &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;enough&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;, &lt;span style=&quot;color:#606&quot;&gt;penguins&lt;/span&gt;: &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;lots&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;}) &amp;gt;
  &lt;span style=&quot;color:#036;font-weight:bold&quot;&gt;Set&lt;/span&gt;.new({&lt;span style=&quot;color:#606&quot;&gt;lions&lt;/span&gt;: &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;enough&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;})
=&amp;gt; &lt;span style=&quot;color:#069&quot;&gt;true&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;In ruby 2.3 you’ll be able to compare sets directly:&lt;/p&gt;

&lt;div class=&quot;language-ruby highlighter-coderay&quot;&gt;&lt;div class=&quot;CodeRay&quot;&gt;
  &lt;div class=&quot;code&quot;&gt;&lt;pre&gt;{&lt;span style=&quot;color:#606&quot;&gt;lions&lt;/span&gt;: &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;enough&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;, &lt;span style=&quot;color:#606&quot;&gt;penguins&lt;/span&gt;: &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;lots&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;} &amp;gt; {&lt;span style=&quot;color:#606&quot;&gt;lions&lt;/span&gt;: &lt;span style=&quot;background-color:hsla(0,100%,50%,0.05)&quot;&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;span style=&quot;color:#D20&quot;&gt;enough&lt;/span&gt;&lt;span style=&quot;color:#710&quot;&gt;&apos;&lt;/span&gt;&lt;/span&gt;}
=&amp;gt; &lt;span style=&quot;color:#069&quot;&gt;true&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Marvelous!&lt;/p&gt;

&lt;p&gt;Thanks to &lt;a href=&quot;http://olivierlacan.com/posts/hash-comparison-in-ruby-2-3/&quot;&gt;Oliver Lacan&lt;/a&gt; for his awesome writeup of the feature.&lt;/p&gt;

&lt;h2 id=&quot;looking-ahead-goodbye-to-the-gil&quot;&gt;looking ahead: goodbye to the GIL&lt;/h2&gt;

&lt;p&gt;MRI, the default ruby implementation, employs a lock called the &lt;em&gt;global interpreter lock&lt;/em&gt; – GIL to her friends. This lock protects each executing ruby thread so that at any given moment only one thread is allowed to be executing ruby code.&lt;/p&gt;

&lt;p&gt;This lock allows a number of simplifications and optimizations in the way the ruby internals are implemented, but is increasingly outdated given how even phones will soon have &lt;a href=&quot;http://heliox20.com/&quot;&gt;10-core cpus&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The lack of real multi-threading has made ruby greatly lag behind other languages, and I’m really interested in seeing the ruby ecosystem successfully transition to a GIL-less model.&lt;/p&gt;

&lt;blockquote class=&quot;twitter-tweet&quot; lang=&quot;en&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;My vague plan for Ruby GIL is 1) add more abstract concurrency e.g. actors 2) add warning when using threads directly 3) then remove GIL&lt;/p&gt;&amp;mdash; Yukihiro Matsumoto (@yukihiro_matz) &lt;a href=&quot;https://twitter.com/yukihiro_matz/status/495219763883163648&quot;&gt;August 1, 2014&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async=&quot;&quot; src=&quot;//platform.twitter.com/widgets.js&quot; charset=&quot;utf-8&quot;&gt;&lt;/script&gt;
&lt;p /&gt;

&lt;p&gt;To tackle this, Matz and the ruby team have been working for some time to remove the GIL, and, beyond that, to offer powerful and easy-to-use tools for multi-threaded programming.&lt;/p&gt;

&lt;p&gt;One such proposal is the stream operator, &lt;code&gt;|&amp;gt;&lt;/code&gt;, that allows multiple components to be joined in a pipeline. It’s still under heavy work, but if you’re interested, you can check out the &lt;a href=&quot;https://github.com/matz/streem&quot;&gt;current implementation&lt;/a&gt; and Matz’s &lt;a href=&quot;https://www.youtube.com/watch?v=48iKjUcENRE&quot;&gt;recent presentation on ruby 3.0&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;on-the-next-episode&quot;&gt;on the next episode!&lt;/h2&gt;

&lt;p&gt;I recently discovered the &lt;a href=&quot;http://crystal-lang.org/&quot;&gt;crystal programming language&lt;/a&gt;, a ruby-inspired language that tries to keep ruby’s awesomeness, but make it compilable down to very efficient machine code.&lt;/p&gt;

&lt;p&gt;I’ve been itching to take it for a spin, so maybe next time!&lt;/p&gt;
</description>
        <pubDate>Fri, 13 Nov 2015 00:03:33 +0000</pubDate>
        <link>https://ivoanjo.me/blog/2015/11/13/ruby-features-im-looking-forward-to/</link>
        <guid isPermaLink="true">https://ivoanjo.me/blog/2015/11/13/ruby-features-im-looking-forward-to/</guid>
        <category>blog</category>
      </item>
      <item>
        <title>starting a new blog</title>
        <description>&lt;p&gt;I haven’t really blogged in a big while, and my &lt;a href=&quot;https://knuxblog.blogspot.pt&quot;&gt;old blog at blogspot&lt;/a&gt; seems to be more and more boring to maintain, so I finally decided to put jekyll to work and added a blog to &lt;a href=&quot;/&quot;&gt;ivoanjo.me&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I’m currently exploring Ruby and other programming languages, so my plan is to document some of my cooler findings for the larger internets.&lt;/p&gt;

&lt;p&gt;Thank you and have an awesome day!&lt;/p&gt;

</description>
        <pubDate>Tue, 03 Nov 2015 21:58:49 +0000</pubDate>
        <link>https://ivoanjo.me/blog/2015/11/03/starting-a-new-blog/</link>
        <guid isPermaLink="true">https://ivoanjo.me/blog/2015/11/03/starting-a-new-blog/</guid>
        <category>blog</category>
      </item>
  </channel>
</rss>
