<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">

  <title><![CDATA[Jiajun Yao]]></title>
  <link href="http://blog.jjyao.me/atom.xml" rel="self"/>
  <link href="http://blog.jjyao.me/"/>
  <updated>2026-05-12T06:35:46-07:00</updated>
  <id>http://blog.jjyao.me/</id>
  <author>
    <name><![CDATA[jjyao]]></name>
    
  </author>
  <generator uri="http://octopress.org/">Octopress</generator>

  
  <entry>
    <title type="html"><![CDATA[Python Exception Reference Cycle]]></title>
    <link href="http://blog.jjyao.me/blog/2026/05/11/python-exception-reference-cycle/"/>
    <updated>2026-05-11T20:59:07-07:00</updated>
    <id>http://blog.jjyao.me/blog/2026/05/11/python-exception-reference-cycle</id>
    <content type="html"><![CDATA[<p>This post talks about Python exception reference cycles: what they are, why they can be problematic and how to avoid them.</p>

<!-- more -->


<h2>What are Python exception reference cycles</h2>

<p>A Python exception has a reference cycle when it has a reference chain back to itself (i.e. &ldquo;exc -> &hellip; -> exc&rdquo;). The following code shows an example of the cycle:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'><span class="k">def</span> <span class="nf">inner</span><span class="p">():</span>
</span><span class='line'>    <span class="n">exc</span> <span class="o">=</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s">&quot;&quot;</span><span class="p">)</span>
</span><span class='line'>    <span class="k">raise</span> <span class="n">exc</span>
</span><span class='line'>
</span><span class='line'><span class="k">try</span><span class="p">:</span>
</span><span class='line'>  <span class="n">inner</span><span class="p">()</span>
</span><span class='line'><span class="k">except</span> <span class="ne">Exception</span> <span class="k">as</span> <span class="n">exc</span><span class="p">:</span>
</span><span class='line'>  <span class="k">assert</span> <span class="n">exc</span><span class="o">.</span><span class="n">__traceback__</span><span class="o">.</span><span class="n">tb_next</span><span class="o">.</span><span class="n">tb_frame</span><span class="o">.</span><span class="n">f_locals</span><span class="p">[</span><span class="s">&#39;exc&#39;</span><span class="p">]</span> <span class="ow">is</span> <span class="n">exc</span>
</span><span class='line'>  <span class="k">print</span><span class="p">(</span><span class="s">&quot;Found Python exception reference cycle!&quot;</span><span class="p">)</span>
</span></code></pre></td></tr></table></div></figure>


<h2>Why are Python exception reference cycles bad</h2>

<p>To understand why Python exception reference cycles are bad, we need to understand some behaviors of Python GC and Python exceptions.</p>

<h3>Python GC</h3>

<p>Python has two ways to find objects to deallocate: reference counting finds objects whose ref counts are zero and the garbage collector finds objects with circular references. For exceptions with reference cycles, only the garbage collector can deallocate them.</p>

<p>Unless manually triggered by <code>gc.collect()</code>, Python GC runs every <a href="https://docs.python.org/3/library/gc.html#gc.set_threshold">X (allocations - deallocations)</a>. Unlike other languages, it&rsquo;s not triggered under memory pressure so it&rsquo;s purely count based. The implication is that a program can hold lots of memory in a few large objects with reference cycles and doesn&rsquo;t trigger GC because the count threshold isn&rsquo;t reached. In the worst case, the program can OOM.</p>

<h3>Python exceptions</h3>

<p>Unlike many other languages, a raised Python exception has references to all frames of the call stack from main all the way to where the exception is raised, and each frame has references to all local variables. As a result, a Python exception can keep lots of objects alive (i.e. prevent ref counts from going down to zero).</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'><span class="k">def</span> <span class="nf">inner</span><span class="p">():</span>
</span><span class='line'>  <span class="n">big</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">*</span> <span class="mi">1024</span> <span class="o">*</span> <span class="mi">1024</span>
</span><span class='line'>  <span class="n">exc</span> <span class="o">=</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s">&quot;&quot;</span><span class="p">)</span>
</span><span class='line'>  <span class="k">raise</span> <span class="n">exc</span>
</span><span class='line'>
</span><span class='line'><span class="k">def</span> <span class="nf">outer</span><span class="p">():</span>
</span><span class='line'>  <span class="n">large</span> <span class="o">=</span> <span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">*</span> <span class="mi">1024</span> <span class="o">*</span> <span class="mi">1024</span>
</span><span class='line'>  <span class="k">try</span><span class="p">:</span>
</span><span class='line'>    <span class="n">inner</span><span class="p">()</span>
</span><span class='line'>  <span class="k">except</span> <span class="ne">Exception</span> <span class="k">as</span> <span class="n">exc</span><span class="p">:</span>
</span><span class='line'>    <span class="k">assert</span> <span class="n">exc</span><span class="o">.</span><span class="n">__traceback__</span><span class="o">.</span><span class="n">tb_next</span><span class="o">.</span><span class="n">tb_frame</span><span class="o">.</span><span class="n">f_locals</span><span class="p">[</span><span class="s">&#39;big&#39;</span><span class="p">]</span> <span class="o">==</span> <span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">*</span> <span class="mi">1024</span> <span class="o">*</span> <span class="mi">1024</span>
</span><span class='line'>    <span class="k">assert</span> <span class="n">exc</span><span class="o">.</span><span class="n">__traceback__</span><span class="o">.</span><span class="n">tb_frame</span><span class="o">.</span><span class="n">f_locals</span><span class="p">[</span><span class="s">&#39;large&#39;</span><span class="p">]</span> <span class="o">==</span> <span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">*</span> <span class="mi">1024</span> <span class="o">*</span> <span class="mi">1024</span>
</span><span class='line'>    <span class="k">assert</span> <span class="n">exc</span><span class="o">.</span><span class="n">__traceback__</span><span class="o">.</span><span class="n">tb_frame</span><span class="o">.</span><span class="n">f_back</span><span class="o">.</span><span class="n">f_locals</span><span class="p">[</span><span class="s">&#39;huge&#39;</span><span class="p">]</span> <span class="o">==</span> <span class="p">[</span><span class="mi">3</span><span class="p">]</span> <span class="o">*</span> <span class="mi">1024</span> <span class="o">*</span> <span class="mi">1024</span>
</span><span class='line'>    <span class="k">print</span><span class="p">(</span><span class="s">&quot;Exception has reference to big, large and huge objects!&quot;</span><span class="p">)</span>
</span><span class='line'>
</span><span class='line'><span class="n">huge</span> <span class="o">=</span> <span class="p">[</span><span class="mi">3</span><span class="p">]</span> <span class="o">*</span> <span class="mi">1024</span> <span class="o">*</span> <span class="mi">1024</span>
</span><span class='line'><span class="n">outer</span><span class="p">()</span>
</span></code></pre></td></tr></table></div></figure>


<p>The net effect is that an exception with a reference cycle can hold lots of objects alive until the next GC happens which can be greatly delayed and the program may just OOM or run out of resources (e.g. open files) before that.</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'><span class="kn">import</span> <span class="nn">gc</span>
</span><span class='line'>
</span><span class='line'><span class="k">class</span> <span class="nc">Giant</span><span class="p">:</span>
</span><span class='line'>  <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
</span><span class='line'>    <span class="bp">self</span><span class="o">.</span><span class="n">data</span> <span class="o">=</span> <span class="p">[</span><span class="mi">4</span><span class="p">]</span> <span class="o">*</span> <span class="mi">1024</span> <span class="o">*</span> <span class="mi">1024</span>
</span><span class='line'>
</span><span class='line'>  <span class="k">def</span> <span class="nf">__del__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
</span><span class='line'>    <span class="k">print</span><span class="p">(</span><span class="s">&quot;Giant __del__ is called&quot;</span><span class="p">)</span>
</span><span class='line'>
</span><span class='line'><span class="k">def</span> <span class="nf">inner</span><span class="p">():</span>
</span><span class='line'>  <span class="n">exc</span> <span class="o">=</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s">&quot;&quot;</span><span class="p">)</span>
</span><span class='line'>  <span class="k">raise</span> <span class="n">exc</span>
</span><span class='line'>
</span><span class='line'><span class="k">def</span> <span class="nf">outer</span><span class="p">():</span>
</span><span class='line'>  <span class="n">giant</span> <span class="o">=</span> <span class="n">Giant</span><span class="p">()</span>
</span><span class='line'>  <span class="k">try</span><span class="p">:</span>
</span><span class='line'>    <span class="n">inner</span><span class="p">()</span>
</span><span class='line'>  <span class="k">except</span> <span class="ne">Exception</span><span class="p">:</span>
</span><span class='line'>    <span class="k">pass</span>
</span><span class='line'>
</span><span class='line'><span class="n">outer</span><span class="p">()</span>
</span><span class='line'><span class="k">print</span><span class="p">(</span><span class="s">&quot;Calling GC&quot;</span><span class="p">)</span>
</span><span class='line'><span class="n">gc</span><span class="o">.</span><span class="n">collect</span><span class="p">()</span>
</span></code></pre></td></tr></table></div></figure>


<p>If you run the above program, you will get</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'><span class="n">Calling</span> <span class="n">GC</span>
</span><span class='line'><span class="n">Giant</span> <span class="n">__del__</span> <span class="ow">is</span> <span class="n">called</span>
</span></code></pre></td></tr></table></div></figure>


<p>and this shows that we now rely on GC to deallocate the Giant object which is undesirable.</p>

<h2>How to avoid Python exception reference cycles</h2>

<p>It turns out the issue we described above is well known to the Python developers and there is a <a href="https://peps.python.org/pep-3110/">PEP</a> that&rsquo;s implemented to help us break the exception reference cycle. Basically we should avoid having local variables point to the exception. In our example, we can do the following to break the reference cycle:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'><span class="k">def</span> <span class="nf">inner</span><span class="p">():</span> <span class="c"># BAD, has cycle</span>
</span><span class='line'>  <span class="n">exc</span> <span class="o">=</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s">&quot;&quot;</span><span class="p">)</span>
</span><span class='line'>  <span class="k">raise</span> <span class="n">exc</span>
</span><span class='line'>
</span><span class='line'><span class="k">def</span> <span class="nf">inner</span><span class="p">():</span> <span class="c"># GOOD, no cycle</span>
</span><span class='line'>  <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s">&quot;&quot;</span><span class="p">)</span>
</span><span class='line'>
</span><span class='line'><span class="k">def</span> <span class="nf">inner</span><span class="p">():</span> <span class="c"># GOOD, no cycle</span>
</span><span class='line'>  <span class="n">exc</span> <span class="o">=</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s">&quot;&quot;</span><span class="p">)</span>
</span><span class='line'>  <span class="k">try</span><span class="p">:</span>
</span><span class='line'>    <span class="k">raise</span> <span class="n">exc</span>
</span><span class='line'>  <span class="k">finally</span><span class="p">:</span>
</span><span class='line'>    <span class="k">del</span> <span class="n">exc</span>
</span></code></pre></td></tr></table></div></figure>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Demystify Smaps]]></title>
    <link href="http://blog.jjyao.me/blog/2025/12/14/demystify-smaps/"/>
    <updated>2025-12-14T22:19:03-08:00</updated>
    <id>http://blog.jjyao.me/blog/2025/12/14/demystify-smaps</id>
    <content type="html"><![CDATA[<p>This post demystifies the Linux <code>/proc/&lt;pid&gt;/smaps</code> file and its <code>Shared_Clean</code>, <code>Shared_Dirty</code>, <code>Private_Clean</code> and <code>Private_Dirty</code> fields.</p>

<!-- more -->


<h2>What is smaps</h2>

<p>The smaps file in Linux provides detailed information for each of the process&rsquo;s VMAs (Virtual Memory Areas), represented by <a href="https://github.com/torvalds/linux/blob/v5.15/include/linux/mm_types.h#L319">struct vm_area_struct</a>. The content of smaps file of a process is constructed by <a href="https://github.com/torvalds/linux/blob/v5.15/fs/proc/task_mmu.c#L955">iterating</a> through each VMA and calling <a href="https://github.com/torvalds/linux/blob/v5.15/fs/proc/task_mmu.c#L811">show_smap</a>. The <code>Shared_Clean</code>, <code>Shared_Dirty</code>, <code>Private_Clean</code> and <code>Private_Dirty</code> fields are printed <a href="https://github.com/torvalds/linux/blob/v5.15/fs/proc/task_mmu.c#L790">here</a> and calculated <a href="https://github.com/torvalds/linux/blob/v5.15/fs/proc/task_mmu.c#L403">here</a>.</p>

<h2>Shared vs Private</h2>

<p>From the perspective of smaps, whether a page is considered shared or private is determined by its <a href="https://github.com/torvalds/linux/blob/v5.15/fs/proc/task_mmu.c#L467C18-L467C31">page_mapcount</a> which is basically <a href="https://github.com/torvalds/linux/blob/v5.15/include/linux/mm.h#L877">page->_mapcount</a> NOT by the <code>MAP_SHARED</code> or <code>MAP_PRIVATE</code> flags used in <a href="https://man7.org/linux/man-pages/man2/mmap.2.html">mmap</a>. <a href="https://github.com/torvalds/linux/blob/v5.15/include/linux/mm_types.h#L201">_mapcount</a> of a page is a counter tracks how many page table entries (PTEs) point to this physical page across ALL processes. A page is considered shared if there are at least 2 PTEs point to it.</p>

<p>Let&rsquo;s verify this with different cases:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'>dd <span class="k">if</span><span class="o">=</span>/dev/zero <span class="nv">of</span><span class="o">=</span>/tmp/smaps  <span class="nv">bs</span><span class="o">=</span>1M <span class="nv">count</span><span class="o">=</span>1024
</span></code></pre></td></tr></table></div></figure>




<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
<span class='line-number'>32</span>
<span class='line-number'>33</span>
<span class='line-number'>34</span>
<span class='line-number'>35</span>
<span class='line-number'>36</span>
<span class='line-number'>37</span>
<span class='line-number'>38</span>
<span class='line-number'>39</span>
<span class='line-number'>40</span>
</pre></td><td class='code'><pre><code class='cpp'><span class='line'><span class="cp">#include &lt;stdio.h&gt;</span>
</span><span class='line'><span class="cp">#include &lt;stdlib.h&gt;</span>
</span><span class='line'><span class="cp">#include &lt;sys/mman.h&gt;</span>
</span><span class='line'><span class="cp">#include &lt;sys/stat.h&gt;</span>
</span><span class='line'><span class="cp">#include &lt;fcntl.h&gt;</span>
</span><span class='line'><span class="cp">#include &lt;unistd.h&gt;</span>
</span><span class='line'><span class="cp">#include &lt;string.h&gt;</span>
</span><span class='line'>
</span><span class='line'><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> <span class="p">{</span>
</span><span class='line'>  <span class="kt">int</span> <span class="n">fd</span> <span class="o">=</span> <span class="n">open</span><span class="p">(</span><span class="s">&quot;/tmp/smaps&quot;</span><span class="p">,</span> <span class="n">O_RDWR</span><span class="p">);</span>
</span><span class='line'>  <span class="k">if</span> <span class="p">(</span><span class="n">fd</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>    <span class="n">perror</span><span class="p">(</span><span class="s">&quot;Failed to open&quot;</span><span class="p">);</span>
</span><span class='line'>    <span class="n">exit</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span>
</span><span class='line'>  <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>  <span class="k">const</span> <span class="kt">int</span> <span class="n">num_mmaps</span> <span class="o">=</span> <span class="n">atoi</span><span class="p">(</span><span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">]);</span>
</span><span class='line'>  <span class="k">const</span> <span class="kt">bool</span> <span class="n">map_shared</span> <span class="o">=</span> <span class="n">strcmp</span><span class="p">(</span><span class="n">argv</span><span class="p">[</span><span class="mi">2</span><span class="p">],</span> <span class="s">&quot;MAP_SHARED&quot;</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">;</span>
</span><span class='line'>  <span class="k">const</span> <span class="kt">bool</span> <span class="n">map_populate</span> <span class="o">=</span> <span class="n">strcmp</span><span class="p">(</span><span class="n">argv</span><span class="p">[</span><span class="mi">3</span><span class="p">],</span> <span class="s">&quot;MAP_POPULATE&quot;</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">;</span>
</span><span class='line'>  <span class="n">printf</span><span class="p">(</span><span class="s">&quot;Command line args: num_mmaps=%d, map_shared=%d, map_populate=%d</span><span class="se">\n</span><span class="s">&quot;</span><span class="p">,</span>
</span><span class='line'>         <span class="n">num_mmaps</span><span class="p">,</span> <span class="n">map_shared</span><span class="p">,</span> <span class="n">map_populate</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'>  <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">num_mmaps</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>    <span class="kt">void</span> <span class="o">*</span><span class="n">map</span> <span class="o">=</span> <span class="n">mmap</span><span class="p">(</span><span class="nb">NULL</span><span class="p">,</span> <span class="mi">512</span> <span class="o">*</span> <span class="mi">1024</span> <span class="o">*</span> <span class="mi">1024</span><span class="p">,</span> <span class="n">PROT_READ</span> <span class="o">|</span> <span class="n">PROT_WRITE</span><span class="p">,</span>
</span><span class='line'>                     <span class="p">(</span><span class="n">map_shared</span> <span class="o">?</span> <span class="nl">MAP_SHARED</span> <span class="p">:</span> <span class="n">MAP_PRIVATE</span><span class="p">)</span> <span class="o">|</span> <span class="p">(</span><span class="n">map_populate</span> <span class="o">?</span> <span class="nl">MAP_POPULATE</span> <span class="p">:</span> <span class="mi">0</span><span class="p">),</span>
</span><span class='line'>                     <span class="n">fd</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'>    <span class="k">if</span> <span class="p">(</span><span class="n">map</span> <span class="o">==</span> <span class="n">MAP_FAILED</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>      <span class="n">perror</span><span class="p">(</span><span class="s">&quot;Failed to mmap&quot;</span><span class="p">);</span>
</span><span class='line'>      <span class="n">close</span><span class="p">(</span><span class="n">fd</span><span class="p">);</span>
</span><span class='line'>      <span class="n">exit</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>    <span class="kt">int</span> <span class="o">*</span><span class="n">data</span> <span class="o">=</span> <span class="p">(</span><span class="kt">int</span><span class="o">*</span><span class="p">)</span> <span class="n">map</span><span class="p">;</span>
</span><span class='line'>    <span class="n">printf</span><span class="p">(</span><span class="s">&quot;data = %d</span><span class="se">\n</span><span class="s">&quot;</span><span class="p">,</span> <span class="n">data</span><span class="p">[</span><span class="mi">0</span><span class="p">]);</span>
</span><span class='line'>  <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>  <span class="k">while</span> <span class="p">(</span><span class="mi">1</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>    <span class="n">sleep</span><span class="p">(</span><span class="mi">2000000</span><span class="p">);</span>
</span><span class='line'>  <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>This is a test program that mmaps 512M out of a 1GB file in various ways.</p>

<h3>Single MAP_SHARED mmap</h3>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'>./test <span class="m">1</span> MAP_SHARED NO_MAP_POPULATE
</span></code></pre></td></tr></table></div></figure>


<p>Content of smaps:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'>7f418625d000-7f41a625d000 rw-s <span class="m">00000000</span> 103:01 <span class="m">132</span>                       /tmp/smaps
</span><span class='line'>Size:             <span class="m">524288</span> kB
</span><span class='line'>KernelPageSize:        <span class="m">4</span> kB
</span><span class='line'>MMUPageSize:           <span class="m">4</span> kB
</span><span class='line'>Rss:                  <span class="m">64</span> kB
</span><span class='line'>Pss:                  <span class="m">64</span> kB
</span><span class='line'>Shared_Clean:          <span class="m">0</span> kB
</span><span class='line'>Shared_Dirty:          <span class="m">0</span> kB
</span><span class='line'>Private_Clean:        <span class="m">64</span> kB
</span><span class='line'>Private_Dirty:         <span class="m">0</span> kB
</span><span class='line'>...
</span></code></pre></td></tr></table></div></figure>


<p>Several things to note here:</p>

<ul>
<li>The mmaped pages are considered private even though we use <code>MAP_SHARED</code> because each physical page only has 1 PTE points to it.</li>
<li>mmap is lazy and doesn&rsquo;t populate the page table unless MAP_POPULATE is specified and that&rsquo;s why we didn&rsquo;t see 524288 KB in Private_Clean.</li>
<li>We also didn&rsquo;t see 4 KB in Private_Clean even though we just read one integer from the file and that&rsquo;s due to <a href="https://github.com/torvalds/linux/blob/v5.15/mm/memory.c#L4107">fault-around</a>.</li>
</ul>


<h3>Multiple MAP_SHARED mmaps in single process</h3>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'>./test <span class="m">2</span> MAP_SHARED NO_MAP_POPULATE
</span></code></pre></td></tr></table></div></figure>


<p>Content of smaps:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'>7f764be9a000-7f766be9a000 rw-s <span class="m">00000000</span> 103:01 <span class="m">132</span>                       /tmp/smaps
</span><span class='line'>Size:             <span class="m">524288</span> kB
</span><span class='line'>KernelPageSize:        <span class="m">4</span> kB
</span><span class='line'>MMUPageSize:           <span class="m">4</span> kB
</span><span class='line'>Rss:                  <span class="m">64</span> kB
</span><span class='line'>Pss:                  <span class="m">32</span> kB
</span><span class='line'>Shared_Clean:         <span class="m">64</span> kB
</span><span class='line'>Shared_Dirty:          <span class="m">0</span> kB
</span><span class='line'>Private_Clean:         <span class="m">0</span> kB
</span><span class='line'>Private_Dirty:         <span class="m">0</span> kB
</span><span class='line'>...
</span><span class='line'>7f766be9a000-7f768be9a000 rw-s <span class="m">00000000</span> 103:01 <span class="m">132</span>                       /tmp/smaps
</span><span class='line'>Size:             <span class="m">524288</span> kB
</span><span class='line'>KernelPageSize:        <span class="m">4</span> kB
</span><span class='line'>MMUPageSize:           <span class="m">4</span> kB
</span><span class='line'>Rss:                  <span class="m">64</span> kB
</span><span class='line'>Pss:                  <span class="m">32</span> kB
</span><span class='line'>Shared_Clean:         <span class="m">64</span> kB
</span><span class='line'>Shared_Dirty:          <span class="m">0</span> kB
</span><span class='line'>Private_Clean:         <span class="m">0</span> kB
</span><span class='line'>Private_Dirty:         <span class="m">0</span> kB
</span><span class='line'>...
</span></code></pre></td></tr></table></div></figure>


<p>In this case, we mmaps the same file twice in the same process so each page now has 2 PTEs point to it and that&rsquo;s why they are considered shared.</p>

<h3>Multiple MAP_SHARED mmaps in multiple processes</h3>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'>./test <span class="m">1</span> MAP_SHARED NO_MAP_POPULATE
</span></code></pre></td></tr></table></div></figure>




<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'>./test <span class="m">1</span> MAP_SHARED NO_MAP_POPULATE
</span></code></pre></td></tr></table></div></figure>


<p>Content of smaps:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'>7fb76d49e000-7fb78d49e000 rw-s <span class="m">00000000</span> 103:01 <span class="m">132</span>                       /tmp/smaps
</span><span class='line'>Size:             <span class="m">524288</span> kB
</span><span class='line'>KernelPageSize:        <span class="m">4</span> kB
</span><span class='line'>MMUPageSize:           <span class="m">4</span> kB
</span><span class='line'>Rss:                  <span class="m">64</span> kB
</span><span class='line'>Pss:                  <span class="m">32</span> kB
</span><span class='line'>Shared_Clean:         <span class="m">64</span> kB
</span><span class='line'>Shared_Dirty:          <span class="m">0</span> kB
</span><span class='line'>Private_Clean:         <span class="m">0</span> kB
</span><span class='line'>Private_Dirty:         <span class="m">0</span> kB
</span></code></pre></td></tr></table></div></figure>




<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'>7f4e1eb61000-7f4e3eb61000 rw-s <span class="m">00000000</span> 103:01 <span class="m">132</span>                       /tmp/smaps
</span><span class='line'>Size:             <span class="m">524288</span> kB
</span><span class='line'>KernelPageSize:        <span class="m">4</span> kB
</span><span class='line'>MMUPageSize:           <span class="m">4</span> kB
</span><span class='line'>Rss:                  <span class="m">64</span> kB
</span><span class='line'>Pss:                  <span class="m">32</span> kB
</span><span class='line'>Shared_Clean:         <span class="m">64</span> kB
</span><span class='line'>Shared_Dirty:          <span class="m">0</span> kB
</span><span class='line'>Private_Clean:         <span class="m">0</span> kB
</span><span class='line'>Private_Dirty:         <span class="m">0</span> kB
</span></code></pre></td></tr></table></div></figure>


<p>In this case, we mmaps the same file once in two processes so each page also has 2 PTEs point to it and that&rsquo;s why they are considered shared.</p>

<h3>Multiple MAP_PRIVATE mmaps in single process</h3>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'>./test <span class="m">2</span> MAP_PRIVATE NO_MAP_POPULATE
</span></code></pre></td></tr></table></div></figure>


<p>Content of smaps:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'>7f726c909000-7f728c909000 rw-p <span class="m">00000000</span> 103:01 <span class="m">132</span>                       /tmp/smaps
</span><span class='line'>Size:             <span class="m">524288</span> kB
</span><span class='line'>KernelPageSize:        <span class="m">4</span> kB
</span><span class='line'>MMUPageSize:           <span class="m">4</span> kB
</span><span class='line'>Rss:                  <span class="m">64</span> kB
</span><span class='line'>Pss:                  <span class="m">32</span> kB
</span><span class='line'>Shared_Clean:         <span class="m">64</span> kB
</span><span class='line'>Shared_Dirty:          <span class="m">0</span> kB
</span><span class='line'>Private_Clean:         <span class="m">0</span> kB
</span><span class='line'>Private_Dirty:         <span class="m">0</span> kB
</span><span class='line'>...
</span><span class='line'>7f728c909000-7f72ac909000 rw-p <span class="m">00000000</span> 103:01 <span class="m">132</span>                       /tmp/smaps
</span><span class='line'>Size:             <span class="m">524288</span> kB
</span><span class='line'>KernelPageSize:        <span class="m">4</span> kB
</span><span class='line'>MMUPageSize:           <span class="m">4</span> kB
</span><span class='line'>Rss:                  <span class="m">64</span> kB
</span><span class='line'>Pss:                  <span class="m">32</span> kB
</span><span class='line'>Shared_Clean:         <span class="m">64</span> kB
</span><span class='line'>Shared_Dirty:          <span class="m">0</span> kB
</span><span class='line'>Private_Clean:         <span class="m">0</span> kB
</span><span class='line'>Private_Dirty:         <span class="m">0</span> kB
</span><span class='line'>...
</span></code></pre></td></tr></table></div></figure>


<p>Since MAP_PRIVATE is copy-on-write (COW) and we only read from the file so the two VMAs are backed by the same physical pages and hence those pages are considered shared.</p>

<h3>Multiple MAP_PRIVATE mmaps with MAP_POPULATE in single process</h3>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'>./test <span class="m">2</span> MAP_PRIVATE MAP_POPULATE
</span></code></pre></td></tr></table></div></figure>


<p>Content of smaps:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'>7fafbaabe000-7fafdaabe000 rw-p <span class="m">00000000</span> 103:01 <span class="m">132</span>                       /tmp/smaps
</span><span class='line'>Size:             <span class="m">524288</span> kB
</span><span class='line'>KernelPageSize:        <span class="m">4</span> kB
</span><span class='line'>MMUPageSize:           <span class="m">4</span> kB
</span><span class='line'>Rss:              <span class="m">524288</span> kB
</span><span class='line'>Pss:              <span class="m">524288</span> kB
</span><span class='line'>Shared_Clean:          <span class="m">0</span> kB
</span><span class='line'>Shared_Dirty:          <span class="m">0</span> kB
</span><span class='line'>Private_Clean:         <span class="m">0</span> kB
</span><span class='line'>Private_Dirty:    <span class="m">524288</span> kB
</span><span class='line'>...
</span><span class='line'>7fafdaabe000-7faffaabe000 rw-p <span class="m">00000000</span> 103:01 <span class="m">132</span>                       /tmp/smaps
</span><span class='line'>Size:             <span class="m">524288</span> kB
</span><span class='line'>KernelPageSize:        <span class="m">4</span> kB
</span><span class='line'>MMUPageSize:           <span class="m">4</span> kB
</span><span class='line'>Rss:              <span class="m">524288</span> kB
</span><span class='line'>Pss:              <span class="m">524288</span> kB
</span><span class='line'>Shared_Clean:          <span class="m">0</span> kB
</span><span class='line'>Shared_Dirty:          <span class="m">0</span> kB
</span><span class='line'>Private_Clean:         <span class="m">0</span> kB
</span><span class='line'>Private_Dirty:    <span class="m">524288</span> kB
</span><span class='line'>...
</span></code></pre></td></tr></table></div></figure>


<p>If the mmap is PROT_WRITE, MAP_PRIVATE and MAP_POPULATE, then kernel will not only populate the page tables but also <a href="https://github.com/torvalds/linux/blob/v5.15/mm/gup.c#L1477">eagerly triggers COW</a> so each VMA is backed by their own private physcial pages.</p>

<h2>Clean vs Dirty</h2>

<p>From the perspective of smaps, whether a page is considered clean or dirty is determined by <a href="https://github.com/torvalds/linux/blob/v5.15/fs/proc/task_mmu.c#L419">this</a>. Conceptually a page is dirty if it cannot just be discarded without data loss, which means it has dirty writes that haven&rsquo;t been flushed to the underlying file or swap space yet.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[LLM Learning Resources]]></title>
    <link href="http://blog.jjyao.me/blog/2025/10/16/llm-learning-resources/"/>
    <updated>2025-10-16T21:54:04-07:00</updated>
    <id>http://blog.jjyao.me/blog/2025/10/16/llm-learning-resources</id>
    <content type="html"><![CDATA[<p>This post lists resources that I find useful during my journey of learning LLM as a system enginer.</p>

<!-- more -->


<h2>Neural Networks</h2>

<p>LLMs are large neural networks so having a basic understanding of what neural networks are is helpful.</p>

<h4>Victor Zhou&rsquo;s Neural Networks From Scratch</h4>

<p><a href="https://victorzhou.com/series/neural-networks-from-scratch/">Neural Networks From Scratch</a> is a 4-post series
that introduces classic neural networks, recurrent neural networks (RNNs) and convolutional neural networks (CNNs).
It doesn&rsquo;t require any prior knowledge except for some math. One good thing about this series is that it&rsquo;s very hands-on and you will learn, step-by-step, how to write a simple nueral network from scratch using only numpy to solve a real problem.</p>

<h4>Michael Nielsen&rsquo;s Visual proof that neural nets can compute any function</h4>

<p><a href="http://neuralnetworksanddeeplearning.com/chap4.html">Visual proof that neural nets can compute any function</a> gives a visual explanation of the <a href="https://en.wikipedia.org/wiki/Universal_approximation_theorem">universal approximation theorem</a> that neural networks can be used to approximate any continuous function to any desired precision.</p>

<h2>LLM</h2>

<h4>Andrej Karpathy&rsquo;s Neural Networks: Zero to Hero</h4>

<p><a href="https://karpathy.ai/zero-to-hero.html">Neural Networks: Zero to Hero</a> is a hands-on course that starts with building a simple neural network from scratch and ends with building a GPT from scratch. It&rsquo;s a great course to learn LLM progressively.</p>

<h3>Inference</h3>

<p>The best way to learn LLM inference is writing an inference engine from scratch IMO and this helps you better understand model architectures as well.</p>

<h4>Andrej Karpathy&rsquo;s llama2.c</h4>

<p><a href="https://github.com/karpathy/llama2.c">llama2.c</a> is an inference engine for Llama 2 in one file of pure C. It can give you a taste of what LLM inference looks like. Based on it, I wrote a <a href="https://github.com/jjyao/llm.edu/tree/main/llama2.rs">Rust implementation</a> with optimizations like tensor parallelism.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[High Output Management]]></title>
    <link href="http://blog.jjyao.me/blog/2025/08/17/high-output-management/"/>
    <updated>2025-08-17T21:29:32-07:00</updated>
    <id>http://blog.jjyao.me/blog/2025/08/17/high-output-management</id>
    <content type="html"><![CDATA[<p>The output of a manager is the output of the organizational units under his or her supervision or influence. This book talks about how to increase the managerial output.</p>

<!-- more -->


<h2>Managerial Leverage</h2>

<p>Managerial output = Output of organization = A1 * L1 + A2 * L2 + &hellip; where A is a managerial activity and L is the corresponding leverage. Manager activities include information-gathering, information-giving, decision-making, nudging, and being a role model. Leverage, by definition, is the measure of the output generated by any given managerial activity. Based on the formula, a manager can increase his output by:</p>

<ol>
<li>Increase the rate with which a manager performs his activities, speeding up his work.</li>
<li>Increasing the leverage associated with the various managerial activities.</li>
<li>Shifting the mix of a manager&rsquo;s activities from those with lower to those with higher leverage.</li>
</ol>


<p>The art of management lies in the capacity to select from the many activities of seemingly comparable significance the one or two or three that provide leverage well beyond the others and concentrate on them. This is how we should allocate our time —— the single most important resource that we allocate from one day to the next. Given time is a finite resource, and when we say &ldquo;yes&rdquo; to one thing we are inevitably saying &ldquo;no&rdquo; to another, we should be very selective about things we choose to do.</p>

<h2>Meetings —— The Medium of Managerial Work</h2>

<p>There are two kinds of meetings. The first is <strong>process-oriented</strong> meeting, knowledge is shared and information is exchanged. Such meetings take place on a regularly scheduled basis. The second is <strong>mission-oriented</strong> meeting, the purpose is to solve a specific problem and produce a decision. They are ad hoc affairs, not scheduled long in advance, because they usually can&rsquo;t be.</p>

<p>One-on-one is a process-oriented meeting. It should be regarded as the subordinate&rsquo;s meeting, with its agenda and tone set by him.</p>

<p>For a mission-oriented meeting, the purpose should be decided beforehand and it&rsquo;s the meeting chairman&rsquo;s job to make sure the meeting accomplishs the purpose for which it was called. Since the goal of this type of meetings is to make a decision, we should control the number of attendees. A decision-making meeting is hard to keep moving if more than six or seven people attend. Eight people should be the absolute cutoff. Decision-making is not a spectator sport, because onlookers get in the way of what needs to be done. Once the meeting is over, the chairman must nail down exactly what happened by sending out minutes that summarize the discussion that occurred, the decision made, and the actions to be taken. And it&rsquo;s very important that attendees get the minutes quickly, before they forget what happened. The minutes should also be as clear and as specific as possible, telling the reader what is to be done, who is to do it, and when.</p>

<h2>Decisions, Decisions</h2>

<p>An organization does not live by its members agreeing with one another at all times about everything. It lives instead by people committing to support the decisions and the moves of the business.</p>

<p><img src="http://blog.jjyao.me/images/post/high-output-management/ideal-decision-making-process.png"></p>

<p>The ideal decision-making process involves three stages. The first stage should be <strong>free</strong> discussion, in which all points of view and all aspects of an issue are openly welcomed and debated. The greater the disagreement and controversy, the more important becomes the word free. The next stage is reaching a <strong>clear</strong> decision. Again, the greater the disagreement about the issue, the more important becomes the word clear. Finally, everyone involved must give the decision reached by the group <strong>full</strong> support.</p>

<p>The person makes the decision is the DRI and everyone else needs to <strong>disagree and commit</strong> once the decision is made. The DRI should have the confidence to make the decision especially when consensus is not reached and the self-confidence mostly comes from a gut-level realization that nobody has ever died from making a wrong business decision, or taking inappropriate action, or being overruled (most decisions are two-way doors).</p>

<p>We shouldn&rsquo;t enter the decision-making stage too early or wait too long. If we make the decision too early, we may miss some opinions. If we make the decision too late (aiming for the absolutely right decision), we are not moving fast enough. Often, it&rsquo;s better to try out a 60-point decision and iterate on it quickly based on feedbacks than trying to find a 100-point decision endlessly.</p>

<p>For decision-making, one of the manager&rsquo;s key tasks is to settle six important questions in advance:</p>

<ul>
<li>What decision needs to be made?</li>
<li>When does it have to be made?</li>
<li>Who will decide?</li>
<li>Who will need to be consulted prior to making the decision?</li>
<li>Who will ratify or veto the decision?</li>
<li>Who will need to be informed of the decision?</li>
</ul>


<h2>Planning: Today&rsquo;s Actions for Tomorrow&rsquo;s Output</h2>

<p>Planning is to answer the qeustion: What do I have to do today to solve —— or better, avoid —— tomorrow&rsquo;s problem? Today&rsquo;s gap represents a failure of planning sometime in the past.</p>

<p>MBO (management-by-objectives) is a planning process that can be applied to daily work. A successful MBO system needs only to answer two questions:</p>

<ul>
<li>Where do I want to go? (The answer provides the objective).</li>
<li>How will I pace myself to see if I am getting there? (The answer gives us milestones, or key results.)</li>
</ul>


<h2>The Sports Analogy</h2>

<p>The role of the manager is that of the coach. First, an ideal coach takes no personal credit for the success of his team, and because of that his players trust him. Second, he is tough on his team. By being critical, he tries to get the best performance his team members can provide. Third, a good coach was likely a good player himself at one time. And having played the game well, he also understands it well.</p>

<h2>Performance Appraisal: Manager as Judge and Jury</h2>

<p>Performance reviews is the single most important form of task-relevant feedback we as supervisors can provide. The goal is to improve the subordinate&rsquo;s performance instead of cleansing our system of all the truths we may have observed about the subordinate so less may very well be more (give one feedback and one area for improvement at a time).</p>

<p>It might be counterintuitive but we should spend more time trying to improve the performance of our stars. After all, these people account for a disproportionately large share of the work in any organization. Put another way, concentrating on the stars is a high-leverage activity: if they get better, the impact on group output is very great indeed. We must keep in mind, however, that no matter how stellar a person&rsquo;s performance level is, there is always room for improvement.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Python Heap Dump]]></title>
    <link href="http://blog.jjyao.me/blog/2024/09/13/python-heap-dump/"/>
    <updated>2024-09-13T21:42:32-07:00</updated>
    <id>http://blog.jjyao.me/blog/2024/09/13/python-heap-dump</id>
    <content type="html"><![CDATA[<p>This post shows how to heap dump a <em>running</em> Python process using <a href="https://pypi.org/project/pyrasite/">pyrasite</a> and <a href="https://pypi.org/project/guppy3/">guppy3</a>.</p>

<!-- more -->


<h3>Install pyrasite</h3>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'>pip install pyrasite
</span></code></pre></td></tr></table></div></figure>


<p><code>pyrasite</code> allows you to attach to a running Python process and run arbitrary Python code. It needs ptrace to function properly and the way to enable it varies depending on your OS. For Ubuntu, you can do:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'>sudo sysctl -w kernel.yama.ptrace_scope<span class="o">=</span>0
</span></code></pre></td></tr></table></div></figure>


<p>If you use <code>Conda</code>, you might need to run <code>unset LD_LIBRARY_PATH</code> so that <code>gdb</code> can use the system <code>libstdc++.so</code> instead of the one installed inside your conda env which can be incompatible.</p>

<h3>Install guppy3</h3>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'>pip install guppy3
</span></code></pre></td></tr></table></div></figure>


<p><code>guppy3</code> has a subpackage <code>heapy</code> that allows you to inspect the heap.</p>

<h3>Dump Heap</h3>

<p>Once everything is installed, we can then use pyrasite to attach to the target running Python process:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'>pyrasite-shell &lt;pid&gt;
</span></code></pre></td></tr></table></div></figure>


<p>This attaches to the process and opens a REPL that you can run the heap dump code using <code>guppy3</code>:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
<span class='line-number'>32</span>
<span class='line-number'>33</span>
<span class='line-number'>34</span>
<span class='line-number'>35</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'><span class="kn">from</span> <span class="nn">guppy</span> <span class="kn">import</span> <span class="n">hpy</span>
</span><span class='line'><span class="n">h</span> <span class="o">=</span> <span class="n">hpy</span><span class="p">()</span>
</span><span class='line'><span class="n">heap</span> <span class="o">=</span> <span class="n">h</span><span class="o">.</span><span class="n">heap</span><span class="p">()</span>
</span><span class='line'>
</span><span class='line'><span class="k">print</span><span class="p">(</span><span class="n">heap</span><span class="o">.</span><span class="n">all</span><span class="p">)</span> <span class="c"># print the heap dump</span>
</span><span class='line'><span class="sd">&quot;&quot;&quot;</span>
</span><span class='line'><span class="sd">Partition of a set of 222038 objects. Total size = 26540189 bytes.</span>
</span><span class='line'><span class="sd"> Index  Count   %     Size   % Cumulative  % Kind (class / dict of class)</span>
</span><span class='line'><span class="sd">     0  67095  30  6591256  25   6591256  25 str</span>
</span><span class='line'><span class="sd">     1  50143  23  3623400  14  10214656  38 tuple</span>
</span><span class='line'><span class="sd">     2  14415   6  2563320  10  12777976  48 types.CodeType</span>
</span><span class='line'><span class="sd">     3  28124  13  2205321   8  14983297  56 bytes</span>
</span><span class='line'><span class="sd">     4   2175   1  2064360   8  17047657  64 type</span>
</span><span class='line'><span class="sd">     5   4816   2  1962952   7  19010609  72 dict (no owner)</span>
</span><span class='line'><span class="sd">     6  13577   6  1846472   7  20857081  79 function</span>
</span><span class='line'><span class="sd">     7   2175   1  1087024   4  21944105  83 dict of type</span>
</span><span class='line'><span class="sd">     8    690   0  1019024   4  22963129  87 dict of module</span>
</span><span class='line'><span class="sd">     9  10472   5   312536   1  23275665  88 int</span>
</span><span class='line'><span class="sd">    10    273   0   244608   1  23520273  89 google._upb._message.MessageMeta</span>
</span><span class='line'><span class="sd">&quot;&quot;&quot;</span>
</span><span class='line'>
</span><span class='line'><span class="k">print</span><span class="p">(</span><span class="n">heap</span><span class="o">.</span><span class="n">all</span><span class="p">[</span><span class="mi">10</span><span class="p">]</span><span class="o">.</span><span class="n">shpaths</span><span class="p">)</span> <span class="c"># print the shortest path from root to object with index 10</span>
</span><span class='line'><span class="sd">&quot;&quot;&quot;</span>
</span><span class='line'><span class="sd"> 0: hp.Root.i0_modules[&#39;ray._private.gcs_utils&#39;].__dict__[&#39;ActorTableData&#39;]</span>
</span><span class='line'><span class="sd"> 1: hp.Root.i0_modules[&#39;ray._private.gcs_utils&#39;].__dict__[&#39;AvailableResources&#39;]</span>
</span><span class='line'><span class="sd"> 2: hp.Root.i0_modules[&#39;ray._private.gcs_utils&#39;].__dict__[&#39;ErrorTableData&#39;]</span>
</span><span class='line'><span class="sd"> 3: hp.Root.i0_modules[&#39;ray._private.gcs_utils&#39;].__dict__[&#39;GcsEntry&#39;]</span>
</span><span class='line'><span class="sd"> 4: hp.Root.i0_modules[&#39;ray._private.gcs_utils&#39;].__dict__[&#39;GcsNodeInfo&#39;]</span>
</span><span class='line'><span class="sd"> 5: hp.Root.i0_modules[&#39;ray._private.gcs_utils&#39;].__dict__[&#39;JobConfig&#39;]</span>
</span><span class='line'><span class="sd"> 6: hp.Root.i0_modules[&#39;ray._private.gcs_utils&#39;].__dict__[&#39;JobTableData&#39;]</span>
</span><span class='line'><span class="sd"> 7: hp.Root.i0_modules[&#39;ray._private.gcs_utils&#39;].__dict__[&#39;PlacementGroupTableData&#39;]</span>
</span><span class='line'><span class="sd"> 8: hp.Root.i0_modules[&#39;ray._private.gcs_utils&#39;].__dict__[&#39;PubSubMessage&#39;]</span>
</span><span class='line'><span class="sd"> 9: hp.Root.i0_modules[&#39;ray._private.gcs_utils&#39;].__dict__[&#39;ResourceDemand&#39;]</span>
</span><span class='line'><span class="sd">&lt;... 271 more paths ...&gt;</span>
</span><span class='line'><span class="sd">&quot;&quot;&quot;</span>
</span></code></pre></td></tr></table></div></figure>



]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[The 4 Disciplines of Execution]]></title>
    <link href="http://blog.jjyao.me/blog/2023/04/16/the-4-disciplines-of-execution/"/>
    <updated>2023-04-16T21:21:10-07:00</updated>
    <id>http://blog.jjyao.me/blog/2023/04/16/the-4-disciplines-of-execution</id>
    <content type="html"><![CDATA[<p>This book shows how a team can execute an important goal successfully in the face of massive amount of day-to-day operations that are urgently required to keep the business running.</p>

<!-- more -->


<p>There are lots of urgent things (whirlwind) to do every day to keep the lights on. Failure to do so can kill the business today. However, there are also important things to take the business to the next level. Failure to do those can kill the business tomorrow. As a result, being able to execute important things successfully while doing the day job is critical for the success of the business in the long term. To help teams to do so, this book presents a methodology called 4DX that consists of four disciplines.</p>

<h2>Discipline 1: Focus on the Wildly Important</h2>

<p>The key of the first discipline is <strong>focus</strong>. Attempting to spread the limited capacity across multiple goals is the most common cause of failure in execution. Instead, <strong>one and only one</strong> wildly important goal (WIG) should be identified and executed.</p>

<p>To identify the WIG, one can ask the following question: If every other aspect of our team&rsquo;s performance remained at its current level, what is the one area where significant improvement would have the greatest <strong>impact</strong>? The resulting WIG should be specific, clearly measurable and in the form of <strong>From X to Y by when</strong> (e.g. improve the NPS score from 1 to 6 by end of the year).</p>

<h2>Discipline 2: Act on the Lead Measures</h2>

<p>The key of the second discipline is <strong>leverage</strong>. Lag measures are the tracking measurements of the WIG and they tell you whether you achieve the WIG or not. For example, if the WIG is improving the NPS score from 1 to 6 by end of the year then the lag measure is the NP score. The issue with the lag measure is that you cannot influence it directly and it is lagging in the sense that by the time you get the result, it is already too late and the performance that drove it is in the past. In contrast, lead measures measure things that lead to the WIG and can be influenced by us directly. For example, burning 1000 calories every day is a good lead measure for a WIG of losing 20 pounds in 3 months.</p>

<p>Two basic characteristics of a valid lead measure are <strong>predictive</strong> and <strong>influenceable</strong>: it&rsquo;s predictive of achieving the WIG and can be influenced directly. There could be many lead measures for a WIG and finding the highest-leverage ones is perhaps the toughest and most intriguing challenge for leaders trying to execute a WIG. Finding lead measures requires the involvement of the frontline team members and that involvement brings engagement and commitment. In the end, it&rsquo;s the frontline team that acts on the lead measures. A leader can only veto but not dictate what the final lead measures should be. The resulting lead measures are the team&rsquo;s bet: they bet that by driving these lead measures, the team is going to achieve the WIG.</p>

<p><img src="http://blog.jjyao.me/images/post/the-4-disciplines-of-execution/lead-measure.png"></p>

<h2>Discipline 3: Keep a Compelling Scoreboard</h2>

<p>The key of the third discipline is <strong>engagement</strong>. A compelling player&rsquo;s scoreboard that clearly shows whether a team is winning or losing drives the highest level of engagement and the engagement drives the highest level of performance. The fundamental purpose of a player&rsquo;s scoreboard is to motivate the players to win.</p>

<p>A compelling scoreboard has the following four characteristics:</p>

<ul>
<li><p>It&rsquo;s simple as a player&rsquo;s scoreboard in a sporting event, not a more complex coach&rsquo;s scoreboard.</p></li>
<li><p>It can be seen easily. A visible scoreboard makes sure that the WIG and lead measures are not forgotten in the constant urgency of day-to-day responsibilities.</p></li>
<li><p>It shows both the lead and lag measures. From the scoreboard, the team can see what they are doing (the lead measures) and what they are getting (the lag measures). Once the team sees that the lag measure is moving because of the efforts they have made on the leads, it has a dramatic effect on engagement because they know they are directly impacting the results.</p></li>
<li><p>It tells if a team is winning or losing immediately. If the team can&rsquo;t quickly determine if they are winning or not by looking at the scoreboard, then it&rsquo;s not a game, it&rsquo;s just data.</p></li>
</ul>


<h2>Discipline 4: Create a Cadence of Accountability</h2>

<p>The key of the fourth discipline is <strong>accountability</strong>. This is where execution actually happens. The previous three disciplines set up the game but until this discipline is applied, the team is not in the game. Without this discipline, there will always be actions the team members know they should perform but never actually do with real consistency due to whirlwind.</p>

<p>To create a cadence of accountability, a WIG session is held on the same day and at the same time every week with the following agenda:</p>

<ol>
<li><p>Account. Report on last week&rsquo;s commitments.</p></li>
<li><p>Review the scoreboard. Learn from successes and failures.</p></li>
<li><p>Plan. Clear the path and make new commitments.</p></li>
</ol>


<p>To figure out the <em>high-impact</em> commitments for the week, ask the question &ldquo;What are the one or two most important things I can do this week to impact the lead measures?&rdquo; Once the commitments are made from team members, they are <em>unconditional</em> regardless of the whirlwind and the team member is accountable to each other.</p>

<p>Finally, a successful 4DX not only helps the team to achieve the specific WIG but also produces a winning team that performs at the next level and is ready for the next WIG.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[The Design of Everyday Things]]></title>
    <link href="http://blog.jjyao.me/blog/2022/06/21/the-design-of-everyday-things/"/>
    <updated>2022-06-21T22:40:54-07:00</updated>
    <id>http://blog.jjyao.me/blog/2022/06/21/the-design-of-everyday-things</id>
    <content type="html"><![CDATA[<p>What&rsquo;s a good design? How to produce a good design? This book provides some answers.</p>

<!-- more -->


<h2>Human-centered Design</h2>

<p>A good design should be human-centered. It should put human needs, capabilities, and behavior first, then accommodate those needs, capabilities, and ways of behaving. <em>The design should adapt to people, not the opposite</em>.</p>

<p>A good design should be understandable and usable. The design should help users establish a concept model of the system that is an explanation, usually highly simplified, of how the system works. There are seven design principles to achieve a good design:</p>

<ul>
<li>Discoverability: It is possible to determine what actions are possible and the current state of the device.</li>
<li>Feedback: There is full and continuous information about the results of actions and the current state of the product or service. After an action has been executed, it is easy to determine the new state.</li>
<li>Conceptual model: The design projects all the information needed to create a good conceptual model of the system, leading to understanding and a feeling of control. The conceptual model enhances both discoverability and evaluation of results.</li>
<li>Affordances: The proper affordances exist to make the desired actions possible.</li>
<li>Signifiers: Effective use of signifiers ensures discoverability and that the feedback is well communicated and intelligible.</li>
<li>Mappings: The relationship between controls and their actions follows the principles of good mapping, enhanced as much as possible through spatial layout and temporal contiguity.</li>
<li>Constraints: Providing physical, logical, semantic, and cultural constraints guides actions and eases interpretation.</li>
</ul>


<h2>The Double-Diamond Model of Design</h2>

<p>Finding the right problem and finding the right solution are the two components of design and this corresponds to the two phases of the design process. The double-diamond model of design describes these two phases.</p>

<p><img src="http://blog.jjyao.me/images/post/the-design-of-everyday-things/double-diamond-model-of-design.png"></p>

<p>To find the real, ROOT problem to solve, we can use the <em>five whys</em> approach. We should keep asking why until we find the real, fundamental, root problem. Don&rsquo;t rely on whatever people tell you because they will tell you that they want &ldquo;a faster horse&rdquo;. In fact, the author has a somewhat counterintuitive rule for himself: never solve the problem I am asked to solve. Because the problem being asked to solve, invariably, is not the real, fundamental, root problem.</p>

<h2>No Human Error, Only Bad Design</h2>

<p>Human error usually is a result of poor design. Whenever human errors happen, we should think about how we can design better to eliminate those errors or reduce the impact if complete elimination is impossible. This is an important mindset to have: if a system lets you make the error, it&rsquo;s badly designed.</p>

<p>There are several design practices to prevent human errors:</p>

<ul>
<li>Avoid procedures that have identical opening steps but then diverge.</li>
<li>Ensure that controls and displays for different purposes are significantly different from one another.</li>
<li>Try to avoid modes. If they are necessary, the equipment must make it obvious which mode is invoked.</li>
<li>People will be interrupted during their activities and they may need assistance in resuming their operations.</li>
<li>Don&rsquo;t count on much being retained in people&rsquo;s short-term memory. The most effective way of helping people remember is to make it unnecessary.</li>
</ul>


<h2>Successful Product, Successful Design</h2>

<p>The author argues that the design is successful only if the final product is successful —— if people buy it, use it and enjoy it. It doesn&rsquo;t matter how great the design is if people don&rsquo;t buy it.</p>

<p>To create a successful product, people should focus on strengths, not weaknesses. If the product has real strengths, it can afford to just be &ldquo;good enough&rdquo; in the other areas. People should also focus on the true needs of the people who use the product and ignore competing voices.</p>

<p>To turn a good idea into a successful product requires <em>timing</em>. Good ideas that appear too early will fail even if eventually others introduce them successfully. It takes a long time (may be decades), for good ideas to traverse the distance from conception to successful products. We should <em>ride the wave</em> to make the product more likely to be successful.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Crossing the Chasm]]></title>
    <link href="http://blog.jjyao.me/blog/2021/12/27/crossing-the-chasm/"/>
    <updated>2021-12-27T20:26:25-08:00</updated>
    <id>http://blog.jjyao.me/blog/2021/12/27/crossing-the-chasm</id>
    <content type="html"><![CDATA[<p>For B2B high-tech startup, there is a period when the product is already successful in the early market and is trying to enter the mainstream market. This period is called crossing-the-chasm period and it&rsquo;s peril. Many startups die during this period and never reach the mainstream market. This book tells us why there is such a period and why it&rsquo;s dangerous. It also shows how we can get through this period and be successful in the mainstream market.</p>

<!-- more -->


<h2>Technology Adoption Life Cycle</h2>

<p><img src="http://blog.jjyao.me/images/post/crossing-the-chasm/technology-adoption-life-cycle.png"></p>

<p>For the technology or product offered by a company, its adoption goes through several phases from left to right.</p>

<h4>Innovators (Technology Enthusiasts)</h4>

<p>This is a group of people who are techies. They just like new technologies for its own sake and are willing to try them. They don&rsquo;t represent a significant market in themselves, nor do they have enough buying power. However they are still important to win over because 1) they are the sounding board and test bed for the new technology or product 2) they are the reference base for early adopters.</p>

<h4>Early Adopters (Visionaries)</h4>

<p>This group of people treat the new technology or product as an opportunity to have a strategic leap forward. They want fundamental breakthrough enabled by the new technology and are willing to take high risks due to the potential order-of-magnitude return on investment. These people have big budget to implement their strategic initiative so they are an important source of high-tech development capital.</p>

<h4>Early Majority (Pragmatists)</h4>

<p>These people represent the mainstream market that any startup wants to win due to its volume. Unlike visionaries, they want incremental, predictable improvements instead of disruptive ones. They have the following characteristics: 1) they are loyal once won and will even help you to defend new comers 2) they want to buy the <em>whole product</em> from the <em>market leader</em> 3) they reference other pragmatists not visionaries.</p>

<h4>Late Majority (Conservatives)</h4>

<p>They buy the extremely mature product with low cost just to stay on par with the rest of the world. They are the low-margin end of the market but have high volume.</p>

<h4>Laggards (Skeptics)</h4>

<p>Even though they may not buy products, they do point continually to the discrepancies between the sales claims and the delivered product. Startups should use their feedbacks to continuously improving the products.</p>

<h2>Word of Mouth</h2>

<p>In the high-tech buying process, word of mouth is the number-one source of information that buyers reference. People reference each other during the buying decision.</p>

<h2>Whole Product</h2>

<p><img src="http://blog.jjyao.me/images/post/crossing-the-chasm/whole-product.png"></p>

<p>In the mainstream market, people want to buy whole product not core product. In other words, they want to buy the product that has a surrounding ecosystem, which radically reduces their burden of support. Since whole products grow up around the market leading products and not around the others, pragmatists buy from market leaders.</p>

<h2>Chasm</h2>

<p>The chasm between visionaries and pragmatists exists because visionaries is a very poor reference base for pragmatists. They are fundamentally different groups of people for the following reasons: 1) visionaries don&rsquo;t need many references to buy a product, rather they want to be the first to buy the product and create competitive advantage; pragmatists, on the other hand, need extensive reference to prove the validity of the new product 2) visionaries care more about the future, in fact, they are defining the future, while pragmatists don&rsquo;t put a lot of stake in futuristic things 3) visionaries don&rsquo;t expect the existence of the whole product and they are willing to piece together one themselves in return for getting a jump on their competition, while pragmatists only want to buy the whole product 4) visionaries, successful or not, don&rsquo;t plan to stick around long while pragmatists are cautious about their decisions since they know they will have to live with the results. This effectively means that when we try to win over pragmatists, there is effectively no reference base to start with.</p>

<h2>D-Day</h2>

<p>The way to cross the chasm successfully is by launching a D-Day type of invasion focusing on a highly specific target segment within a mainstream marketplace.</p>

<h4>Target the Point of Attack</h4>

<p>The first thing to do is finding the target niche market segment which is also called the beachhead segment. The segment should be <em>big enough to matter, small enough to win and good fit with your crown jewels</em>. Customers in that segment should have compelling reason to buy the product or in other words, feel enough pain. Instead of picking the optimal beachhead to be successful, which is very hard if not impossible, what more important is winning whatever good enough beachhead that&rsquo;s picked.</p>

<p>It&rsquo;s very important to pick a very specific beachhead to conquer instead of the entire mainstream market when we are crossing the chasm for the following reasons: 1) word-of-mouth has boundaries which is ususally within a market segment so winning over one or two customers in each of five or ten different segments is worse than winning four or five customers in one segment in terms of word-of-mouth effect 2) it&rsquo;s easier to become <em>a big fish in a small pond</em> and achieve market leadership given that pragmatists want to buy from market leaders 3) our scarce resource is only enough to build the whole product for a single niche market.</p>

<h4>Assemble the Invasion Force</h4>

<p>The next thing is creating the ecosystem around our core product, namely the whole product. This often requires bringing in partners and allies needed to make it a reality.</p>

<h4>Define the Battle</h4>

<p>Then we need to create the competition and positioning in order for our product to be <em>easy to buy</em>. Viable competition is important since where there is no competition, there is no market. <em>Market alternatives</em> indicate the existence of the budget dollars to buy our products and <em>product alternatives</em> call out the differentiation. The positioning of our product should be short enough to pass the elevator test so that it can successfully create and occupy a space inside the target customers&#8217; head.</p>

<h4>Launch the Invasion</h4>

<p>Finally we need to select the intended distribution channel and set pricing to give us motivational leverage over that channel.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Multipliers: How the Best Leaders Make Everyone Smarter]]></title>
    <link href="http://blog.jjyao.me/blog/2021/08/29/multipliers-how-the-best-leaders-make-everyone-smarter/"/>
    <updated>2021-08-29T22:07:08-07:00</updated>
    <id>http://blog.jjyao.me/blog/2021/08/29/multipliers-how-the-best-leaders-make-everyone-smarter</id>
    <content type="html"><![CDATA[<p>When you ask people if they want to be multipliers who make surrounding people better or diminishers who make everyone worse, most people will say that they want to be multipliers. However, in reality, many people are accidental diminishers in some aspects. Being a true multiplier requires a multiplier mindset and certain approaches. This book tells you what multipliers are and how to become one.</p>

<!-- more -->


<p>Multipliers are leaders who make people better and more capable. They can access and revitalize the intelligence in the people around them. They are <em>genius makers</em> by accessing and multiplying the genius in others. They have a <em>growth mindset</em>, which is a belief that basic qualities like intelligence and ability can be cultivated through effort. In contrast, diminishers drain intelligence and capability out of the people around them.</p>

<h2>Multiplier Mindset</h2>

<p>What people believe affects their behaviors. As a result, we need to have a multiplier mindset first in order to become one. The fundamental assumption a multiplier has is that people are smart. They discover the genius in people by asking &ldquo;how is this person smart?&rdquo;. Multipliers believe that:</p>

<ol>
<li><em>People are smart and will figure things out.</em></li>
<li><em>If I can find someone&rsquo;s genius, I can put them to work.</em></li>
<li><em>People&rsquo;s best thinking must be given, not taken.</em></li>
<li><em>People get smarter by being challenged.</em></li>
<li><em>With enough minds, we can figure it out.</em></li>
</ol>


<h2>Challenger vs Know-it-all</h2>

<p>Since multipliers believe that people get smarter by being challenged, they ask really insightful and interesting questions that make people think. They don&rsquo;t limit the team to what they know, they push their teams beyond their own knowledge and that of the organization. Even if they have the answer, the don&rsquo;t just give them. Instead, they just provide enough information to provoke thinking and to help people discover and see the opportunity for themselves. <em>What&rsquo;s more important as a leader is not having the right answer but asking the right questions.</em></p>

<h2>Debate Maker vs Decision Maker</h2>

<p>Multipliers believe that with enough minds, we can figure it out. As a result, they like <em>collective debate</em>. Through debate, they challenge and stretch what people know, thus making the organization smarter over time and creating the organizational will to execute the decisions made. In contrast, when people execute an undebated decision, they turn to debating the soundness of a decision rather than executing it.</p>

<h2>Liberator vs Tyrant</h2>

<p>Multipliers believe that people&rsquo;s best thinking must be given, not taken. They provide a safe environment for people to think and make mistakes. The highest quality of thinking cannot emerge without learning and learning can&rsquo;t happen without mistakes. <em>Intimidation and fear rarely produce truly great work.</em> Speaking of creating a safe environment, there is no easier way to invite experimentation and learning than to <em>share stories about multipliers&#8217; own mistakes</em>.</p>

<p>While multiplier gives space and safe environment, they also demand the best work. It&rsquo;s a fair trade. They create an intense environment that requires people&rsquo;s best thinking and their best work. They generate pressue, but they don&rsquo;t generate stress. Requiring people&rsquo;s best work is different from insisting on desired outcomes. Stress is created when people are expected to produce outcomes that are beyond their control. But they feel positive pressure when they are held to their best work. <em>Multipliers distinguish best work from outcomes.</em></p>

<h2>Investor vs Micro-manager</h2>

<p>Multipliers believe that people are smart and will figure things out. So they operate as investors, giving ownership that keeps rolling back to other people. As investors, they define ownership, invest resources and hold people <em>accountable</em>. When they teach, they invest in their people&rsquo;s ability to solve and avoid problems in the future. In the end, multipliers enable others to operate independently by giving other people ownership for results and investing in their success. They create organizations that can perform and win, not only without them on the field, but long after their direct influence is felt.</p>

<h2>Talent Magnet vs Empire Builder</h2>

<p>Multipliers believe that if I can find someone&rsquo;s genius, I can put them to work. They are like magnets that draw in talent and develop it to its fullset. They look for talent everywhere, find people&rsquo;s <em>native genius</em>, utilize people at their fullsets and remove the blockers. Multipliers not only notice people&rsquo;s talent, they <em>label</em> it for them. By telling people what they see, they raise people&rsquo;s awareness and confidence, allowing them to provide their capability more fully. What&rsquo;s more, once they uncover the native genius of others, they look for opportunities that demand that capability.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[What I Have Learned From the LinkedIn Graph Database Team]]></title>
    <link href="http://blog.jjyao.me/blog/2021/08/22/what-i-have-learned-from-the-linkedin-graph-database-team/"/>
    <updated>2021-08-22T19:48:33-07:00</updated>
    <id>http://blog.jjyao.me/blog/2021/08/22/what-i-have-learned-from-the-linkedin-graph-database-team</id>
    <content type="html"><![CDATA[<p>I had worked for the LinkedIn graph database team for 5+ years and we successfully built a <a href="https://engineering.linkedin.com/blog/2020/liquid-the-soul-of-a-new-graph-database-part-1">graph database</a> serving the entire LinkedIn economic graph. In this post, I want to share what I have learned. Disclaimer: many of the words and wisdom are from my great colleagues.</p>

<!-- more -->


<h3>All incidents are gifts</h3>

<p>Incidents are opportunities for us to fix bugs, improve the stability of the system and improve the process of handling incidents. We should treat them as gifts and learn as much as possible out of them.</p>

<h3>All incidents should be novel</h3>

<p>This basically means that we should never make the same mistake twice. Once an incident happens, we try as hard as we can to fix it and make sure it will never happen again with the same root cause.</p>

<h3>Hardware failure is common at scale</h3>

<p>We have, on average, 2 DIMM failures per week so we should design our software in a fault tolerant way.</p>

<h3>API is sticky</h3>

<p>Once clients start to use the exposed APIs, they become extremely sticky. That means we need to design them carefully since changing them afterwards is <a href="https://www.joelonsoftware.com/2004/06/13/how-microsoft-lost-the-api-war/">costly</a>.</p>

<h3>Logging is talking to the user/operator</h3>

<p>How programs talk to humans has a huge impact on the rate at which mistakes can be fixed. If programs tell humans exactly what is wrong, that rate can be very fast. If programs are silent or overwhelm humans with too much information, that rate can be extremely slow. When there are too many spurious errors, people get alerts fatigue and they will overlook the real problems.</p>

<p>When we write logs in our code, we need to remember that the audience is not just us but also people that may not be familiar with the entire codebase like SREs. That means the log messages should be crystal clear and actionable. Imagining how frustrating it is when oncalls get paged at 2am and they have no clue what those log messages mean and how to act on them. <a href="https://spark.apache.org/error-message-guidelines.html">Here</a> is a guideline of how to write good error messages.</p>

<h3>Comment on why</h3>

<p>Code comments should say why the code is there instead of what the code does. What the code does should be clear from the code itself. If it is not the case, then we should refactor the code to make it clear instead of adding a comment. A large decaying comment is frequently just an apology for crappy code. Don&rsquo;t accept the apology. Fix the code. Don&rsquo;t give up until you try your best. Then, as a last resort, write the comment.</p>

<h3>Good enough is not enough</h3>

<p>The math is simple: 0.8 * 0.8 * 0.8 * &hellip;.. = 0. If every time we just achieve good enough, then eventually it will become zero/failure. We should never settle and always try to do as best as we can.</p>

<h3>Conduct code review</h3>

<p>Code review is not just about finding bugs. We should also think about how we can rewrite the code in a better way that is easily understandable and unlikely to cause future bugs.</p>

<p>Also reading other people&rsquo;s good reviews allows us to learn not only from our own mistakes but also the mistakes of others.</p>

<h3>Write design document</h3>

<p>&ldquo;Writing is nature’s way of letting you know how sloppy your thinking is&rdquo; by Leslie Lamport. The very act of writing the design document helps to clarify the design itself. It also helps people to learn or understand the system in the future.</p>

<h3><a href="http://blog.jjyao.me/blog/2021/08/18/keep-your-eyes-open/">Keep your eyes open</a></h3>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Keep Your Eyes Open]]></title>
    <link href="http://blog.jjyao.me/blog/2021/08/18/keep-your-eyes-open/"/>
    <updated>2021-08-18T08:10:01-07:00</updated>
    <id>http://blog.jjyao.me/blog/2021/08/18/keep-your-eyes-open</id>
    <content type="html"><![CDATA[<p>As engineers, our job is to solve problems. In order to do that, we need to discover them first. To me, the best way to find problems is through doing things while keeping the eyes open.</p>

<!-- more -->


<p>Problems are everywhere, it&rsquo;s just whether we can find them or not. Whenever we are doing some task, it&rsquo;s not just about finishing the task itself, it&rsquo;s also about discovering new problems along the way. Here we have a cycle of <code>doing things -&gt; discovering problems -&gt; doing more things</code>. Through this cycle, we make whatever we are building better and better.</p>

<p>If we treat everything we do as an opportunity of discovering new problems, then we will find tons of them. To make this more concrete, let me give some examples:</p>

<ul>
<li>Whenever we touch a piece of code, even just one line, it&rsquo;s an opportunity to look at the surrounding code and see if we can refactor to make it better.</li>
<li>Whenever we do some repetitive work, it&rsquo;s an opportunity to automate it.</li>
<li>Whenever we talk to clients, it&rsquo;s an opportunity to learn their pain points.</li>
</ul>


<p>Amar Bose also told an interesting <a href="https://www.youtube.com/watch?v=ySAXW-7WrDg">story</a> where the student with the eyes open saw a huge opportunity while doing a quite tedious work.</p>

<p>Keep your eyes open, problems and opportunities are around you.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Response Time and Throughput]]></title>
    <link href="http://blog.jjyao.me/blog/2021/04/04/response-time-and-throughput/"/>
    <updated>2021-04-04T13:43:32-07:00</updated>
    <id>http://blog.jjyao.me/blog/2021/04/04/response-time-and-throughput</id>
    <content type="html"><![CDATA[<p>For the discussion of this post, response time is the time between a service receiving a request and returning a response. It is the sum of waiting time and processing time. Waiting time is how long the request waits in queues before being processed. Processing time is the time to actually do the work of the request. Throughput is the number of requests that are completed per unit time. This post discusses how they can be possibly related.</p>

<!-- more -->


<h2>Lower Processing Time &amp; Higher Throughput</h2>

<p>If we reduce the processing time, the throughput might be higher. For example, the throughput is 10 requests per second if the processing time is 100ms CPU time assuming it&rsquo;s a single CPU system. If the processing time is reduced to 10ms CPU time, the throughput is increased to 100 requests per second.</p>

<h2>Higher Processing Time &amp; Lower Throughput</h2>

<p>This is the opposite of lower processing time &amp; higher throughput. This is undesirable since we lose both processing time and throughput.</p>

<h2>Lower Processing Time &amp; Lower Throughput</h2>

<p>By optimizing the part of the system that&rsquo;s not the throughput bottleneck, the throughput keeps the same or is even lower. For example, the request processing time is 100ms CPU time and 10ms IO time. Since the request is CPU bound, reducing the IO time will bring down the overall processing time but throughput will still be the same: 10 requests per second. If reducing the IO time comes with the cost of increasing the CPU time (say CPU time becomes 101ms and IO time becomes 5ms), the throughput is actually lower even though the processing time is also lower.</p>

<h2>Higher Processing Time &amp; Higher Throughput</h2>

<p>If we can reduce the time spent on the bottleneck part of the system at the cost of increasing overall processing time, we can get higher throughput. Lets still use the request with 100ms CPU time and 10ms IO time as an example. If we can reduce the CPU time to 90ms at the cost of increasing the IO time to 30ms, the throughput is higher now even though the overall processing time is also higher.</p>

<h2>Higher Waiting Time &amp; Higher Throughput</h2>

<p>The maximum throughput we can get is 10 requests per second if the processing time is 100ms CPU time. To achieve that maximum throughput, we need to make sure the CPU is busy all the time (i.e. 100% utilization). In other words, there is always a request in the queue waitting to be processed as soon as the CPU finishes the current request. Basically we want requests to wait for CPU instead of CPU waiting for requests. By having requests wait for CPU, we incur some waiting time to achieve the higher (maximum) throughput.</p>

<h2>Lower Waiting Time &amp; Lower Throughput</h2>

<p>This is the opposite of higher waiting time &amp; higher throughput. To make sure the waiting time is zero, we need to make sure the CPU is idle and there is no other requests in the queue by the time when the request is received. By having CPU idle for some time, the throughput will be lower than the maximum throughput.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Nondeterministic Code]]></title>
    <link href="http://blog.jjyao.me/blog/2021/02/26/nondeterministic-code/"/>
    <updated>2021-02-26T16:11:07-08:00</updated>
    <id>http://blog.jjyao.me/blog/2021/02/26/nondeterministic-code</id>
    <content type="html"><![CDATA[<p>Nondeterministic code is hard to debug since bugs are not consistently reproducible. It&rsquo;s easy to notice that the code is perhaps nondeterministic if multi-threading or random functions are involved. However we can still write nondeterministic single-threaded code without using random functions.</p>

<!-- more -->


<h2>Random Address</h2>

<p><a href="https://en.wikipedia.org/wiki/Address_space_layout_randomization">Address space layout randomization</a> randomly arranges the address space positions of stack and heap of a process, which means the address of a variable changes for each run. This is the source of nondeterminism if we try to iterate through an unordered container of pointers.</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
</pre></td><td class='code'><pre><code class='cpp'><span class='line'><span class="cp">#include &lt;iostream&gt;</span>
</span><span class='line'><span class="cp">#include &lt;unordered_set&gt;</span>
</span><span class='line'>
</span><span class='line'><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'>  <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">a</span> <span class="o">=</span> <span class="s">&quot;aaaaa&quot;</span><span class="p">;</span>
</span><span class='line'>  <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">b</span> <span class="o">=</span> <span class="s">&quot;bb&quot;</span><span class="p">;</span>
</span><span class='line'>  <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">c</span> <span class="o">=</span> <span class="s">&quot;cccccccccccc&quot;</span><span class="p">;</span>
</span><span class='line'>  <span class="n">std</span><span class="o">::</span><span class="n">unordered_set</span><span class="o">&lt;</span><span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">*&gt;</span> <span class="n">set</span><span class="p">;</span>
</span><span class='line'>  <span class="n">set</span><span class="p">.</span><span class="n">emplace</span><span class="p">(</span><span class="o">&amp;</span><span class="n">a</span><span class="p">);</span>
</span><span class='line'>  <span class="n">set</span><span class="p">.</span><span class="n">emplace</span><span class="p">(</span><span class="o">&amp;</span><span class="n">b</span><span class="p">);</span>
</span><span class='line'>  <span class="n">set</span><span class="p">.</span><span class="n">emplace</span><span class="p">(</span><span class="o">&amp;</span><span class="n">c</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'>  <span class="k">for</span> <span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">*</span> <span class="nl">p</span> <span class="p">:</span> <span class="n">set</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>    <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="o">*</span><span class="n">p</span> <span class="o">&lt;&lt;</span> <span class="s">&quot;(&quot;</span> <span class="o">&lt;&lt;</span> <span class="n">p</span> <span class="o">&lt;&lt;</span> <span class="s">&quot;, &quot;</span> <span class="o">&lt;&lt;</span> <span class="n">std</span><span class="o">::</span><span class="n">hash</span><span class="o">&lt;</span><span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">*&gt;</span><span class="p">{}(</span><span class="n">p</span><span class="p">)</span> <span class="o">&lt;&lt;</span> <span class="s">&quot;)&quot;</span> <span class="o">&lt;&lt;</span> <span class="n">std</span><span class="o">::</span><span class="n">endl</span><span class="p">;</span>
</span><span class='line'>  <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>  <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>




<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
</pre></td><td class='code'><pre><code class='cpp'><span class='line'><span class="o">&gt;</span> <span class="n">clang</span><span class="o">++</span> <span class="n">demo</span><span class="p">.</span><span class="n">cc</span> <span class="o">-</span><span class="n">o</span> <span class="n">demo</span> <span class="o">-</span><span class="n">std</span><span class="o">=</span><span class="n">c</span><span class="o">++</span><span class="mi">11</span>
</span><span class='line'><span class="o">&gt;</span> <span class="p">.</span><span class="o">/</span><span class="n">demo</span>
</span><span class='line'><span class="n">cccccccccccc</span><span class="p">(</span><span class="mh">0x7ffeeedbf650</span><span class="p">,</span> <span class="mi">16564608384425460261</span><span class="p">)</span>
</span><span class='line'><span class="n">bb</span><span class="p">(</span><span class="mh">0x7ffeeedbf678</span><span class="p">,</span> <span class="mi">5964435063914947271</span><span class="p">)</span>
</span><span class='line'><span class="n">aaaaa</span><span class="p">(</span><span class="mh">0x7ffeeedbf690</span><span class="p">,</span> <span class="mi">696214236533423747</span><span class="p">)</span>
</span><span class='line'><span class="o">&gt;</span> <span class="p">.</span><span class="o">/</span><span class="n">demo</span>
</span><span class='line'><span class="n">bb</span><span class="p">(</span><span class="mh">0x7ffee3cd6678</span><span class="p">,</span> <span class="mi">2875564916106665130</span><span class="p">)</span>
</span><span class='line'><span class="n">cccccccccccc</span><span class="p">(</span><span class="mh">0x7ffee3cd6650</span><span class="p">,</span> <span class="mi">14656991250807877473</span><span class="p">)</span>
</span><span class='line'><span class="n">aaaaa</span><span class="p">(</span><span class="mh">0x7ffee3cd6690</span><span class="p">,</span> <span class="mi">10500981134548248633</span><span class="p">)</span>
</span></code></pre></td></tr></table></div></figure>


<p>As we can see, the address of variable a, b and c keeps changing for each run, which affects their positions in the hash set and, as a result, we will iterate them in different orders.</p>

<p>Lets try to <a href="https://stackoverflow.com/questions/23897963/documented-way-to-disable-aslr-on-os-x">disable</a> ASLR and verify that the nondeterminism is gone:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
</pre></td><td class='code'><pre><code class='cpp'><span class='line'><span class="o">&gt;</span> <span class="n">clang</span><span class="o">++</span> <span class="n">demo</span><span class="p">.</span><span class="n">cc</span> <span class="o">-</span><span class="n">o</span> <span class="n">demo</span> <span class="o">-</span><span class="n">std</span><span class="o">=</span><span class="n">c</span><span class="o">++</span><span class="mi">11</span> <span class="o">-</span><span class="n">Wl</span><span class="p">,</span><span class="o">-</span><span class="n">no_pie</span>
</span><span class='line'><span class="o">&gt;</span> <span class="p">.</span><span class="o">/</span><span class="n">demo</span>
</span><span class='line'><span class="n">bb</span><span class="p">(</span><span class="mh">0x7ffeefbff678</span><span class="p">,</span> <span class="mi">6189850235780456993</span><span class="p">)</span>
</span><span class='line'><span class="n">cccccccccccc</span><span class="p">(</span><span class="mh">0x7ffeefbff650</span><span class="p">,</span> <span class="mi">14250952053958696967</span><span class="p">)</span>
</span><span class='line'><span class="n">aaaaa</span><span class="p">(</span><span class="mh">0x7ffeefbff690</span><span class="p">,</span> <span class="mi">4593858558987980877</span><span class="p">)</span>
</span><span class='line'><span class="o">&gt;</span> <span class="p">.</span><span class="o">/</span><span class="n">demo</span>
</span><span class='line'><span class="n">bb</span><span class="p">(</span><span class="mh">0x7ffeefbff678</span><span class="p">,</span> <span class="mi">6189850235780456993</span><span class="p">)</span>
</span><span class='line'><span class="n">cccccccccccc</span><span class="p">(</span><span class="mh">0x7ffeefbff650</span><span class="p">,</span> <span class="mi">14250952053958696967</span><span class="p">)</span>
</span><span class='line'><span class="n">aaaaa</span><span class="p">(</span><span class="mh">0x7ffeefbff690</span><span class="p">,</span> <span class="mi">4593858558987980877</span><span class="p">)</span>
</span></code></pre></td></tr></table></div></figure>


<p>Since the nondeterminism is generally undesired, clang has a <a href="https://clang.llvm.org/docs/analyzer/checkers.html#alpha-nondeterminism-pointeriteration-c">checker</a> to detect such usages.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[JIT in Action]]></title>
    <link href="http://blog.jjyao.me/blog/2021/01/16/jit-in-action/"/>
    <updated>2021-01-16T22:23:27-08:00</updated>
    <id>http://blog.jjyao.me/blog/2021/01/16/jit-in-action</id>
    <content type="html"><![CDATA[<p><a href="https://en.wikipedia.org/wiki/Just-in-time_compilation">JIT</a> is a way of executing computer code that involves compilation during execution of a program at <strong>runtime</strong>. This post shows how to execute <a href="https://en.wikipedia.org/wiki/Brainfuck">Brainfuck</a> programs using JIT in various ways.</p>

<ol>
<li><a href="#interpreter">Interpreter</a></li>
<li><a href="#transpilation">Transpilation</a></li>
<li><a href="#llvm">LLVM</a></li>
<li><a href="#dynasm">DynASM</a></li>
</ol>


<!-- more -->


<h2><a id="interpreter"></a>Interpreter</h2>

<p>Before showing how to use JIT to run a Brainfuck program, lets see how it can be run by an interpreter.</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
<span class='line-number'>32</span>
<span class='line-number'>33</span>
<span class='line-number'>34</span>
<span class='line-number'>35</span>
<span class='line-number'>36</span>
<span class='line-number'>37</span>
<span class='line-number'>38</span>
<span class='line-number'>39</span>
<span class='line-number'>40</span>
<span class='line-number'>41</span>
<span class='line-number'>42</span>
<span class='line-number'>43</span>
<span class='line-number'>44</span>
<span class='line-number'>45</span>
<span class='line-number'>46</span>
<span class='line-number'>47</span>
<span class='line-number'>48</span>
<span class='line-number'>49</span>
<span class='line-number'>50</span>
<span class='line-number'>51</span>
<span class='line-number'>52</span>
<span class='line-number'>53</span>
<span class='line-number'>54</span>
<span class='line-number'>55</span>
<span class='line-number'>56</span>
<span class='line-number'>57</span>
<span class='line-number'>58</span>
<span class='line-number'>59</span>
<span class='line-number'>60</span>
<span class='line-number'>61</span>
<span class='line-number'>62</span>
<span class='line-number'>63</span>
<span class='line-number'>64</span>
<span class='line-number'>65</span>
<span class='line-number'>66</span>
<span class='line-number'>67</span>
<span class='line-number'>68</span>
<span class='line-number'>69</span>
<span class='line-number'>70</span>
<span class='line-number'>71</span>
<span class='line-number'>72</span>
<span class='line-number'>73</span>
<span class='line-number'>74</span>
<span class='line-number'>75</span>
<span class='line-number'>76</span>
<span class='line-number'>77</span>
<span class='line-number'>78</span>
<span class='line-number'>79</span>
<span class='line-number'>80</span>
<span class='line-number'>81</span>
<span class='line-number'>82</span>
<span class='line-number'>83</span>
</pre></td><td class='code'><pre><code class='cpp'><span class='line'><span class="cp">#include &lt;cstdio&gt;</span>
</span><span class='line'><span class="cp">#include &lt;cstdlib&gt;</span>
</span><span class='line'><span class="cp">#include &lt;string&gt;</span>
</span><span class='line'><span class="cp">#include &lt;vector&gt;</span>
</span><span class='line'><span class="cp">#include &lt;fstream&gt;</span>
</span><span class='line'><span class="cp">#include &lt;streambuf&gt;</span>
</span><span class='line'>
</span><span class='line'><span class="k">class</span> <span class="nc">BrainfuckInterpreter</span> <span class="p">{</span>
</span><span class='line'>  <span class="k">public</span><span class="o">:</span>
</span><span class='line'>    <span class="n">BrainfuckInterpreter</span><span class="p">(</span><span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&amp;</span> <span class="n">program</span><span class="p">)</span>
</span><span class='line'>      <span class="o">:</span> <span class="n">program</span><span class="p">(</span><span class="n">program</span><span class="p">)</span> <span class="p">{}</span>
</span><span class='line'>
</span><span class='line'>    <span class="kt">void</span> <span class="n">run</span><span class="p">();</span>
</span><span class='line'>
</span><span class='line'>  <span class="k">private</span><span class="o">:</span>
</span><span class='line'>    <span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">program</span><span class="p">;</span>
</span><span class='line'><span class="p">};</span>
</span><span class='line'>
</span><span class='line'><span class="kt">void</span> <span class="n">BrainfuckInterpreter</span><span class="o">::</span><span class="n">run</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'>  <span class="kt">char</span> <span class="n">data</span><span class="p">[</span><span class="mi">30000</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">0</span><span class="p">};</span>
</span><span class='line'>  <span class="kt">char</span><span class="o">*</span> <span class="n">ptr</span> <span class="o">=</span> <span class="n">data</span><span class="p">;</span>
</span><span class='line'>  <span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">size_t</span><span class="o">&gt;</span> <span class="n">stack</span><span class="p">;</span>
</span><span class='line'>  <span class="kt">size_t</span> <span class="n">skips</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'>  <span class="k">for</span> <span class="p">(</span><span class="kt">size_t</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">program</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="o">++</span><span class="n">i</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>    <span class="k">switch</span><span class="p">(</span><span class="n">program</span><span class="p">[</span><span class="n">i</span><span class="p">])</span> <span class="p">{</span>
</span><span class='line'>      <span class="k">case</span> <span class="sc">&#39;&gt;&#39;</span><span class="o">:</span>
</span><span class='line'>        <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">skips</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>          <span class="o">++</span><span class="n">ptr</span><span class="p">;</span>
</span><span class='line'>        <span class="p">}</span>
</span><span class='line'>        <span class="k">break</span><span class="p">;</span>
</span><span class='line'>      <span class="k">case</span> <span class="sc">&#39;&lt;&#39;</span><span class="o">:</span>
</span><span class='line'>        <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">skips</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>          <span class="o">--</span><span class="n">ptr</span><span class="p">;</span>
</span><span class='line'>        <span class="p">}</span>
</span><span class='line'>        <span class="k">break</span><span class="p">;</span>
</span><span class='line'>      <span class="k">case</span> <span class="sc">&#39;+&#39;</span><span class="o">:</span>
</span><span class='line'>        <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">skips</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>          <span class="o">++*</span><span class="n">ptr</span><span class="p">;</span>
</span><span class='line'>        <span class="p">}</span>
</span><span class='line'>        <span class="k">break</span><span class="p">;</span>
</span><span class='line'>      <span class="k">case</span> <span class="sc">&#39;-&#39;</span><span class="o">:</span>
</span><span class='line'>        <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">skips</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>          <span class="o">--*</span><span class="n">ptr</span><span class="p">;</span>
</span><span class='line'>        <span class="p">}</span>
</span><span class='line'>        <span class="k">break</span><span class="p">;</span>
</span><span class='line'>      <span class="k">case</span> <span class="sc">&#39;.&#39;</span><span class="o">:</span>
</span><span class='line'>        <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">skips</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>          <span class="n">putchar</span><span class="p">(</span><span class="k">static_cast</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span><span class="p">(</span><span class="o">*</span><span class="n">ptr</span><span class="p">));</span>
</span><span class='line'>        <span class="p">}</span>
</span><span class='line'>        <span class="k">break</span><span class="p">;</span>
</span><span class='line'>      <span class="k">case</span> <span class="sc">&#39;,&#39;</span><span class="o">:</span>
</span><span class='line'>        <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">skips</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>          <span class="o">*</span><span class="n">ptr</span> <span class="o">=</span> <span class="k">static_cast</span><span class="o">&lt;</span><span class="kt">char</span><span class="o">&gt;</span><span class="p">(</span><span class="n">getchar</span><span class="p">());</span>
</span><span class='line'>        <span class="p">}</span>
</span><span class='line'>        <span class="k">break</span><span class="p">;</span>
</span><span class='line'>      <span class="k">case</span> <span class="sc">&#39;[&#39;</span><span class="o">:</span>
</span><span class='line'>        <span class="n">stack</span><span class="p">.</span><span class="n">emplace_back</span><span class="p">(</span><span class="n">i</span><span class="p">);</span>
</span><span class='line'>        <span class="k">if</span> <span class="p">(</span><span class="o">!*</span><span class="n">ptr</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>          <span class="o">++</span><span class="n">skips</span><span class="p">;</span>
</span><span class='line'>        <span class="p">}</span>
</span><span class='line'>        <span class="k">break</span><span class="p">;</span>
</span><span class='line'>      <span class="k">case</span> <span class="sc">&#39;]&#39;</span><span class="o">:</span>
</span><span class='line'>        <span class="k">if</span> <span class="p">(</span><span class="o">*</span><span class="n">ptr</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>          <span class="n">i</span> <span class="o">=</span> <span class="o">*</span><span class="p">(</span><span class="n">stack</span><span class="p">.</span><span class="n">end</span><span class="p">()</span> <span class="o">-</span> <span class="mi">1</span><span class="p">);</span>
</span><span class='line'>        <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
</span><span class='line'>          <span class="n">stack</span><span class="p">.</span><span class="n">pop_back</span><span class="p">();</span>
</span><span class='line'>        <span class="p">}</span>
</span><span class='line'>        <span class="k">if</span> <span class="p">(</span><span class="n">skips</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>          <span class="o">--</span><span class="n">skips</span><span class="p">;</span>
</span><span class='line'>        <span class="p">}</span>
</span><span class='line'>        <span class="k">break</span><span class="p">;</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>  <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="kt">int</span> <span class="n">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span><span class="o">**</span> <span class="n">argv</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>  <span class="n">std</span><span class="o">::</span><span class="n">ifstream</span> <span class="n">ifs</span><span class="p">(</span><span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">]);</span>
</span><span class='line'>  <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">program</span><span class="p">((</span><span class="n">std</span><span class="o">::</span><span class="n">istreambuf_iterator</span><span class="o">&lt;</span><span class="kt">char</span><span class="o">&gt;</span><span class="p">(</span><span class="n">ifs</span><span class="p">)),</span> <span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">istreambuf_iterator</span><span class="o">&lt;</span><span class="kt">char</span><span class="o">&gt;</span><span class="p">()));</span>
</span><span class='line'>  <span class="n">BrainfuckInterpreter</span> <span class="nf">interpreter</span><span class="p">(</span><span class="n">program</span><span class="p">);</span>
</span><span class='line'>  <span class="n">interpreter</span><span class="p">.</span><span class="n">run</span><span class="p">();</span>
</span><span class='line'>  <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>




<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='cpp'><span class='line'><span class="n">g</span><span class="o">++</span> <span class="o">-</span><span class="n">std</span><span class="o">=</span><span class="n">c</span><span class="o">++</span><span class="mi">11</span> <span class="o">-</span><span class="n">o</span> <span class="n">brainfuck</span> <span class="n">brainfuck</span><span class="p">.</span><span class="n">cc</span>
</span><span class='line'>
</span><span class='line'><span class="p">.</span><span class="o">/</span><span class="n">brainfuck</span> <span class="n">program</span><span class="p">.</span><span class="n">bf</span>
</span></code></pre></td></tr></table></div></figure>


<p>For a complicated Brainfuck program like <a href="https://www.google.com/search?q=mandelbrot.bf">mandelbrot.bf</a>, running in an interpreter will be slow.</p>

<h2><a id="transpilation"></a>Transpilation</h2>

<p>One way to generate and run native code for a Brainfuck program is transpilaiton. The first step is generating the equivalent C/C++ code for the Brainfuck program and then using a conventional compiler to generate a shared object. The second step is using <code>dlopen()</code> to load the shared object and run it.</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
<span class='line-number'>32</span>
<span class='line-number'>33</span>
<span class='line-number'>34</span>
<span class='line-number'>35</span>
<span class='line-number'>36</span>
<span class='line-number'>37</span>
<span class='line-number'>38</span>
<span class='line-number'>39</span>
<span class='line-number'>40</span>
<span class='line-number'>41</span>
<span class='line-number'>42</span>
<span class='line-number'>43</span>
<span class='line-number'>44</span>
<span class='line-number'>45</span>
<span class='line-number'>46</span>
<span class='line-number'>47</span>
<span class='line-number'>48</span>
<span class='line-number'>49</span>
<span class='line-number'>50</span>
<span class='line-number'>51</span>
<span class='line-number'>52</span>
<span class='line-number'>53</span>
<span class='line-number'>54</span>
<span class='line-number'>55</span>
<span class='line-number'>56</span>
<span class='line-number'>57</span>
<span class='line-number'>58</span>
<span class='line-number'>59</span>
<span class='line-number'>60</span>
<span class='line-number'>61</span>
<span class='line-number'>62</span>
<span class='line-number'>63</span>
<span class='line-number'>64</span>
<span class='line-number'>65</span>
<span class='line-number'>66</span>
<span class='line-number'>67</span>
<span class='line-number'>68</span>
<span class='line-number'>69</span>
<span class='line-number'>70</span>
<span class='line-number'>71</span>
<span class='line-number'>72</span>
<span class='line-number'>73</span>
<span class='line-number'>74</span>
<span class='line-number'>75</span>
<span class='line-number'>76</span>
<span class='line-number'>77</span>
<span class='line-number'>78</span>
<span class='line-number'>79</span>
<span class='line-number'>80</span>
<span class='line-number'>81</span>
<span class='line-number'>82</span>
<span class='line-number'>83</span>
<span class='line-number'>84</span>
<span class='line-number'>85</span>
<span class='line-number'>86</span>
<span class='line-number'>87</span>
<span class='line-number'>88</span>
<span class='line-number'>89</span>
<span class='line-number'>90</span>
<span class='line-number'>91</span>
<span class='line-number'>92</span>
<span class='line-number'>93</span>
<span class='line-number'>94</span>
<span class='line-number'>95</span>
<span class='line-number'>96</span>
</pre></td><td class='code'><pre><code class='cpp'><span class='line'><span class="cp">#include &lt;dlfcn.h&gt;</span>
</span><span class='line'><span class="cp">#include &lt;cstdio&gt;</span>
</span><span class='line'><span class="cp">#include &lt;cstdlib&gt;</span>
</span><span class='line'><span class="cp">#include &lt;string&gt;</span>
</span><span class='line'><span class="cp">#include &lt;vector&gt;</span>
</span><span class='line'><span class="cp">#include &lt;fstream&gt;</span>
</span><span class='line'><span class="cp">#include &lt;iostream&gt;</span>
</span><span class='line'><span class="cp">#include &lt;streambuf&gt;</span>
</span><span class='line'>
</span><span class='line'><span class="k">class</span> <span class="nc">BrainfuckTranspiler</span> <span class="p">{</span>
</span><span class='line'>  <span class="k">public</span><span class="o">:</span>
</span><span class='line'>    <span class="n">BrainfuckTranspiler</span><span class="p">(</span><span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&amp;</span> <span class="n">program</span><span class="p">)</span>
</span><span class='line'>      <span class="o">:</span> <span class="n">program</span><span class="p">(</span><span class="n">program</span><span class="p">)</span> <span class="p">{}</span>
</span><span class='line'>
</span><span class='line'>    <span class="kt">void</span> <span class="n">run</span><span class="p">();</span>
</span><span class='line'>
</span><span class='line'>  <span class="k">private</span><span class="o">:</span>
</span><span class='line'>    <span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">program</span><span class="p">;</span>
</span><span class='line'><span class="p">};</span>
</span><span class='line'>
</span><span class='line'><span class="kt">void</span> <span class="n">BrainfuckTranspiler</span><span class="o">::</span><span class="n">run</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'>  <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">ccname</span> <span class="o">=</span> <span class="n">std</span><span class="o">::</span><span class="n">tmpnam</span><span class="p">(</span><span class="k">nullptr</span><span class="p">);</span>
</span><span class='line'>  <span class="n">ccname</span> <span class="o">+=</span> <span class="s">&quot;.cc&quot;</span><span class="p">;</span>
</span><span class='line'>  <span class="n">std</span><span class="o">::</span><span class="n">ofstream</span> <span class="n">ofs</span><span class="p">;</span>
</span><span class='line'>  <span class="n">ofs</span><span class="p">.</span><span class="n">open</span><span class="p">(</span><span class="n">ccname</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'>  <span class="n">ofs</span> <span class="o">&lt;&lt;</span> <span class="n">R</span><span class="s">&quot;(</span>
</span><span class='line'><span class="cp">#include &lt;cstdio&gt;</span>
</span><span class='line'><span class="cp">#include &lt;vector&gt;</span>
</span><span class='line'>
</span><span class='line'><span class="k">extern</span> <span class="s">&quot;C&quot;</span> <span class="kt">void</span> <span class="n">_run</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'>  <span class="kt">char</span> <span class="n">data</span><span class="p">[</span><span class="mi">30000</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">0</span><span class="p">};</span>
</span><span class='line'>  <span class="kt">char</span><span class="o">*</span> <span class="n">ptr</span> <span class="o">=</span> <span class="n">data</span><span class="p">;</span>
</span><span class='line'>  <span class="p">)</span><span class="s">&quot;;</span>
</span><span class='line'>
</span><span class='line'>  <span class="k">for</span> <span class="p">(</span><span class="kt">size_t</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">program</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="o">++</span><span class="n">i</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>    <span class="k">switch</span><span class="p">(</span><span class="n">program</span><span class="p">[</span><span class="n">i</span><span class="p">])</span> <span class="p">{</span>
</span><span class='line'>      <span class="k">case</span> <span class="sc">&#39;&gt;&#39;</span><span class="o">:</span>
</span><span class='line'>        <span class="n">ofs</span> <span class="o">&lt;&lt;</span> <span class="s">&quot;++ptr;&quot;</span> <span class="o">&lt;&lt;</span> <span class="n">std</span><span class="o">::</span><span class="n">endl</span><span class="p">;</span>
</span><span class='line'>        <span class="k">break</span><span class="p">;</span>
</span><span class='line'>      <span class="k">case</span> <span class="sc">&#39;&lt;&#39;</span><span class="o">:</span>
</span><span class='line'>        <span class="n">ofs</span> <span class="o">&lt;&lt;</span> <span class="s">&quot;--ptr;&quot;</span> <span class="o">&lt;&lt;</span> <span class="n">std</span><span class="o">::</span><span class="n">endl</span><span class="p">;</span>
</span><span class='line'>        <span class="k">break</span><span class="p">;</span>
</span><span class='line'>      <span class="k">case</span> <span class="sc">&#39;+&#39;</span><span class="o">:</span>
</span><span class='line'>        <span class="n">ofs</span> <span class="o">&lt;&lt;</span> <span class="s">&quot;++*ptr;&quot;</span> <span class="o">&lt;&lt;</span> <span class="n">std</span><span class="o">::</span><span class="n">endl</span><span class="p">;</span>
</span><span class='line'>        <span class="k">break</span><span class="p">;</span>
</span><span class='line'>      <span class="k">case</span> <span class="sc">&#39;-&#39;</span><span class="o">:</span>
</span><span class='line'>        <span class="n">ofs</span> <span class="o">&lt;&lt;</span> <span class="s">&quot;--*ptr;&quot;</span> <span class="o">&lt;&lt;</span> <span class="n">std</span><span class="o">::</span><span class="n">endl</span><span class="p">;</span>
</span><span class='line'>        <span class="k">break</span><span class="p">;</span>
</span><span class='line'>      <span class="k">case</span> <span class="sc">&#39;.&#39;</span><span class="o">:</span>
</span><span class='line'>        <span class="n">ofs</span> <span class="o">&lt;&lt;</span> <span class="s">&quot;putchar(static_cast&lt;int&gt;(*ptr));&quot;</span> <span class="o">&lt;&lt;</span> <span class="n">std</span><span class="o">::</span><span class="n">endl</span><span class="p">;</span>
</span><span class='line'>        <span class="k">break</span><span class="p">;</span>
</span><span class='line'>      <span class="k">case</span> <span class="sc">&#39;,&#39;</span><span class="o">:</span>
</span><span class='line'>        <span class="n">ofs</span> <span class="o">&lt;&lt;</span> <span class="s">&quot;*ptr = static_cast&lt;char&gt;(getchar());&quot;</span> <span class="o">&lt;&lt;</span> <span class="n">std</span><span class="o">::</span><span class="n">endl</span><span class="p">;</span>
</span><span class='line'>        <span class="k">break</span><span class="p">;</span>
</span><span class='line'>      <span class="k">case</span> <span class="sc">&#39;[&#39;</span><span class="o">:</span>
</span><span class='line'>        <span class="n">ofs</span> <span class="o">&lt;&lt;</span> <span class="s">&quot;while (*ptr) {&quot;</span> <span class="o">&lt;&lt;</span> <span class="n">std</span><span class="o">::</span><span class="n">endl</span><span class="p">;</span>
</span><span class='line'>        <span class="k">break</span><span class="p">;</span>
</span><span class='line'>      <span class="k">case</span> <span class="sc">&#39;]&#39;</span><span class="o">:</span>
</span><span class='line'>        <span class="n">ofs</span> <span class="o">&lt;&lt;</span> <span class="s">&quot;}&quot;</span> <span class="o">&lt;&lt;</span> <span class="n">std</span><span class="o">::</span><span class="n">endl</span><span class="p">;</span>
</span><span class='line'>        <span class="k">break</span><span class="p">;</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>  <span class="p">}</span>
</span><span class='line'>  <span class="n">ofs</span> <span class="o">&lt;&lt;</span> <span class="s">&quot;}&quot;</span><span class="p">;</span>
</span><span class='line'>  <span class="n">ofs</span><span class="p">.</span><span class="n">close</span><span class="p">();</span>
</span><span class='line'>
</span><span class='line'>  <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">soname</span> <span class="o">=</span> <span class="n">std</span><span class="o">::</span><span class="n">tmpnam</span><span class="p">(</span><span class="k">nullptr</span><span class="p">);</span>
</span><span class='line'>  <span class="n">soname</span> <span class="o">+=</span> <span class="s">&quot;.so&quot;</span><span class="p">;</span>
</span><span class='line'>  <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">compile</span> <span class="o">=</span> <span class="s">&quot;g++ &quot;</span> <span class="o">+</span> <span class="n">ccname</span> <span class="o">+</span> <span class="s">&quot; -o &quot;</span> <span class="o">+</span> <span class="n">soname</span> <span class="o">+</span> <span class="s">&quot; -shared -fPIC&quot;</span><span class="p">;</span>
</span><span class='line'>  <span class="n">system</span><span class="p">(</span><span class="n">compile</span><span class="p">.</span><span class="n">c_str</span><span class="p">());</span>
</span><span class='line'>
</span><span class='line'>  <span class="kt">void</span><span class="o">*</span> <span class="n">handle</span> <span class="o">=</span> <span class="n">dlopen</span><span class="p">(</span><span class="n">soname</span><span class="p">.</span><span class="n">c_str</span><span class="p">(),</span> <span class="n">RTLD_NOW</span><span class="p">);</span>
</span><span class='line'>  <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">handle</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>    <span class="n">std</span><span class="o">::</span><span class="n">cerr</span> <span class="o">&lt;&lt;</span> <span class="n">dlerror</span><span class="p">()</span> <span class="o">&lt;&lt;</span> <span class="n">std</span><span class="o">::</span><span class="n">endl</span><span class="p">;</span>
</span><span class='line'>  <span class="p">}</span>
</span><span class='line'>  <span class="n">dlerror</span><span class="p">();</span>
</span><span class='line'>  <span class="kt">void</span> <span class="p">(</span><span class="o">*</span><span class="n">_run</span><span class="p">)();</span>
</span><span class='line'>  <span class="n">_run</span> <span class="o">=</span> <span class="p">(</span><span class="kt">void</span> <span class="p">(</span><span class="o">*</span><span class="p">)())</span> <span class="n">dlsym</span><span class="p">(</span><span class="n">handle</span><span class="p">,</span> <span class="s">&quot;_run&quot;</span><span class="p">);</span>
</span><span class='line'>  <span class="kt">char</span><span class="o">*</span> <span class="n">error</span> <span class="o">=</span> <span class="n">dlerror</span><span class="p">();</span>
</span><span class='line'>  <span class="k">if</span> <span class="p">(</span><span class="n">error</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>    <span class="n">std</span><span class="o">::</span><span class="n">cerr</span> <span class="o">&lt;&lt;</span> <span class="n">error</span> <span class="o">&lt;&lt;</span> <span class="n">std</span><span class="o">::</span><span class="n">endl</span><span class="p">;</span>
</span><span class='line'>  <span class="p">}</span>
</span><span class='line'>  <span class="p">(</span><span class="o">*</span><span class="n">_run</span><span class="p">)();</span>
</span><span class='line'>  <span class="n">dlclose</span><span class="p">(</span><span class="n">handle</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'>  <span class="n">remove</span><span class="p">(</span><span class="n">ccname</span><span class="p">.</span><span class="n">c_str</span><span class="p">());</span>
</span><span class='line'>  <span class="n">remove</span><span class="p">(</span><span class="n">soname</span><span class="p">.</span><span class="n">c_str</span><span class="p">());</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="kt">int</span> <span class="n">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span><span class="o">**</span> <span class="n">argv</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>  <span class="n">std</span><span class="o">::</span><span class="n">ifstream</span> <span class="n">ifs</span><span class="p">(</span><span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">]);</span>
</span><span class='line'>  <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">program</span><span class="p">((</span><span class="n">std</span><span class="o">::</span><span class="n">istreambuf_iterator</span><span class="o">&lt;</span><span class="kt">char</span><span class="o">&gt;</span><span class="p">(</span><span class="n">ifs</span><span class="p">)),</span> <span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">istreambuf_iterator</span><span class="o">&lt;</span><span class="kt">char</span><span class="o">&gt;</span><span class="p">()));</span>
</span><span class='line'>  <span class="n">BrainfuckTranspiler</span> <span class="nf">transpiler</span><span class="p">(</span><span class="n">program</span><span class="p">);</span>
</span><span class='line'>  <span class="n">transpiler</span><span class="p">.</span><span class="n">run</span><span class="p">();</span>
</span><span class='line'>  <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>




<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='cpp'><span class='line'><span class="n">g</span><span class="o">++</span> <span class="o">-</span><span class="n">std</span><span class="o">=</span><span class="n">c</span><span class="o">++</span><span class="mi">11</span> <span class="o">-</span><span class="n">ldl</span> <span class="o">-</span><span class="n">o</span> <span class="n">brainfuck</span> <span class="n">brainfuck</span><span class="p">.</span><span class="n">cc</span>
</span><span class='line'>
</span><span class='line'><span class="p">.</span><span class="o">/</span><span class="n">brainfuck</span> <span class="n">program</span><span class="p">.</span><span class="n">bf</span>
</span></code></pre></td></tr></table></div></figure>


<h2><a id="llvm"></a>LLVM</h2>

<p>Besides using an external compiler process to generate the native code, we can also use LLVM mcjit by first generating the equivalent LLVM IR for the Brainfuck program. We can generate the IR manually or using clang frontend. Here I&rsquo;m using clang to generate the IR but LLVM has an <a href="https://github.com/llvm/llvm-project/tree/main/llvm/examples/BrainF">example</a> of manually generating it. The LLVM version I&rsquo;m using is 7.0.1.</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
<span class='line-number'>32</span>
<span class='line-number'>33</span>
<span class='line-number'>34</span>
<span class='line-number'>35</span>
<span class='line-number'>36</span>
<span class='line-number'>37</span>
<span class='line-number'>38</span>
<span class='line-number'>39</span>
<span class='line-number'>40</span>
<span class='line-number'>41</span>
<span class='line-number'>42</span>
<span class='line-number'>43</span>
<span class='line-number'>44</span>
<span class='line-number'>45</span>
<span class='line-number'>46</span>
<span class='line-number'>47</span>
<span class='line-number'>48</span>
<span class='line-number'>49</span>
<span class='line-number'>50</span>
<span class='line-number'>51</span>
<span class='line-number'>52</span>
<span class='line-number'>53</span>
<span class='line-number'>54</span>
<span class='line-number'>55</span>
<span class='line-number'>56</span>
<span class='line-number'>57</span>
<span class='line-number'>58</span>
<span class='line-number'>59</span>
<span class='line-number'>60</span>
<span class='line-number'>61</span>
<span class='line-number'>62</span>
<span class='line-number'>63</span>
<span class='line-number'>64</span>
<span class='line-number'>65</span>
<span class='line-number'>66</span>
<span class='line-number'>67</span>
<span class='line-number'>68</span>
<span class='line-number'>69</span>
<span class='line-number'>70</span>
<span class='line-number'>71</span>
<span class='line-number'>72</span>
<span class='line-number'>73</span>
<span class='line-number'>74</span>
<span class='line-number'>75</span>
<span class='line-number'>76</span>
<span class='line-number'>77</span>
<span class='line-number'>78</span>
<span class='line-number'>79</span>
<span class='line-number'>80</span>
<span class='line-number'>81</span>
<span class='line-number'>82</span>
<span class='line-number'>83</span>
<span class='line-number'>84</span>
<span class='line-number'>85</span>
<span class='line-number'>86</span>
<span class='line-number'>87</span>
<span class='line-number'>88</span>
<span class='line-number'>89</span>
<span class='line-number'>90</span>
<span class='line-number'>91</span>
<span class='line-number'>92</span>
<span class='line-number'>93</span>
<span class='line-number'>94</span>
<span class='line-number'>95</span>
<span class='line-number'>96</span>
<span class='line-number'>97</span>
<span class='line-number'>98</span>
<span class='line-number'>99</span>
<span class='line-number'>100</span>
<span class='line-number'>101</span>
<span class='line-number'>102</span>
<span class='line-number'>103</span>
<span class='line-number'>104</span>
<span class='line-number'>105</span>
<span class='line-number'>106</span>
<span class='line-number'>107</span>
<span class='line-number'>108</span>
<span class='line-number'>109</span>
<span class='line-number'>110</span>
<span class='line-number'>111</span>
<span class='line-number'>112</span>
<span class='line-number'>113</span>
<span class='line-number'>114</span>
<span class='line-number'>115</span>
<span class='line-number'>116</span>
<span class='line-number'>117</span>
<span class='line-number'>118</span>
<span class='line-number'>119</span>
<span class='line-number'>120</span>
<span class='line-number'>121</span>
<span class='line-number'>122</span>
<span class='line-number'>123</span>
<span class='line-number'>124</span>
<span class='line-number'>125</span>
<span class='line-number'>126</span>
<span class='line-number'>127</span>
<span class='line-number'>128</span>
<span class='line-number'>129</span>
</pre></td><td class='code'><pre><code class='cpp'><span class='line'><span class="cp">#include &lt;cstdlib&gt;</span>
</span><span class='line'><span class="cp">#include &lt;string&gt;</span>
</span><span class='line'><span class="cp">#include &lt;vector&gt;</span>
</span><span class='line'><span class="cp">#include &lt;sstream&gt;</span>
</span><span class='line'><span class="cp">#include &lt;fstream&gt;</span>
</span><span class='line'><span class="cp">#include &lt;iostream&gt;</span>
</span><span class='line'><span class="cp">#include &lt;streambuf&gt;</span>
</span><span class='line'><span class="cp">#include &lt;clang/Driver/Compilation.h&gt;</span>
</span><span class='line'><span class="cp">#include &lt;clang/Driver/Driver.h&gt;</span>
</span><span class='line'><span class="cp">#include &lt;clang/CodeGen/CodeGenAction.h&gt;</span>
</span><span class='line'><span class="cp">#include &lt;clang/Frontend/FrontendOptions.h&gt;</span>
</span><span class='line'><span class="cp">#include &lt;clang/Frontend/CompilerInstance.h&gt;</span>
</span><span class='line'><span class="cp">#include &lt;clang/Frontend/CompilerInvocation.h&gt;</span>
</span><span class='line'><span class="cp">#include &lt;clang/Frontend/TextDiagnosticPrinter.h&gt;</span>
</span><span class='line'><span class="cp">#include &lt;llvm/IR/Module.h&gt;</span>
</span><span class='line'><span class="cp">#include &lt;llvm/ADT/StringRef.h&gt;</span>
</span><span class='line'><span class="cp">#include &lt;llvm/IR/LLVMContext.h&gt;</span>
</span><span class='line'><span class="cp">#include &lt;llvm/Support/Host.h&gt;</span>
</span><span class='line'><span class="cp">#include &lt;llvm/Support/TargetSelect.h&gt;</span>
</span><span class='line'><span class="cp">#include &lt;llvm/ExecutionEngine/ExecutionEngine.h&gt;</span>
</span><span class='line'><span class="cp">#include &lt;llvm/ExecutionEngine/GenericValue.h&gt;</span>
</span><span class='line'>
</span><span class='line'><span class="k">class</span> <span class="nc">BrainfuckLLVM</span> <span class="p">{</span>
</span><span class='line'>  <span class="k">public</span><span class="o">:</span>
</span><span class='line'>    <span class="n">BrainfuckLLVM</span><span class="p">(</span><span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&amp;</span> <span class="n">program</span><span class="p">,</span> <span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&amp;</span> <span class="n">clangexe</span><span class="p">)</span>
</span><span class='line'>      <span class="o">:</span> <span class="n">program</span><span class="p">(</span><span class="n">program</span><span class="p">),</span> <span class="n">clangexe</span><span class="p">(</span><span class="n">clangexe</span><span class="p">)</span> <span class="p">{}</span>
</span><span class='line'>
</span><span class='line'>    <span class="kt">void</span> <span class="n">run</span><span class="p">();</span>
</span><span class='line'>
</span><span class='line'>  <span class="k">private</span><span class="o">:</span>
</span><span class='line'>    <span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">program</span><span class="p">;</span>
</span><span class='line'>    <span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">clangexe</span><span class="p">;</span>
</span><span class='line'><span class="p">};</span>
</span><span class='line'>
</span><span class='line'><span class="kt">void</span> <span class="n">BrainfuckLLVM</span><span class="o">::</span><span class="n">run</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'>  <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">ccname</span> <span class="o">=</span> <span class="n">std</span><span class="o">::</span><span class="n">tmpnam</span><span class="p">(</span><span class="k">nullptr</span><span class="p">);</span>
</span><span class='line'>  <span class="n">ccname</span> <span class="o">+=</span> <span class="s">&quot;.cc&quot;</span><span class="p">;</span>
</span><span class='line'>  <span class="n">std</span><span class="o">::</span><span class="n">ofstream</span> <span class="n">ofs</span><span class="p">;</span>
</span><span class='line'>  <span class="n">ofs</span><span class="p">.</span><span class="n">open</span><span class="p">(</span><span class="n">ccname</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'>  <span class="n">ofs</span> <span class="o">&lt;&lt;</span> <span class="n">R</span><span class="s">&quot;(</span>
</span><span class='line'><span class="cp">#include &lt;cstdio&gt;</span>
</span><span class='line'><span class="cp">#include &lt;vector&gt;</span>
</span><span class='line'>
</span><span class='line'><span class="k">extern</span> <span class="s">&quot;C&quot;</span> <span class="kt">void</span> <span class="n">_run</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'>  <span class="kt">char</span> <span class="n">data</span><span class="p">[</span><span class="mi">30000</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">0</span><span class="p">};</span>
</span><span class='line'>  <span class="kt">char</span><span class="o">*</span> <span class="n">ptr</span> <span class="o">=</span> <span class="n">data</span><span class="p">;</span>
</span><span class='line'>  <span class="p">)</span><span class="s">&quot;;</span>
</span><span class='line'>
</span><span class='line'>  <span class="k">for</span> <span class="p">(</span><span class="kt">size_t</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">program</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="o">++</span><span class="n">i</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>    <span class="k">switch</span><span class="p">(</span><span class="n">program</span><span class="p">[</span><span class="n">i</span><span class="p">])</span> <span class="p">{</span>
</span><span class='line'>      <span class="k">case</span> <span class="sc">&#39;&gt;&#39;</span><span class="o">:</span>
</span><span class='line'>        <span class="n">ofs</span> <span class="o">&lt;&lt;</span> <span class="s">&quot;++ptr;&quot;</span> <span class="o">&lt;&lt;</span> <span class="n">std</span><span class="o">::</span><span class="n">endl</span><span class="p">;</span>
</span><span class='line'>        <span class="k">break</span><span class="p">;</span>
</span><span class='line'>      <span class="k">case</span> <span class="sc">&#39;&lt;&#39;</span><span class="o">:</span>
</span><span class='line'>        <span class="n">ofs</span> <span class="o">&lt;&lt;</span> <span class="s">&quot;--ptr;&quot;</span> <span class="o">&lt;&lt;</span> <span class="n">std</span><span class="o">::</span><span class="n">endl</span><span class="p">;</span>
</span><span class='line'>        <span class="k">break</span><span class="p">;</span>
</span><span class='line'>      <span class="k">case</span> <span class="sc">&#39;+&#39;</span><span class="o">:</span>
</span><span class='line'>        <span class="n">ofs</span> <span class="o">&lt;&lt;</span> <span class="s">&quot;++*ptr;&quot;</span> <span class="o">&lt;&lt;</span> <span class="n">std</span><span class="o">::</span><span class="n">endl</span><span class="p">;</span>
</span><span class='line'>        <span class="k">break</span><span class="p">;</span>
</span><span class='line'>      <span class="k">case</span> <span class="sc">&#39;-&#39;</span><span class="o">:</span>
</span><span class='line'>        <span class="n">ofs</span> <span class="o">&lt;&lt;</span> <span class="s">&quot;--*ptr;&quot;</span> <span class="o">&lt;&lt;</span> <span class="n">std</span><span class="o">::</span><span class="n">endl</span><span class="p">;</span>
</span><span class='line'>        <span class="k">break</span><span class="p">;</span>
</span><span class='line'>      <span class="k">case</span> <span class="sc">&#39;.&#39;</span><span class="o">:</span>
</span><span class='line'>        <span class="n">ofs</span> <span class="o">&lt;&lt;</span> <span class="s">&quot;putchar(static_cast&lt;int&gt;(*ptr));&quot;</span> <span class="o">&lt;&lt;</span> <span class="n">std</span><span class="o">::</span><span class="n">endl</span><span class="p">;</span>
</span><span class='line'>        <span class="k">break</span><span class="p">;</span>
</span><span class='line'>      <span class="k">case</span> <span class="sc">&#39;,&#39;</span><span class="o">:</span>
</span><span class='line'>        <span class="n">ofs</span> <span class="o">&lt;&lt;</span> <span class="s">&quot;*ptr = static_cast&lt;char&gt;(getchar());&quot;</span> <span class="o">&lt;&lt;</span> <span class="n">std</span><span class="o">::</span><span class="n">endl</span><span class="p">;</span>
</span><span class='line'>        <span class="k">break</span><span class="p">;</span>
</span><span class='line'>      <span class="k">case</span> <span class="sc">&#39;[&#39;</span><span class="o">:</span>
</span><span class='line'>        <span class="n">ofs</span> <span class="o">&lt;&lt;</span> <span class="s">&quot;while (*ptr) {&quot;</span> <span class="o">&lt;&lt;</span> <span class="n">std</span><span class="o">::</span><span class="n">endl</span><span class="p">;</span>
</span><span class='line'>        <span class="k">break</span><span class="p">;</span>
</span><span class='line'>      <span class="k">case</span> <span class="sc">&#39;]&#39;</span><span class="o">:</span>
</span><span class='line'>        <span class="n">ofs</span> <span class="o">&lt;&lt;</span> <span class="s">&quot;}&quot;</span> <span class="o">&lt;&lt;</span> <span class="n">std</span><span class="o">::</span><span class="n">endl</span><span class="p">;</span>
</span><span class='line'>        <span class="k">break</span><span class="p">;</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>  <span class="p">}</span>
</span><span class='line'>  <span class="n">ofs</span> <span class="o">&lt;&lt;</span> <span class="s">&quot;}&quot;</span><span class="p">;</span>
</span><span class='line'>  <span class="n">ofs</span><span class="p">.</span><span class="n">close</span><span class="p">();</span>
</span><span class='line'>
</span><span class='line'>  <span class="c1">// Generate LLVM IR using clang frontend</span>
</span><span class='line'>  <span class="n">clang</span><span class="o">::</span><span class="n">IntrusiveRefCntPtr</span><span class="o">&lt;</span><span class="n">clang</span><span class="o">::</span><span class="n">DiagnosticOptions</span><span class="o">&gt;</span> <span class="n">dopts</span> <span class="o">=</span> <span class="k">new</span> <span class="n">clang</span><span class="o">::</span><span class="n">DiagnosticOptions</span><span class="p">();</span>
</span><span class='line'>  <span class="n">clang</span><span class="o">::</span><span class="n">TextDiagnosticPrinter</span><span class="o">*</span> <span class="n">tdp</span> <span class="o">=</span> <span class="k">new</span> <span class="n">clang</span><span class="o">::</span><span class="n">TextDiagnosticPrinter</span><span class="p">(</span><span class="n">llvm</span><span class="o">::</span><span class="n">errs</span><span class="p">(),</span> <span class="o">&amp;*</span><span class="n">dopts</span><span class="p">);</span>
</span><span class='line'>  <span class="n">clang</span><span class="o">::</span><span class="n">IntrusiveRefCntPtr</span><span class="o">&lt;</span><span class="n">clang</span><span class="o">::</span><span class="n">DiagnosticIDs</span><span class="o">&gt;</span> <span class="n">dids</span><span class="p">(</span><span class="k">new</span> <span class="n">clang</span><span class="o">::</span><span class="n">DiagnosticIDs</span><span class="p">());</span>
</span><span class='line'>  <span class="n">clang</span><span class="o">::</span><span class="n">DiagnosticsEngine</span> <span class="n">dengine</span><span class="p">(</span><span class="n">dids</span><span class="p">,</span> <span class="o">&amp;*</span><span class="n">dopts</span><span class="p">,</span> <span class="n">tdp</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'>  <span class="n">llvm</span><span class="o">::</span><span class="n">Triple</span> <span class="n">triple</span><span class="p">(</span><span class="n">llvm</span><span class="o">::</span><span class="n">sys</span><span class="o">::</span><span class="n">getProcessTriple</span><span class="p">());</span>
</span><span class='line'>  <span class="n">clang</span><span class="o">::</span><span class="n">driver</span><span class="o">::</span><span class="n">Driver</span> <span class="n">driver</span><span class="p">(</span><span class="n">clangexe</span><span class="p">,</span> <span class="n">triple</span><span class="p">.</span><span class="n">str</span><span class="p">(),</span> <span class="n">dengine</span><span class="p">);</span>
</span><span class='line'>  <span class="n">driver</span><span class="p">.</span><span class="n">setTitle</span><span class="p">(</span><span class="s">&quot;clang&quot;</span><span class="p">);</span>
</span><span class='line'>  <span class="n">driver</span><span class="p">.</span><span class="n">setCheckInputsExist</span><span class="p">(</span><span class="nb">false</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'>  <span class="n">llvm</span><span class="o">::</span><span class="n">SmallVector</span><span class="o">&lt;</span><span class="k">const</span> <span class="kt">char</span><span class="o">*</span><span class="p">,</span> <span class="mi">16</span><span class="o">&gt;</span> <span class="n">args</span><span class="p">;</span>
</span><span class='line'>  <span class="n">args</span><span class="p">.</span><span class="n">push_back</span><span class="p">(</span><span class="s">&quot;clang&quot;</span><span class="p">);</span>
</span><span class='line'>  <span class="n">args</span><span class="p">.</span><span class="n">push_back</span><span class="p">(</span><span class="n">ccname</span><span class="p">.</span><span class="n">c_str</span><span class="p">());</span>
</span><span class='line'>  <span class="n">args</span><span class="p">.</span><span class="n">push_back</span><span class="p">(</span><span class="s">&quot;-fsyntax-only&quot;</span><span class="p">);</span>
</span><span class='line'>  <span class="n">std</span><span class="o">::</span><span class="n">unique_ptr</span><span class="o">&lt;</span><span class="n">clang</span><span class="o">::</span><span class="n">driver</span><span class="o">::</span><span class="n">Compilation</span><span class="o">&gt;</span> <span class="n">compilation</span><span class="p">(</span><span class="n">driver</span><span class="p">.</span><span class="n">BuildCompilation</span><span class="p">(</span><span class="n">args</span><span class="p">));</span>
</span><span class='line'>  <span class="k">const</span> <span class="n">clang</span><span class="o">::</span><span class="n">driver</span><span class="o">::</span><span class="n">JobList</span><span class="o">&amp;</span> <span class="n">jobs</span> <span class="o">=</span> <span class="n">compilation</span><span class="o">-&gt;</span><span class="n">getJobs</span><span class="p">();</span>
</span><span class='line'>  <span class="k">const</span> <span class="n">clang</span><span class="o">::</span><span class="n">driver</span><span class="o">::</span><span class="n">Command</span><span class="o">&amp;</span> <span class="n">command</span> <span class="o">=</span> <span class="k">static_cast</span><span class="o">&lt;</span><span class="n">clang</span><span class="o">::</span><span class="n">driver</span><span class="o">::</span><span class="n">Command</span><span class="o">&gt;</span><span class="p">(</span><span class="o">*</span><span class="n">jobs</span><span class="p">.</span><span class="n">begin</span><span class="p">());</span>
</span><span class='line'>  <span class="k">const</span> <span class="n">clang</span><span class="o">::</span><span class="n">driver</span><span class="o">::</span><span class="n">ArgStringList</span><span class="o">&amp;</span> <span class="n">ccargs</span> <span class="o">=</span> <span class="n">command</span><span class="p">.</span><span class="n">getArguments</span><span class="p">();</span>
</span><span class='line'>  <span class="n">std</span><span class="o">::</span><span class="n">unique_ptr</span><span class="o">&lt;</span><span class="n">clang</span><span class="o">::</span><span class="n">CompilerInvocation</span><span class="o">&gt;</span> <span class="n">cinvocation</span><span class="p">(</span><span class="k">new</span> <span class="n">clang</span><span class="o">::</span><span class="n">CompilerInvocation</span><span class="p">());</span>
</span><span class='line'>  <span class="n">clang</span><span class="o">::</span><span class="n">CompilerInvocation</span><span class="o">::</span><span class="n">CreateFromArgs</span><span class="p">(</span><span class="o">*</span><span class="n">cinvocation</span><span class="p">,</span> <span class="k">const_cast</span><span class="o">&lt;</span><span class="k">const</span> <span class="kt">char</span><span class="o">**&gt;</span><span class="p">(</span><span class="n">ccargs</span><span class="p">.</span><span class="n">data</span><span class="p">()),</span>
</span><span class='line'>      <span class="k">const_cast</span><span class="o">&lt;</span><span class="k">const</span> <span class="kt">char</span><span class="o">**&gt;</span><span class="p">(</span><span class="n">ccargs</span><span class="p">.</span><span class="n">data</span><span class="p">())</span> <span class="o">+</span> <span class="n">ccargs</span><span class="p">.</span><span class="n">size</span><span class="p">(),</span> <span class="n">dengine</span><span class="p">);</span>
</span><span class='line'>  <span class="n">clang</span><span class="o">::</span><span class="n">CompilerInstance</span> <span class="n">cinstance</span><span class="p">;</span>
</span><span class='line'>  <span class="n">cinstance</span><span class="p">.</span><span class="n">setInvocation</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">move</span><span class="p">(</span><span class="n">cinvocation</span><span class="p">));</span>
</span><span class='line'>  <span class="n">cinstance</span><span class="p">.</span><span class="n">createDiagnostics</span><span class="p">();</span>
</span><span class='line'>
</span><span class='line'>  <span class="n">llvm</span><span class="o">::</span><span class="n">LLVMContext</span> <span class="n">context</span><span class="p">;</span>
</span><span class='line'>  <span class="n">clang</span><span class="o">::</span><span class="n">EmitLLVMOnlyAction</span> <span class="n">action</span><span class="p">(</span><span class="o">&amp;</span><span class="n">context</span><span class="p">);</span>
</span><span class='line'>  <span class="n">cinstance</span><span class="p">.</span><span class="n">ExecuteAction</span><span class="p">(</span><span class="n">action</span><span class="p">);</span>
</span><span class='line'>  <span class="n">std</span><span class="o">::</span><span class="n">unique_ptr</span><span class="o">&lt;</span><span class="n">llvm</span><span class="o">::</span><span class="n">Module</span><span class="o">&gt;</span> <span class="n">module</span> <span class="o">=</span> <span class="n">action</span><span class="p">.</span><span class="n">takeModule</span><span class="p">();</span>
</span><span class='line'>
</span><span class='line'>  <span class="c1">// Use mcjit to generate the native code from IR and run it</span>
</span><span class='line'>  <span class="n">llvm</span><span class="o">::</span><span class="n">InitializeNativeTarget</span><span class="p">();</span>
</span><span class='line'>  <span class="n">llvm</span><span class="o">::</span><span class="n">InitializeNativeTargetAsmPrinter</span><span class="p">();</span>
</span><span class='line'>  <span class="n">llvm</span><span class="o">::</span><span class="n">Function</span><span class="o">*</span> <span class="n">_run</span> <span class="o">=</span> <span class="n">module</span><span class="o">-&gt;</span><span class="n">getFunction</span><span class="p">(</span><span class="s">&quot;_run&quot;</span><span class="p">);</span>
</span><span class='line'>  <span class="n">llvm</span><span class="o">::</span><span class="n">ExecutionEngine</span><span class="o">*</span> <span class="n">ee</span> <span class="o">=</span> <span class="n">llvm</span><span class="o">::</span><span class="n">EngineBuilder</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">move</span><span class="p">(</span><span class="n">module</span><span class="p">)).</span><span class="n">create</span><span class="p">();</span>
</span><span class='line'>  <span class="n">llvm</span><span class="o">::</span><span class="n">GenericValue</span> <span class="n">gv</span> <span class="o">=</span> <span class="n">ee</span><span class="o">-&gt;</span><span class="n">runFunction</span><span class="p">(</span><span class="n">_run</span><span class="p">,</span> <span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="n">llvm</span><span class="o">::</span><span class="n">GenericValue</span><span class="o">&gt;</span><span class="p">());</span>
</span><span class='line'>  <span class="n">fflush</span><span class="p">(</span><span class="n">stdout</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'>  <span class="n">remove</span><span class="p">(</span><span class="n">ccname</span><span class="p">.</span><span class="n">c_str</span><span class="p">());</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="kt">int</span> <span class="n">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span><span class="o">**</span> <span class="n">argv</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>  <span class="n">std</span><span class="o">::</span><span class="n">ifstream</span> <span class="n">ifs</span><span class="p">(</span><span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">]);</span>
</span><span class='line'>  <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">program</span><span class="p">((</span><span class="n">std</span><span class="o">::</span><span class="n">istreambuf_iterator</span><span class="o">&lt;</span><span class="kt">char</span><span class="o">&gt;</span><span class="p">(</span><span class="n">ifs</span><span class="p">)),</span> <span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">istreambuf_iterator</span><span class="o">&lt;</span><span class="kt">char</span><span class="o">&gt;</span><span class="p">()));</span>
</span><span class='line'>  <span class="n">BrainfuckLLVM</span> <span class="nf">llvm</span><span class="p">(</span><span class="n">program</span><span class="p">,</span> <span class="n">argv</span><span class="p">[</span><span class="mi">2</span><span class="p">]);</span>
</span><span class='line'>  <span class="n">llvm</span><span class="p">.</span><span class="n">run</span><span class="p">();</span>
</span><span class='line'>  <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>




<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='cpp'><span class='line'><span class="n">g</span><span class="o">++</span> <span class="o">-</span><span class="n">std</span><span class="o">=</span><span class="n">c</span><span class="o">++</span><span class="mi">11</span> <span class="err">`</span><span class="o">/</span><span class="n">path</span><span class="o">/</span><span class="n">to</span><span class="o">/</span><span class="n">llvm</span><span class="o">-</span><span class="n">config</span> <span class="o">--</span><span class="n">cxxflags</span> <span class="o">--</span><span class="n">ldflags</span><span class="err">`</span> <span class="o">-</span><span class="n">lclangASTMatchers</span> <span class="o">-</span><span class="n">lclangFrontendTool</span> <span class="o">-</span><span class="n">lclangFrontend</span> <span class="o">-</span><span class="n">lclangDriver</span> <span class="o">-</span><span class="n">lclangSerialization</span> <span class="o">-</span><span class="n">lclangCodeGen</span> <span class="o">-</span><span class="n">lclangParse</span> <span class="o">-</span><span class="n">lclangSema</span> <span class="o">-</span><span class="n">lclangToolingInclusions</span> <span class="o">-</span><span class="n">lclangToolingCore</span>  <span class="o">-</span><span class="n">lclangFormat</span> <span class="o">-</span><span class="n">lclangIndex</span> <span class="o">-</span><span class="n">lclangCrossTU</span> <span class="o">-</span><span class="n">lclangStaticAnalyzerFrontend</span> <span class="o">-</span><span class="n">lclangStaticAnalyzerCheckers</span> <span class="o">-</span><span class="n">lclangStaticAnalyzerCore</span> <span class="o">-</span><span class="n">lclangAnalysis</span> <span class="o">-</span><span class="n">lclangARCMigrate</span> <span class="o">-</span><span class="n">lclangRewriteFrontend</span> <span class="o">-</span><span class="n">lclangRewrite</span> <span class="o">-</span><span class="n">lclangEdit</span> <span class="o">-</span><span class="n">lclangAST</span> <span class="o">-</span><span class="n">lclangLex</span> <span class="o">-</span><span class="n">lclangBasic</span> <span class="err">`</span><span class="o">/</span><span class="n">path</span><span class="o">/</span><span class="n">to</span><span class="o">/</span><span class="n">llvm</span><span class="o">-</span><span class="n">config</span> <span class="o">--</span><span class="n">libs</span><span class="err">`</span> <span class="o">-</span><span class="n">o</span> <span class="n">brainfuck</span> <span class="n">brainfuck</span><span class="p">.</span><span class="n">cc</span>
</span><span class='line'>
</span><span class='line'><span class="p">.</span><span class="o">/</span><span class="n">brainfuck</span> <span class="n">program</span><span class="p">.</span><span class="n">bf</span> <span class="o">/</span><span class="n">path</span><span class="o">/</span><span class="n">to</span><span class="o">/</span><span class="n">clang</span>
</span></code></pre></td></tr></table></div></figure>


<h2><a id="dynasm"></a>DynASM</h2>

<p>Another way of generating the native code is using <a href="https://luajit.org/dynasm.html">DynASM</a> from LuaJIT and there is an <a href="https://corsix.github.io/dynasm-doc/tutorial.html">example</a> online.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Good Economics for Hard Times]]></title>
    <link href="http://blog.jjyao.me/blog/2020/12/20/good-economics-for-hard-times/"/>
    <updated>2020-12-20T14:04:45-08:00</updated>
    <id>http://blog.jjyao.me/blog/2020/12/20/good-economics-for-hard-times</id>
    <content type="html"><![CDATA[<p>2020，世界很复杂。贸易战，美国大选，全球气候变暖，贫富差距扩大化等热点问题影响着我们每一个人。如果你也对这些问题感兴趣，我推荐你阅读《Good Economics for Hard Times》。这本书可能会带给你一些不同的角度来看待这些问题，有些甚至可能完全颠覆你以往的认知。以下是我的读书笔记：</p>

<ol>
<li><a href="#immigration">移民</a></li>
<li><a href="#globalization">全球化</a></li>
<li><a href="#prejudice">偏见</a></li>
<li><a href="#growth">经济增长</a></li>
<li><a href="#climate">气候变暖</a></li>
<li><a href="#inequality">贫富差距</a></li>
</ol>


<!-- more -->


<h2><a id="immigration"></a>移民</h2>

<p>这本书分析了两类移民对当地人的影响，分别是低技能移民（low-skilled immigrants）和高技能移民（high-skilled immigrants）。</p>

<p>很多人认为低技能的移民会伤害到低技能的当地人的利益：工资会降低，工作机会会被抢走。<strong><em>然而研究表明低技能的移民并不会降低当地人的工资和就业率</em></strong>。移民增加了劳动力的供应的同时也增加了劳动力的需求 （One very big problem with the supply-demand analysis applied to immigration is that an influx of migrants increases the demand for labor at the same time it increases the supply of laborers.）。一个原因是低技能的移民会在当地生活消费，从而产生了新的需求，因而创造出更多的工作岗位。比如移民的增加，使得管理者需求增加而本地人因为语言等的优势更容易获得这些岗位。另一个原因是廉价的移民劳动力会延缓机器化自动化的发生。另外低技能移民很多做的都是当地人不想干的活，因此并没有真正从当地人手中抢走任何工作。同时作者认为当地人并不一定会在和移民的竞争中落入下风。相对于一个新来的陌生移民，当地人有着自身的优势，比如语言的优势，老板知根知底的优势。</p>

<p>对于高技能移民，作者认为对当地人的影响是两面的。好的方面是高技能移民能提供廉价的高技能服务比如看病，而这可以使当地的低收入人群受益。不好的方面是当地拥有同等技能的人会面临着更激烈的竞争。</p>

<h2><a id="globalization"></a>全球化</h2>

<p>全球化和自由贸易可以使得每个国家做自己拥有比较优势（comparative advantage）的活，以此提高生产效率（productivity）。这个世界作为一个整体因此受益，而收益的再分配可以让每个人享受到全球化的成果。而为了达到效率的最大化，资源（比如资本和劳动力）需要能够自由流通到需要它们的地方。然而本书却提出了资源往往具有粘性（resources tend to be sticky）的观点，也就是说资源往往到不了最需要它们的地方。比如出于不确定性，人们更愿意留在家乡而不是到更需要劳动力的城市和国家。</p>

<p>同时作者分析了全球化和自由贸易对于发达国家和发展中国家的影响。发达国家的优势是资本而发展中国家的优势是廉价劳动力，因此全球化会使发达国家的资本家受益而发展中国家的工人受益。另一方面，发达国家资本家受益的同时，它们的工人会在和发展中国家廉价劳动力竞争中受损（Workers were likely to suffer from trade in rich countries and benefit from it in poor countries.）。为了帮助受影响的发达国家工人，国家需要进行收入再分配和各类政策扶持。而贸易战却不是解决这个问题的方法之一，它帮助了某些人的同时也会伤害到另外一些人（While trade war may save some jobs in steal, it would likely cause significant new damage to others. The US economy will be fine. Hundreds of thousands of people will not.）。</p>

<h2><a id="prejudice"></a>偏见</h2>

<p>本书提到了现在社会充满了对立，分裂和偏见的现象（比如民主党vs共和党，白人vs黑人）。作者认为现在的社交网络非但没有缓解这些现象，反而作为一个回声室（echo chamber），恶化了它们。作者还认为人们的对立和偏见背后有着深层次的原因（比如对世界的不满，感到没有被世界尊重）。打击偏见的方法不应该是直接和他们就此争论或者表现出对他们的鄙视，这样做只会加深偏见（Preferences like prejudice are as much part of the symptoms of the malaise as its cause, perhaps more. Prejudice is often a defensive reaction to the many things we feel are going wrong in the world, our economic travails, and a sense that we are no longer respected or valued.）。为了缓解这些现象，作者认为一个有效的方式是多接触，多互相了解。而学校在这一方面扮演了非常重要的角色。不同背景的年轻人生活学习在一起，可以消除偏见达到互信（Familiarity performed its magic.）。而这也是像哈佛这样培养未来领导人的学校需要招收各个族群学生的一个原因，过多的偏向某一个族群会产生不好的影响（As a flagship producer of the next generation of leaders, Harvard clearly needs to find a place for students from all social groups, and a massive overrepresentation of any particular social group relative to its weight in the population is both perhaps undesirable in a democracy and likely to lead to political problems.）。</p>

<h2><a id="growth"></a>经济增长</h2>

<p>本书的一个重要观点是<strong><em>人们目前还不知道持久经济增长的内在机制是什么</em></strong>，包括如何恢复增长和保持增长（Despite the best efforts of generations of economists, the deep mechanisms of persistent economic growth remain elusive.）。与此相关的是给富人减税并不会促进经济的增长（Tax cuts for the wealthy do not produce economic growth.）。另一方面，尽管无法带来持续的经济增长，但提高资源利用率，减少资源的错误分配还是能让贫穷国家获得一定的增长，而这需要克服之前提到的资源粘性问题。最后虽然没人知道如何持续不断的增长经济，但所有国家都能致力于改善国民的福祉，即使它们不能被反映在GDP上（GDP values only those things priced and marketed.）。</p>

<h2><a id="climate"></a>气候变暖</h2>

<p>气候变暖是个全球性的问题，然而它却非常不公平。很大一部分的碳排放都是发达国家导致的（直接排放或者消费发展中国家生产的商品），然而全球变暖的大部分代价却是由发展中国家来承受。因此作者认为发达国家需要为气候变暖承担很大一部分责任。作者还认为人们的消费习惯是可以被改变的，可以变得更低碳更环保。通过税的引导，政府可以慢慢改变人们不环保的消费习惯。</p>

<h2><a id="inequality"></a>贫富差距</h2>

<p>日益扩大的贫富差距也是本书的一个重点讨论议题。作者认为美国这几十年的贫富差距是人为的政策导致的而不是不可控的技术革新（The last thirty years of US history should convince us that the evolution of inequality is not the by-product of technological changes we do not control: it is the result of policy decisions.）。</p>

<p>首先作者认为先富带动后富并没有真正在美国发生，相反富人的财富得到了极大的增长，而穷人的工资涨幅却没有跟上GDP的涨幅，结果就是社会的财富越来越集中到少数富人手中。其中一个重要原因是富人的低税收。低税收使得高工资对CEO们更有吸引力（因为大部分工资都会变成税后工资）而公司之间对优秀CEO的争夺也相应拉高了工资。另外现在CEO主要的收入来自股票而不是基本工资，这也就使得他们对涨工资动力不大，反而会想要降低工资来削减成本从而提升股价（Linking managerial pay to the stock market meant that manager’s pay was no longer linked to a salary scale within the enterprise. When everyone was on the same scale, CEOs had to grow salaries at the bottom to increase their own. With stock options, they had no reason to increase wages at the bottom, and in fact every reason to squeeze costs.）。作者提倡对富人收取高额的税收，并且没有证据表明这样做会降低富人的工作积极性（All in all, therefore, it seems to us that high marginal income tax rates, applied only to very high incomes, are a perfectly sensible way to limit the explosion of top income inequality. They would not be extortionary, since very few people will end up paying them; top mangers will simply not get these kinds of income anymore. And from all we see, they won’t discourage anybody to work as hard as they can.）。另外作者也意识到征收富人税会面临极大的困难。一方面富人有足够的资源对政客进行游说，另一方面富人可以将财富转移到低税收国家进行避税，而国家之间对于这些财富的竞争会使得税率变低（This gives rise to a race to the bottom on tax rates.）。归根到底征收富人税并不是一个经济问题，而是个政治问题（The difficulty of raising top tax rates is a political one.）。</p>

<p>在富人越来越富的同时，美国的穷人却遇到了收入停滞和阶级固化的问题。由此他们会产生绝望或愤怒，绝望的人把问题归咎于自身而愤怒的人把问题归咎于别人（The majority of Americans whose wages and income have stagnated, and who confront an ever-widening gap between the wealth they see around them and the financial woes they are experiencing, face a choice between blaming themselves for not benefitting from the opportunities they believe their society offers and finding someone to blame for stealing their jobs. That way lies despair and anger.）。而这两种情绪对个人和社会都没有益处，绝望的人失去了希望而愤怒的人把问题错误地归咎于移民和全球化（Behind the anti-immigrant views, are two misconceptions: an exaggeration of how many migrants are coming in, or about to come in, and a belief in the nonfact that low-skilled immigrants depress wages.）。作者认为政府需要出台政策来帮助那些受全球化和自由贸易影响的人，其中一个方法就是UBI（universal basic income）。不像别的救助项目，UBI没有任何门槛（比如没有复杂的申请和审核流程）因此可以保证最需要帮助的人能够享受到。另外没有证据显示穷人会因此降低工作积极性或者乱花钱（There is no support in the data for the view that the poor just blow the money on desires rather than needs.）。相反地，这些钱能让穷人少了后顾之忧，让他们有更多的精力放在工作之上，让他们更可能离开家乡去寻找更多的工作机会。在有着这些优势的情况下，实施UBI最大的困难就是政府没有足够的钱。</p>

<p>最后作者充满人文关怀地提到对于穷人的帮助需要照顾他们的尊严，要把他们当作人来对待。他们可能有问题，但他们不是问题本身（While they may have problems, they are not the problem. They are entitled to be seen for who they are and to not be defined by the difficulties besieging them.）。</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Software Engineering Laws]]></title>
    <link href="http://blog.jjyao.me/blog/2020/01/25/software-engineering-laws/"/>
    <updated>2020-01-25T11:23:14-08:00</updated>
    <id>http://blog.jjyao.me/blog/2020/01/25/software-engineering-laws</id>
    <content type="html"><![CDATA[<ol>
<li><a href="#murphy_law">Murphy&rsquo;s law</a></li>
<li><a href="#amdahl_law">Amdahl&rsquo;s law</a></li>
<li><a href="#brooks_law">Brooks&rsquo;s law</a></li>
<li><a href="#hofstadter_law">Hofstadter&rsquo;s law</a></li>
</ol>


<!-- more -->


<h2><a id="murphy_law"></a>Murphy&rsquo;s law</h2>

<p>Anything that can go wrong will go wrong.</p>

<h2><a id="amdahl_law"></a>Amdahl&rsquo;s law</h2>

<p>The performance improvement to be gained by making some part of the execution faster is limited by the fraction of the time that part uses.</p>

<h2><a id="brooks_law"></a>Brooks&rsquo;s law</h2>

<p>Adding manpower to a late software project makes it later.</p>

<h2><a id="hofstadter_law"></a>Hofstadter&rsquo;s law</h2>

<p>It always takes longer than you expect, even when you take into account Hofstadter&rsquo;s Law.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Floating-Point Surprises]]></title>
    <link href="http://blog.jjyao.me/blog/2019/07/03/floating-point-surprises/"/>
    <updated>2019-07-03T15:57:02-07:00</updated>
    <id>http://blog.jjyao.me/blog/2019/07/03/floating-point-surprises</id>
    <content type="html"><![CDATA[<p>The single-precision floating-point or double-precision floating-point has finite precision so <a href="https://en.wikipedia.org/wiki/Loss_of_significance">loss of significance</a> can happen and cause surprises.</p>

<!-- more -->


<p>Let&rsquo;s take float, which has 23 bits mantissa, as an example. <code>198705381</code> as an integer has the binary representation <code>00001011 11011000 00000000 11100101</code>. <code>198705381.0f</code> as a float has the binary representation <code>0 10011010 01111011000000000001110</code>. Here a round-down happens due to the default IEEE 754 rounding mode <code>round to the nearest, ties to even</code> and <code>198705381.0f</code> is rounded down to <code>198705376.0f</code>.</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='cpp'><span class='line'><span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="n">std</span><span class="o">::</span><span class="n">setprecision</span><span class="p">(</span><span class="mi">16</span><span class="p">)</span> <span class="o">&lt;&lt;</span> <span class="mf">198705381.0f</span> <span class="o">&lt;&lt;</span> <span class="s">&quot;</span><span class="se">\n</span><span class="s">&quot;</span><span class="p">;</span> <span class="c1">// output is 198705376</span>
</span></code></pre></td></tr></table></div></figure>


<p><code>199698905</code> as an integer has the binary representation <code>00001011 11100111 00101001 11011001</code>. <code>199698905.0f</code> as a float has the binary representation <code>0 10011010 01111100111001010011110</code>. Here a round-up happens and <code>199698905.0f</code> is rounded up to <code>199698912.0f</code>.</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='cpp'><span class='line'><span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="n">std</span><span class="o">::</span><span class="n">setprecision</span><span class="p">(</span><span class="mi">16</span><span class="p">)</span> <span class="o">&lt;&lt;</span> <span class="mf">199698905.0f</span> <span class="o">&lt;&lt;</span> <span class="s">&quot;</span><span class="se">\n</span><span class="s">&quot;</span><span class="p">;</span> <span class="c1">// output is 199698912</span>
</span></code></pre></td></tr></table></div></figure>


<p>Due to the loss of significance, many surprises can happen:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='cpp'><span class='line'><span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="mf">198705381.0f</span> <span class="o">-</span> <span class="mf">198705380.0f</span> <span class="o">&lt;&lt;</span> <span class="s">&quot;</span><span class="se">\n</span><span class="s">&quot;</span><span class="p">;</span>  <span class="c1">// output is 0 since they are both rounded down to the same value</span>
</span><span class='line'>
</span><span class='line'><span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="mf">198705381.0f</span> <span class="o">*</span> <span class="mf">1.005f</span> <span class="o">-</span> <span class="mf">199698905.0f</span> <span class="o">&lt;&lt;</span> <span class="s">&quot;</span><span class="se">\n</span><span class="s">&quot;</span><span class="p">;</span> <span class="c1">// output is negative (should be positive if we use double instead of float) since one is rounded down and the other is rounded up</span>
</span></code></pre></td></tr></table></div></figure>


<h3>References</h3>

<p>[1] <a href="https://benjaminjurke.com/content/articles/2015/loss-of-significance-in-floating-point-computations">https://benjaminjurke.com/content/articles/2015/loss-of-significance-in-floating-point-computations</a> <br/>
[2] <a href="https://www.h-schmidt.net/FloatConverter/IEEE754.html">https://www.h-schmidt.net/FloatConverter/IEEE754.html</a></p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Interaction Between HugeTLBFS and Hugepages]]></title>
    <link href="http://blog.jjyao.me/blog/2019/04/01/interaction-between-hugetlbfs-and-hugepages/"/>
    <updated>2019-04-01T19:57:31-07:00</updated>
    <id>http://blog.jjyao.me/blog/2019/04/01/interaction-between-hugetlbfs-and-hugepages</id>
    <content type="html"><![CDATA[<p>This post shows the interaction between hugetlbfs and huge pages by an example program. All the results are based on linux 3.10.0-514.55.4.el7.x86_64.</p>

<!-- more -->


<h2>Setup</h2>

<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>sudo mount -t hugetlbfs -o mode=0777,pagesize=2M nodev /mnt/huge
</span><span class='line'>echo '10' | sudo tee /proc/sys/vm/nr_hugepages</span></code></pre></td></tr></table></div></figure>


<p>This creates a hugetlbfs with maximum of 10 huge pages.</p>

<h2>Example Program</h2>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
<span class='line-number'>32</span>
<span class='line-number'>33</span>
<span class='line-number'>34</span>
<span class='line-number'>35</span>
<span class='line-number'>36</span>
<span class='line-number'>37</span>
<span class='line-number'>38</span>
<span class='line-number'>39</span>
<span class='line-number'>40</span>
<span class='line-number'>41</span>
<span class='line-number'>42</span>
<span class='line-number'>43</span>
<span class='line-number'>44</span>
<span class='line-number'>45</span>
<span class='line-number'>46</span>
<span class='line-number'>47</span>
<span class='line-number'>48</span>
</pre></td><td class='code'><pre><code class='c'><span class='line'><span class="cp">#include &lt;stdio.h&gt;</span>
</span><span class='line'><span class="cp">#include &lt;stdlib.h&gt;</span>
</span><span class='line'><span class="cp">#include &lt;sys/types.h&gt;</span>
</span><span class='line'><span class="cp">#include &lt;fcntl.h&gt;</span>
</span><span class='line'><span class="cp">#include &lt;unistd.h&gt;</span>
</span><span class='line'><span class="cp">#include &lt;sys/mman.h&gt;</span>
</span><span class='line'>
</span><span class='line'><span class="cp">#define MB (1024*1024)</span>
</span><span class='line'>
</span><span class='line'><span class="kt">void</span> <span class="nf">meminfo</span><span class="p">(</span><span class="kt">char</span><span class="o">*</span> <span class="n">msg</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>  <span class="n">printf</span><span class="p">(</span><span class="n">msg</span><span class="p">);</span>
</span><span class='line'>  <span class="n">system</span><span class="p">(</span><span class="s">&quot;cat /proc/meminfo | grep HugePages_&quot;</span><span class="p">);</span>
</span><span class='line'>  <span class="n">printf</span><span class="p">(</span><span class="s">&quot;</span><span class="se">\n</span><span class="s">&quot;</span><span class="p">);</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span><span class="o">*</span> <span class="n">argv</span><span class="p">[])</span> <span class="p">{</span>
</span><span class='line'>  <span class="n">meminfo</span><span class="p">(</span><span class="s">&quot;Initial meminfo: </span><span class="se">\n</span><span class="s">&quot;</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'>  <span class="kt">int</span> <span class="n">fd</span> <span class="o">=</span> <span class="n">open</span><span class="p">(</span><span class="s">&quot;/mnt/huge/foo.txt&quot;</span><span class="p">,</span> <span class="n">O_RDWR</span> <span class="o">|</span> <span class="n">O_CREAT</span> <span class="o">|</span> <span class="n">O_TRUNC</span><span class="p">,</span> <span class="n">S_IRUSR</span> <span class="o">|</span> <span class="n">S_IWUSR</span> <span class="o">|</span> <span class="n">S_IRGRP</span> <span class="o">|</span> <span class="n">S_IROTH</span><span class="p">);</span>
</span><span class='line'>  <span class="n">meminfo</span><span class="p">(</span><span class="s">&quot;After create and open the file: </span><span class="se">\n</span><span class="s">&quot;</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'>  <span class="n">ftruncate</span><span class="p">(</span><span class="n">fd</span><span class="p">,</span> <span class="mi">4</span> <span class="o">*</span> <span class="n">MB</span><span class="p">);</span>
</span><span class='line'>  <span class="n">meminfo</span><span class="p">(</span><span class="s">&quot;After set file size to 4MB: </span><span class="se">\n</span><span class="s">&quot;</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'>  <span class="kt">void</span><span class="o">*</span> <span class="n">base</span> <span class="o">=</span> <span class="n">mmap</span><span class="p">(</span><span class="nb">NULL</span><span class="p">,</span> <span class="mi">4</span> <span class="o">*</span> <span class="n">MB</span><span class="p">,</span> <span class="n">PROT_WRITE</span> <span class="o">|</span> <span class="n">PROT_READ</span><span class="p">,</span> <span class="n">MAP_SHARED</span><span class="p">,</span> <span class="n">fd</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>
</span><span class='line'>  <span class="n">meminfo</span><span class="p">(</span><span class="s">&quot;After mmap 4MB without MAP_POPULATE: </span><span class="se">\n</span><span class="s">&quot;</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'>  <span class="n">munmap</span><span class="p">(</span><span class="n">base</span><span class="p">,</span> <span class="mi">4</span> <span class="o">*</span> <span class="n">MB</span><span class="p">);</span>
</span><span class='line'>  <span class="n">meminfo</span><span class="p">(</span><span class="s">&quot;After munmap: </span><span class="se">\n</span><span class="s">&quot;</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'>  <span class="n">base</span> <span class="o">=</span> <span class="n">mmap</span><span class="p">(</span><span class="nb">NULL</span><span class="p">,</span> <span class="mi">4</span> <span class="o">*</span> <span class="n">MB</span><span class="p">,</span> <span class="n">PROT_WRITE</span> <span class="o">|</span> <span class="n">PROT_READ</span><span class="p">,</span> <span class="n">MAP_SHARED</span> <span class="o">|</span> <span class="n">MAP_POPULATE</span><span class="p">,</span> <span class="n">fd</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>
</span><span class='line'>  <span class="n">meminfo</span><span class="p">(</span><span class="s">&quot;After mmap 4MB with MAP_POPULATE: </span><span class="se">\n</span><span class="s">&quot;</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'>  <span class="n">munmap</span><span class="p">(</span><span class="n">base</span><span class="p">,</span> <span class="mi">4</span> <span class="o">*</span> <span class="n">MB</span><span class="p">);</span>
</span><span class='line'>  <span class="n">meminfo</span><span class="p">(</span><span class="s">&quot;After munmap: </span><span class="se">\n</span><span class="s">&quot;</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'>  <span class="n">ftruncate</span><span class="p">(</span><span class="n">fd</span><span class="p">,</span> <span class="mi">8</span> <span class="o">*</span> <span class="n">MB</span><span class="p">);</span>
</span><span class='line'>  <span class="n">meminfo</span><span class="p">(</span><span class="s">&quot;After set file size to 8MB: </span><span class="se">\n</span><span class="s">&quot;</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'>  <span class="n">base</span> <span class="o">=</span> <span class="n">mmap</span><span class="p">(</span><span class="nb">NULL</span><span class="p">,</span> <span class="mi">8</span> <span class="o">*</span> <span class="n">MB</span><span class="p">,</span> <span class="n">PROT_WRITE</span> <span class="o">|</span> <span class="n">PROT_READ</span><span class="p">,</span> <span class="n">MAP_SHARED</span> <span class="o">|</span> <span class="n">MAP_POPULATE</span><span class="p">,</span> <span class="n">fd</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>
</span><span class='line'>  <span class="n">meminfo</span><span class="p">(</span><span class="s">&quot;After mmap 8MB with MAP_POPULATE: </span><span class="se">\n</span><span class="s">&quot;</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'>  <span class="n">munmap</span><span class="p">(</span><span class="n">base</span><span class="p">,</span> <span class="mi">8</span> <span class="o">*</span> <span class="n">MB</span><span class="p">);</span>
</span><span class='line'>  <span class="n">meminfo</span><span class="p">(</span><span class="s">&quot;After munmap: </span><span class="se">\n</span><span class="s">&quot;</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'>  <span class="n">close</span><span class="p">(</span><span class="n">fd</span><span class="p">);</span>
</span><span class='line'>  <span class="n">meminfo</span><span class="p">(</span><span class="s">&quot;After close: </span><span class="se">\n</span><span class="s">&quot;</span><span class="p">);</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>The output of running this program is:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
<span class='line-number'>32</span>
<span class='line-number'>33</span>
<span class='line-number'>34</span>
<span class='line-number'>35</span>
<span class='line-number'>36</span>
<span class='line-number'>37</span>
<span class='line-number'>38</span>
<span class='line-number'>39</span>
<span class='line-number'>40</span>
<span class='line-number'>41</span>
<span class='line-number'>42</span>
<span class='line-number'>43</span>
<span class='line-number'>44</span>
<span class='line-number'>45</span>
<span class='line-number'>46</span>
<span class='line-number'>47</span>
<span class='line-number'>48</span>
<span class='line-number'>49</span>
<span class='line-number'>50</span>
<span class='line-number'>51</span>
<span class='line-number'>52</span>
<span class='line-number'>53</span>
<span class='line-number'>54</span>
<span class='line-number'>55</span>
<span class='line-number'>56</span>
<span class='line-number'>57</span>
<span class='line-number'>58</span>
<span class='line-number'>59</span>
<span class='line-number'>60</span>
<span class='line-number'>61</span>
<span class='line-number'>62</span>
<span class='line-number'>63</span>
<span class='line-number'>64</span>
<span class='line-number'>65</span>
</pre></td><td class='code'><pre><code class='c'><span class='line'><span class="n">Initial</span> <span class="nl">meminfo</span><span class="p">:</span>
</span><span class='line'><span class="nl">HugePages_Total</span><span class="p">:</span>      <span class="mi">10</span>
</span><span class='line'><span class="nl">HugePages_Free</span><span class="p">:</span>       <span class="mi">10</span>
</span><span class='line'><span class="nl">HugePages_Rsvd</span><span class="p">:</span>        <span class="mi">0</span>
</span><span class='line'><span class="nl">HugePages_Surp</span><span class="p">:</span>        <span class="mi">0</span>
</span><span class='line'>
</span><span class='line'><span class="n">After</span> <span class="n">creat</span> <span class="n">and</span> <span class="n">open</span> <span class="n">the</span> <span class="nl">file</span><span class="p">:</span>
</span><span class='line'><span class="nl">HugePages_Total</span><span class="p">:</span>      <span class="mi">10</span>
</span><span class='line'><span class="nl">HugePages_Free</span><span class="p">:</span>       <span class="mi">10</span>
</span><span class='line'><span class="nl">HugePages_Rsvd</span><span class="p">:</span>        <span class="mi">0</span>
</span><span class='line'><span class="nl">HugePages_Surp</span><span class="p">:</span>        <span class="mi">0</span>
</span><span class='line'>
</span><span class='line'><span class="n">After</span> <span class="n">set</span> <span class="n">file</span> <span class="n">size</span> <span class="n">to</span> <span class="mi">4</span><span class="nl">MB</span><span class="p">:</span>
</span><span class='line'><span class="nl">HugePages_Total</span><span class="p">:</span>      <span class="mi">10</span>
</span><span class='line'><span class="nl">HugePages_Free</span><span class="p">:</span>       <span class="mi">10</span>
</span><span class='line'><span class="nl">HugePages_Rsvd</span><span class="p">:</span>        <span class="mi">0</span>
</span><span class='line'><span class="nl">HugePages_Surp</span><span class="p">:</span>        <span class="mi">0</span>
</span><span class='line'>
</span><span class='line'><span class="n">After</span> <span class="n">mmap</span> <span class="mi">4</span><span class="n">MB</span> <span class="n">without</span> <span class="nl">MAP_POPULATE</span><span class="p">:</span>
</span><span class='line'><span class="nl">HugePages_Total</span><span class="p">:</span>      <span class="mi">10</span>
</span><span class='line'><span class="nl">HugePages_Free</span><span class="p">:</span>       <span class="mi">10</span>
</span><span class='line'><span class="nl">HugePages_Rsvd</span><span class="p">:</span>        <span class="mi">2</span>
</span><span class='line'><span class="nl">HugePages_Surp</span><span class="p">:</span>        <span class="mi">0</span>
</span><span class='line'>
</span><span class='line'><span class="n">After</span> <span class="nl">munmap</span><span class="p">:</span>
</span><span class='line'><span class="nl">HugePages_Total</span><span class="p">:</span>      <span class="mi">10</span>
</span><span class='line'><span class="nl">HugePages_Free</span><span class="p">:</span>       <span class="mi">10</span>
</span><span class='line'><span class="nl">HugePages_Rsvd</span><span class="p">:</span>        <span class="mi">2</span>
</span><span class='line'><span class="nl">HugePages_Surp</span><span class="p">:</span>        <span class="mi">0</span>
</span><span class='line'>
</span><span class='line'><span class="n">After</span> <span class="n">mmap</span> <span class="mi">4</span><span class="n">MB</span> <span class="n">with</span> <span class="nl">MAP_POPULATE</span><span class="p">:</span>
</span><span class='line'><span class="nl">HugePages_Total</span><span class="p">:</span>      <span class="mi">10</span>
</span><span class='line'><span class="nl">HugePages_Free</span><span class="p">:</span>        <span class="mi">8</span>
</span><span class='line'><span class="nl">HugePages_Rsvd</span><span class="p">:</span>        <span class="mi">0</span>
</span><span class='line'><span class="nl">HugePages_Surp</span><span class="p">:</span>        <span class="mi">0</span>
</span><span class='line'>
</span><span class='line'><span class="n">After</span> <span class="nl">munmap</span><span class="p">:</span>
</span><span class='line'><span class="nl">HugePages_Total</span><span class="p">:</span>      <span class="mi">10</span>
</span><span class='line'><span class="nl">HugePages_Free</span><span class="p">:</span>        <span class="mi">8</span>
</span><span class='line'><span class="nl">HugePages_Rsvd</span><span class="p">:</span>        <span class="mi">0</span>
</span><span class='line'><span class="nl">HugePages_Surp</span><span class="p">:</span>        <span class="mi">0</span>
</span><span class='line'>
</span><span class='line'><span class="n">After</span> <span class="n">set</span> <span class="n">file</span> <span class="n">size</span> <span class="n">to</span> <span class="mi">8</span><span class="nl">MB</span><span class="p">:</span>
</span><span class='line'><span class="nl">HugePages_Total</span><span class="p">:</span>      <span class="mi">10</span>
</span><span class='line'><span class="nl">HugePages_Free</span><span class="p">:</span>        <span class="mi">8</span>
</span><span class='line'><span class="nl">HugePages_Rsvd</span><span class="p">:</span>        <span class="mi">0</span>
</span><span class='line'><span class="nl">HugePages_Surp</span><span class="p">:</span>        <span class="mi">0</span>
</span><span class='line'>
</span><span class='line'><span class="n">After</span> <span class="n">mmap</span> <span class="mi">8</span><span class="n">MB</span> <span class="n">with</span> <span class="nl">MAP_POPULATE</span><span class="p">:</span>
</span><span class='line'><span class="nl">HugePages_Total</span><span class="p">:</span>      <span class="mi">10</span>
</span><span class='line'><span class="nl">HugePages_Free</span><span class="p">:</span>        <span class="mi">6</span>
</span><span class='line'><span class="nl">HugePages_Rsvd</span><span class="p">:</span>        <span class="mi">0</span>
</span><span class='line'><span class="nl">HugePages_Surp</span><span class="p">:</span>        <span class="mi">0</span>
</span><span class='line'>
</span><span class='line'><span class="n">After</span> <span class="nl">munmap</span><span class="p">:</span>
</span><span class='line'><span class="nl">HugePages_Total</span><span class="p">:</span>      <span class="mi">10</span>
</span><span class='line'><span class="nl">HugePages_Free</span><span class="p">:</span>        <span class="mi">6</span>
</span><span class='line'><span class="nl">HugePages_Rsvd</span><span class="p">:</span>        <span class="mi">0</span>
</span><span class='line'><span class="nl">HugePages_Surp</span><span class="p">:</span>        <span class="mi">0</span>
</span><span class='line'>
</span><span class='line'><span class="n">After</span> <span class="nl">close</span><span class="p">:</span>
</span><span class='line'><span class="nl">HugePages_Total</span><span class="p">:</span>      <span class="mi">10</span>
</span><span class='line'><span class="nl">HugePages_Free</span><span class="p">:</span>        <span class="mi">6</span>
</span><span class='line'><span class="nl">HugePages_Rsvd</span><span class="p">:</span>        <span class="mi">0</span>
</span><span class='line'><span class="nl">HugePages_Surp</span><span class="p">:</span>        <span class="mi">0</span>
</span></code></pre></td></tr></table></div></figure>


<h2>Observations</h2>

<ol>
<li>Just setting the file size won&rsquo;t allocate/reserve any huge pages. It only affects the logical file size not the physical one.</li>
<li><code>mmap</code> only reserves the huge pages.</li>
<li>Populating the page table or accessing a page actually allocates the huge pages.</li>
<li><code>HugePages_Free</code> includes <code>HugePages_Rsvd</code> so the number of free-to-use huge pages is actually <code>HugePages_Free</code> minus <code>HugePages_Rsvd</code>.</li>
</ol>


<h2>Reference</h2>

<ol>
<li><a href="http://www.lenky.info/archives/2012/03/1219">Linux下hugetlbpage使用详解</a></li>
</ol>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Linux PID]]></title>
    <link href="http://blog.jjyao.me/blog/2018/12/16/linux-pid/"/>
    <updated>2018-12-16T08:15:30-08:00</updated>
    <id>http://blog.jjyao.me/blog/2018/12/16/linux-pid</id>
    <content type="html"><![CDATA[<p>In the Linux world, pid means two things. It&rsquo;s the id of a process from POSIX&rsquo;s point of view and the id of a task from kernel&rsquo;s point of view.</p>

<!-- more -->


<h2>PID</h2>

<p>In POSIX, process is an instance of a running program and it contains one or more threads. The id of a process is called pid.</p>

<p>In the Linux kernel, task is the basic execution unit and is thread in the POSIX definition. Task is represented by <code>struct task_struct</code> in the code:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
</pre></td><td class='code'><pre><code class='c'><span class='line'><span class="k">struct</span> <span class="n">task_struct</span> <span class="p">{</span>
</span><span class='line'>  <span class="p">...</span>
</span><span class='line'>  <span class="kt">pid_t</span>   <span class="n">pid</span><span class="p">;</span>
</span><span class='line'>  <span class="kt">pid_t</span>   <span class="n">tgid</span><span class="p">;</span>
</span><span class='line'>  <span class="p">...</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>Here, pid is the id of a task and tgid is the id of the thread group that contains the task. As we can see, <code>task_struct.pid</code> basically is POSIX thread id and <code>task_struct.tgid</code> is POSIX process id.</p>

<h2>EXAMPLES</h2>

<p>Two different meanings of pid can cause lots of confusions and it&rsquo;s important to know whether we are talking about pid in the POSIX context or in the Linux kernel context.</p>

<h3>getpid</h3>

<p><code>getpid()</code> is a function defined by the POSIX standard and pid means the id of a process in this context. Linux implements it by returning <code>task_struct.tgid</code>:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='c'><span class='line'><span class="n">SYSCALL_DEFINE0</span><span class="p">(</span><span class="n">getpid</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>  <span class="k">return</span> <span class="n">task_tgid_vnr</span><span class="p">(</span><span class="n">current</span><span class="p">);</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<h3>/proc/[pid]</h3>

<p>The proc file system is an interface to kernel data structures and pid means the id of a task/thread in this context. For example, <code>/proc/[pid]/status</code> shows status information about the task/thread and the implementation is in <code>fs/proc/array.c</code>.</p>

<h2>References</h2>

<p>[1] <a href="https://www.kernel.org/doc/ols/2002/ols2002-pages-330-337.pdf">https://www.kernel.org/doc/ols/2002/ols2002-pages-330-337.pdf</a> <br/>
[2] <a href="https://stackoverflow.com/questions/9305992/if-threads-share-the-same-pid-how-can-they-be-identified">https://stackoverflow.com/questions/9305992/if-threads-share-the-same-pid-how-can-they-be-identified</a></p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Microbenchmark]]></title>
    <link href="http://blog.jjyao.me/blog/2018/11/11/microbenchmark/"/>
    <updated>2018-11-11T13:58:58-08:00</updated>
    <id>http://blog.jjyao.me/blog/2018/11/11/microbenchmark</id>
    <content type="html"><![CDATA[<p>Microbenchmark is used to measure the performance of a small piece of code for the purpose of performance optimization. Writing a good microbenchmark is <a href="https://www.ibm.com/developerworks/library/j-benchmark1/index.html">hard</a> and that&rsquo;s why we should use microbenchmark frameworks (e.g. <a href="http://openjdk.java.net/projects/code-tools/jmh/">JMH</a> for Java and <a href="https://github.com/google/benchmark">Google Benchmark</a> for C++) to help us. This post contains microbenchmarks that I think are interesting.</p>

<!-- more -->


<p><strong>Don&rsquo;t directly use the performance numbers in this post, do your own measurement!</strong> Those numbers are highly dependent on the environment where those benchmarks are running.</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
</pre></td><td class='code'><pre><code class='c'><span class='line'><span class="n">BENCHMARK_DEFINE_F</span><span class="p">(</span><span class="n">BenchmarkFixture</span><span class="p">,</span> <span class="n">ForLoopAssignmentBenchmark</span><span class="p">)(</span><span class="n">benchmark</span><span class="o">::</span><span class="n">State</span><span class="o">&amp;</span> <span class="n">state</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>  <span class="k">for</span> <span class="p">(</span><span class="k">auto</span> <span class="nl">_</span> <span class="p">:</span> <span class="n">state</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>    <span class="kt">char</span> <span class="n">c</span><span class="p">[</span><span class="mi">2048</span><span class="p">];</span>
</span><span class='line'>    <span class="k">for</span> <span class="p">(</span><span class="kt">size_t</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="mi">2048</span><span class="p">;</span> <span class="o">++</span><span class="n">i</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>      <span class="n">c</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="sc">&#39;a&#39;</span><span class="p">;</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>    <span class="n">benchmark</span><span class="o">::</span><span class="n">DoNotOptimize</span><span class="p">(</span><span class="n">c</span><span class="p">);</span>
</span><span class='line'>  <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'><span class="n">BENCHMARK_REGISTER_F</span><span class="p">(</span><span class="n">BenchmarkFixture</span><span class="p">,</span> <span class="n">ForLoopAssignmentBenchmark</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'><span class="n">BENCHMARK_DEFINE_F</span><span class="p">(</span><span class="n">BenchmarkFixture</span><span class="p">,</span> <span class="n">MemsetBenchmark</span><span class="p">)(</span><span class="n">benchmark</span><span class="o">::</span><span class="n">State</span><span class="o">&amp;</span> <span class="n">state</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>  <span class="k">for</span> <span class="p">(</span><span class="k">auto</span> <span class="nl">_</span> <span class="p">:</span> <span class="n">state</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>    <span class="kt">char</span> <span class="n">c</span><span class="p">[</span><span class="mi">2048</span><span class="p">];</span>
</span><span class='line'>    <span class="n">memset</span><span class="p">(</span><span class="n">c</span><span class="p">,</span> <span class="sc">&#39;a&#39;</span><span class="p">,</span> <span class="mi">2048</span><span class="p">);</span>
</span><span class='line'>    <span class="n">benchmark</span><span class="o">::</span><span class="n">DoNotOptimize</span><span class="p">(</span><span class="n">c</span><span class="p">);</span>
</span><span class='line'>  <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'><span class="n">BENCHMARK_REGISTER_F</span><span class="p">(</span><span class="n">BenchmarkFixture</span><span class="p">,</span> <span class="n">MemsetBenchmark</span><span class="p">);</span>
</span></code></pre></td></tr></table></div></figure>


<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
</pre></td><td class='code'><pre><code class='c'><span class='line'><span class="n">Run</span> <span class="n">on</span> <span class="p">(</span><span class="mi">12</span> <span class="n">X</span> <span class="mi">2500</span> <span class="n">MHz</span> <span class="n">CPU</span> <span class="n">s</span><span class="p">)</span>
</span><span class='line'><span class="o">------------------------------------------------------------------------------------</span>
</span><span class='line'><span class="n">Benchmark</span>                                              <span class="n">Time</span>           <span class="n">CPU</span> <span class="n">Iterations</span>
</span><span class='line'><span class="o">------------------------------------------------------------------------------------</span>
</span><span class='line'><span class="n">BenchmarkFixture</span><span class="o">/</span><span class="n">ForLoopAssignmentBenchmark</span>         <span class="mi">1013</span> <span class="n">ns</span>       <span class="mi">1013</span> <span class="n">ns</span>     <span class="mi">750073</span>
</span><span class='line'><span class="n">BenchmarkFixture</span><span class="o">/</span><span class="n">MemsetBenchmark</span>                      <span class="mi">84</span> <span class="n">ns</span>         <span class="mi">84</span> <span class="n">ns</span>    <span class="mi">6209926</span>
</span></code></pre></td></tr></table></div></figure>


<p>As we can see, memset is much faster than the for loop assignment in this case. Looking at the generated assembly code, memset uses <code>rep stos</code> instruction which can be the <a href="https://stackoverflow.com/questions/33480999/how-can-the-rep-stosb-instruction-execute-faster-than-the-equivalent-loop">reason</a> why it&rsquo;s faster.</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
</pre></td><td class='code'><pre><code class='c'><span class='line'><span class="c1">// https://shipilev.net/blog/2014/nanotrusting-nanotime/</span>
</span><span class='line'><span class="kr">inline</span> <span class="kt">uint64_t</span> <span class="nf">NanosecondsSinceEpoch</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'>  <span class="n">timespec</span> <span class="n">tp</span><span class="p">;</span>
</span><span class='line'>  <span class="n">clock_gettime</span><span class="p">(</span><span class="n">CLOCK_REALTIME</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">tp</span><span class="p">);</span>
</span><span class='line'>  <span class="k">return</span> <span class="n">tp</span><span class="p">.</span><span class="n">tv_sec</span> <span class="o">*</span> <span class="n">NS_PER_SEC</span> <span class="o">+</span> <span class="n">tp</span><span class="p">.</span><span class="n">tv_nsec</span><span class="p">;</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="n">BENCHMARK_DEFINE_F</span><span class="p">(</span><span class="n">BenchmarkFixture</span><span class="p">,</span> <span class="n">NanoTimeLatencyBenchmark</span><span class="p">)(</span><span class="n">benchmark</span><span class="o">::</span><span class="n">State</span><span class="o">&amp;</span> <span class="n">state</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>  <span class="k">for</span> <span class="p">(</span><span class="k">auto</span> <span class="nl">_</span> <span class="p">:</span> <span class="n">state</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>    <span class="n">benchmark</span><span class="o">::</span><span class="n">DoNotOptimize</span><span class="p">(</span><span class="n">NanosecondsSinceEpoch</span><span class="p">());</span>
</span><span class='line'>  <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'><span class="n">BENCHMARK_REGISTER_F</span><span class="p">(</span><span class="n">BenchmarkFixture</span><span class="p">,</span> <span class="n">NanoTimeLatencyBenchmark</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'><span class="n">BENCHMARK_DEFINE_F</span><span class="p">(</span><span class="n">BenchmarkFixture</span><span class="p">,</span> <span class="n">NanoTimeGranularityBenchmark</span><span class="p">)(</span><span class="n">benchmark</span><span class="o">::</span><span class="n">State</span><span class="o">&amp;</span> <span class="n">state</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>  <span class="kt">uint64_t</span> <span class="n">cur_nano</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
</span><span class='line'>  <span class="kt">uint64_t</span> <span class="n">last_nano</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
</span><span class='line'>  <span class="k">for</span> <span class="p">(</span><span class="k">auto</span> <span class="nl">_</span> <span class="p">:</span> <span class="n">state</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>    <span class="k">do</span> <span class="p">{</span>
</span><span class='line'>      <span class="n">cur_nano</span> <span class="o">=</span> <span class="n">NanosecondsSinceEpoch</span><span class="p">();</span>
</span><span class='line'>    <span class="p">}</span> <span class="k">while</span> <span class="p">(</span><span class="n">cur_nano</span> <span class="o">==</span> <span class="n">last_nano</span><span class="p">);</span>
</span><span class='line'>    <span class="n">last_nano</span> <span class="o">=</span> <span class="n">cur_nano</span><span class="p">;</span>
</span><span class='line'>  <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'><span class="n">BENCHMARK_REGISTER_F</span><span class="p">(</span><span class="n">BenchmarkFixture</span><span class="p">,</span> <span class="n">NanoTimeGranularityBenchmark</span><span class="p">);</span>
</span></code></pre></td></tr></table></div></figure>


<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
</pre></td><td class='code'><pre><code class='c'><span class='line'><span class="n">Run</span> <span class="n">on</span> <span class="p">(</span><span class="mi">12</span> <span class="n">X</span> <span class="mi">2500</span> <span class="n">MHz</span> <span class="n">CPU</span> <span class="n">s</span><span class="p">)</span>
</span><span class='line'><span class="o">------------------------------------------------------------------------------------</span>
</span><span class='line'><span class="n">Benchmark</span>                                              <span class="n">Time</span>           <span class="n">CPU</span> <span class="n">Iterations</span>
</span><span class='line'><span class="o">------------------------------------------------------------------------------------</span>
</span><span class='line'><span class="n">BenchmarkFixture</span><span class="o">/</span><span class="n">NanoTimeLatencyBenchmark</span>             <span class="mi">39</span> <span class="n">ns</span>         <span class="mi">39</span> <span class="n">ns</span>   <span class="mi">18361529</span>
</span><span class='line'><span class="n">BenchmarkFixture</span><span class="o">/</span><span class="n">NanoTimeGranularityBenchmark</span>         <span class="mi">39</span> <span class="n">ns</span>         <span class="mi">39</span> <span class="n">ns</span>   <span class="mi">18073581</span>
</span></code></pre></td></tr></table></div></figure>


<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
<span class='line-number'>32</span>
<span class='line-number'>33</span>
<span class='line-number'>34</span>
<span class='line-number'>35</span>
<span class='line-number'>36</span>
<span class='line-number'>37</span>
</pre></td><td class='code'><pre><code class='java'><span class='line'><span class="kd">public</span> <span class="kd">class</span> <span class="nc">NanoTimeBenchmark</span> <span class="o">{</span>
</span><span class='line'>  <span class="nd">@State</span><span class="o">(</span><span class="n">Scope</span><span class="o">.</span><span class="na">Benchmark</span><span class="o">)</span>
</span><span class='line'>  <span class="kd">public</span> <span class="kd">static</span> <span class="kd">class</span> <span class="nc">BenchmarkState</span> <span class="o">{</span>
</span><span class='line'>    <span class="kd">public</span> <span class="kt">long</span> <span class="n">_lastNano</span><span class="o">;</span>
</span><span class='line'>    <span class="nd">@Setup</span><span class="o">(</span><span class="n">Level</span><span class="o">.</span><span class="na">Iteration</span><span class="o">)</span>
</span><span class='line'>    <span class="kd">public</span> <span class="kt">void</span> <span class="nf">setup</span><span class="o">()</span> <span class="o">{</span>
</span><span class='line'>      <span class="n">_lastNano</span> <span class="o">=</span> <span class="mi">0</span><span class="o">;</span>
</span><span class='line'>    <span class="o">}</span>
</span><span class='line'>  <span class="o">}</span>
</span><span class='line'>
</span><span class='line'>  <span class="nd">@Benchmark</span>
</span><span class='line'>  <span class="nd">@Fork</span><span class="o">(</span><span class="mi">1</span><span class="o">)</span>
</span><span class='line'>  <span class="nd">@Threads</span><span class="o">(</span><span class="mi">1</span><span class="o">)</span>
</span><span class='line'>  <span class="nd">@Warmup</span><span class="o">(</span><span class="n">iterations</span> <span class="o">=</span> <span class="mi">10</span><span class="o">,</span> <span class="n">time</span> <span class="o">=</span> <span class="mi">5</span><span class="o">,</span> <span class="n">timeUnit</span> <span class="o">=</span> <span class="n">TimeUnit</span><span class="o">.</span><span class="na">SECONDS</span><span class="o">)</span>
</span><span class='line'>  <span class="nd">@Measurement</span><span class="o">(</span><span class="n">iterations</span> <span class="o">=</span> <span class="mi">10</span><span class="o">,</span> <span class="n">time</span> <span class="o">=</span> <span class="mi">5</span><span class="o">,</span> <span class="n">timeUnit</span> <span class="o">=</span> <span class="n">TimeUnit</span><span class="o">.</span><span class="na">SECONDS</span><span class="o">)</span>
</span><span class='line'>  <span class="nd">@BenchmarkMode</span><span class="o">(</span><span class="n">Mode</span><span class="o">.</span><span class="na">AverageTime</span><span class="o">)</span>
</span><span class='line'>  <span class="nd">@OutputTimeUnit</span><span class="o">(</span><span class="n">TimeUnit</span><span class="o">.</span><span class="na">NANOSECONDS</span><span class="o">)</span>
</span><span class='line'>  <span class="kd">public</span> <span class="kt">long</span> <span class="nf">nanoTimeLatency</span><span class="o">()</span> <span class="o">{</span>
</span><span class='line'>    <span class="k">return</span> <span class="n">System</span><span class="o">.</span><span class="na">nanoTime</span><span class="o">();</span>
</span><span class='line'>  <span class="o">}</span>
</span><span class='line'>
</span><span class='line'>  <span class="nd">@Benchmark</span>
</span><span class='line'>  <span class="nd">@Fork</span><span class="o">(</span><span class="mi">1</span><span class="o">)</span>
</span><span class='line'>  <span class="nd">@Threads</span><span class="o">(</span><span class="mi">1</span><span class="o">)</span>
</span><span class='line'>  <span class="nd">@Warmup</span><span class="o">(</span><span class="n">iterations</span> <span class="o">=</span> <span class="mi">10</span><span class="o">,</span> <span class="n">time</span> <span class="o">=</span> <span class="mi">5</span><span class="o">,</span> <span class="n">timeUnit</span> <span class="o">=</span> <span class="n">TimeUnit</span><span class="o">.</span><span class="na">SECONDS</span><span class="o">)</span>
</span><span class='line'>  <span class="nd">@Measurement</span><span class="o">(</span><span class="n">iterations</span> <span class="o">=</span> <span class="mi">10</span><span class="o">,</span> <span class="n">time</span> <span class="o">=</span> <span class="mi">5</span><span class="o">,</span> <span class="n">timeUnit</span> <span class="o">=</span> <span class="n">TimeUnit</span><span class="o">.</span><span class="na">SECONDS</span><span class="o">)</span>
</span><span class='line'>  <span class="nd">@BenchmarkMode</span><span class="o">(</span><span class="n">Mode</span><span class="o">.</span><span class="na">AverageTime</span><span class="o">)</span>
</span><span class='line'>  <span class="nd">@OutputTimeUnit</span><span class="o">(</span><span class="n">TimeUnit</span><span class="o">.</span><span class="na">NANOSECONDS</span><span class="o">)</span>
</span><span class='line'>  <span class="kd">public</span> <span class="kt">long</span> <span class="nf">nanoTimeGranularity</span><span class="o">(</span><span class="n">BenchmarkState</span> <span class="n">benchmarkState</span><span class="o">)</span> <span class="o">{</span>
</span><span class='line'>    <span class="kt">long</span> <span class="n">cur</span><span class="o">;</span>
</span><span class='line'>    <span class="k">do</span> <span class="o">{</span>
</span><span class='line'>      <span class="n">cur</span> <span class="o">=</span> <span class="n">System</span><span class="o">.</span><span class="na">nanoTime</span><span class="o">();</span>
</span><span class='line'>    <span class="o">}</span> <span class="k">while</span> <span class="o">(</span><span class="n">cur</span> <span class="o">==</span> <span class="n">benchmarkState</span><span class="o">.</span><span class="na">_lastNano</span><span class="o">);</span>
</span><span class='line'>    <span class="n">benchmarkState</span><span class="o">.</span><span class="na">_lastNano</span> <span class="o">=</span> <span class="n">cur</span><span class="o">;</span>
</span><span class='line'>    <span class="k">return</span> <span class="n">cur</span><span class="o">;</span>
</span><span class='line'>  <span class="o">}</span>
</span><span class='line'><span class="o">}</span>
</span></code></pre></td></tr></table></div></figure>


<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='java'><span class='line'><span class="n">Benchmark</span>                              <span class="n">Mode</span>  <span class="n">Cnt</span>   <span class="n">Score</span>   <span class="n">Error</span>  <span class="n">Units</span>
</span><span class='line'><span class="n">NanoTimeBenchmark</span><span class="o">.</span><span class="na">nanoTimeLatency</span>      <span class="n">avgt</span>   <span class="mi">10</span>  <span class="mf">42.705</span> <span class="err">±</span> <span class="mf">0.302</span>  <span class="n">ns</span><span class="o">/</span><span class="n">op</span>
</span><span class='line'><span class="n">NanoTimeBenchmark</span><span class="o">.</span><span class="na">nanoTimeGranularity</span>  <span class="n">avgt</span>   <span class="mi">10</span>  <span class="mf">43.875</span> <span class="err">±</span> <span class="mf">0.674</span>  <span class="n">ns</span><span class="o">/</span><span class="n">op</span>
</span></code></pre></td></tr></table></div></figure>


<p>This shows the overhead of getting time in both C++ and Java. They are not free!</p>
]]></content>
  </entry>
  
</feed>
