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

  <title><![CDATA[Alan Pierce]]></title>
  <link href="http://www.alangpierce.com/atom.xml" rel="self"/>
  <link href="http://www.alangpierce.com/"/>
  <updated>2018-01-07T09:51:49-08:00</updated>
  <id>http://www.alangpierce.com/</id>
  <author>
    <name><![CDATA[Alan Pierce]]></name>
    
  </author>
  <generator uri="http://octopress.org/">Octopress</generator>

  
  <entry>
    <title type="html"><![CDATA[From 200K Lines of CoffeeScript to Zero: Making Decaffeinate Super-stable]]></title>
    <link href="http://www.alangpierce.com/blog/2018/01/06/from-200k-lines-of-coffeescript-to-zero-making-decaffeinate-super-stable/"/>
    <updated>2018-01-06T07:45:36-08:00</updated>
    <id>http://www.alangpierce.com/blog/2018/01/06/from-200k-lines-of-coffeescript-to-zero-making-decaffeinate-super-stable</id>
    <content type="html"><![CDATA[<p><strong>This is a cross-post of a post of a post I made to the Benchling Engineering
blog. <a href="https://benchling.engineering/from-200k-lines-of-coffeescript-to-zero-making-decaffeinate-super-stable-4de0ca68d9bc">See the original post.</a></strong></p>

<p>The world of frontend development evolves so quickly that sometimes it feels
impossible to keep up. Even worse, what do you do with your existing code when
technologies shift? Innovations in languages, libraries, and practices are
great, but they’re only useful if they can be used in practice. To enable new
technologies, we need good modernization tools to aid in the transition process.</p>

<p>At <a href="https://benchling.com/enterprise">Benchling</a>, we chose CoffeeScript in 2013,
but about a year and a half ago, we recognized that the language was losing
steam. The community and the tools were all moving to JavaScript, and with
ES2015, JavaScript was getting much, much better. We made a decision: <strong>New code
will be in JavaScript, and for now, the 200,000 lines of CoffeeScript will stay
as-is. We’ll convert code over to JS as we find time for it.</strong> We wanted to be
entirely on JavaScript, of course, but converting that much code seemed like a
gigantic task.</p>

<p>I took that as a challenge, and a year and a half later, I’m happy to say that
that gigantic task is now complete. We’re finally at zero lines of CoffeeScript,
all with minimal disruption to feature work. At the time, there weren’t good
tools for such a big conversion, so I had to help build them. I started
contributing to the <a href="https://github.com/decaffeinate/decaffeinate">decaffeinate</a>
open source project, became the primary maintainer, and pushed it to completion.
This post is about that long journey, and now that a tool like decaffeinate
exists, it probably won’t take as long for you. 😄</p>

<h2>Why switch to JavaScript?</h2>

<p>At Benchling, we build tools to help biologists coordinate experiments, analyze
and work with DNA, and more, and one of our strengths is our modern platform. We
need to build and iterate quickly, so it’s important that we always have access
to the latest and greatest tools. (<a href="http://grnh.se/wt7plq">We’re also hiring!</a>)</p>

<p>We started with CoffeeScript in 2013, and that was the right choice at the time.
The JavaScript language was at a standstill, and CoffeeScript overhauled it by
introducing arrow functions, classes, destructuring, string templates, array
spread, and lots of other cool features. It certainly had problems, like lack of
standardization, surprises around variable scoping, and difficulty writing
tooling, but it was the best there was.</p>

<p>Over the next few years, JavaScript made a comeback. Inspired largely by many of
the CoffeeScript features, the JavaScript committee released the ES2015 spec
(a.k.a. ES6) that moved the language up to parity with CoffeeScript in some
cases and beyond in other cases, and with Babel, it was possible to use modern
JavaScript in any browser without waiting. The community became focused on
JavaScript, so the tools got better. <a href="https://eslint.org/">ESLint</a> now has
hundreds of rules and many competing popular default configurations,
<a href="https://prettier.io/">Prettier</a> is a whole new class of formatter, and
<a href="https://www.typescriptlang.org/">TypeScript</a> and <a href="https://flow.org/">Flow</a>
allow advanced type checking while staying true to JS. Switching programming
languages is never an easy choice, but it seemed like JavaScript was a safer
long-term bet, and it’s easy to use the two side-by-side, so writing new code in
JavaScript seemed reasonable.</p>

<p>Having a split codebase is possible, but it ended up hurting productivity when
working with older code. Switching back and forth between two languages is a
pain, and two frontend languages meant more for new hires to learn and more
trivial style rules to keep track of. And, of course, our new tools like ESLint
couldn’t help when modifying old CoffeeScript code, where they probably would be
most useful. A unified JavaScript codebase seemed like the right end goal.</p>

<h2>First idea: convert the code by hand</h2>

<p>One day in June 2016, a coworker decided to be ambitious: he was working with a
complex 500-line React component, GuideGroupTable.coffee, and he was going to
port it to ES6 first to make it easier to work with. Line-by-line, he carefully
reworked the syntax and some of the logic until finally, GuideGroupTable.js was
ready to try out. It broke the first time, and the second, but after fixing some
little mistakes, things seemed to work, and he wrote some additional tests to
gain more confidence in the conversion.</p>

<p>Even with tests, and even with a thorough code review, making such a big change
to complex code is risky, and it ended up introducing two bugs. In all,
converting the code, getting it reviewed, and fixing the resulting bugs took
about two engineer-days total. But at least there was a shiny new modern-looking
GuideGroupTable.js. One file down, about 1000 more to go.</p>

<p><strong>Math quiz:</strong> If every 500 lines of CoffeeScript converted takes 2 days and
introduces 2 bugs, how many days and bugs is it for 200,000 lines?</p>

<p><strong>Answer:</strong> 800 days (or 6,400 hours), 800 bugs.</p>

<p>Spending over 3 engineer-years on switching programming languages would be a
disastrous waste of time, especially for a startup; that’s time that could be
spent working on real problems that scientists are facing. At the end of the
day, <strong>cancer doesn’t care what programming language we use</strong>, and if sticking
with CoffeeScript is the pragmatic choice, that’s what we’ll do.</p>

<p>Maybe this was just a particularly difficult case and other code would be
easier. Even if these estimates are too high by a factor of ten, 640 hours and
80 bugs is still way too much to ask. If we’re going to move off of CoffeeScript
at all, there needs to be a better way.</p>

<h2>Second idea: the CoffeeScript compiler</h2>

<p>In a certain sense, automatically converting CoffeeScript to JavaScript is
trivial: just run it through the CoffeeScript compiler. The newest versions of
CoffeeScript (which didn’t exist at the time) produce pretty good code, but
<a href="http://coffeescript.org/#try:toolbarMouseOverHandler%20%3D%20%28fmt%29%20-%3E%0A%20%20%20%20attachFmts%20%3D%20%5B%0A%20%20%20%20%20%20%20%20%27table%27%2C%20%27day%27%2C%20%27attach%27%2C%20DATA_TABLE%2C%20DATA_TABLE_CONFIG%2C%0A%20%20%20%20%20%20%20%20REGISTRATION_TABLE%2C%20NOTE_LINKED_ASSAY_DATA%0A%20%20%20%20%5D%0A%20%20%20%20%7Bindex%2C%20subIndex%7D%20%3D%20%40state.selected%0A%20%20%20%20%0A%20%20%20%20if%20fmt%20in%20%5B%27left%27%2C%20%27center%27%2C%20%27right%27%2C%20%27important%27%5D%0A%20%20%20%20%20%20%20%20%40setState%20%7BhighlightIndex%3A%20index%7D%0A%20%20%20%20else%20if%20fmt%20%3D%3D%20%27delete%27%20and%20subIndex%20!%3D%20%27item%27%0A%20%20%20%20%20%20%20%20%40setState%20%7BhighlightIndex%3A%20index%7D%0A%20%20%20%20else%20if%20fmt%20in%20attachFmts%0A%20%20%20%20%20%20%20%20%40setState%20%7BinsertIndex%3A%20index%7D%0A%20%20%20%20return">there’s still quite a bit to be desired</a>:</p>

<ul>
<li>It reformats your code: it switches to two-space indentation, it deletes blank
lines, it sometimes expands one-liners to multiple lines, and it sometimes joins
multi-line expressions into one long line.</li>
<li>It always uses <code>var</code> and declares all variables at the top of the file/function.</li>
<li>It sometimes generates awkward code for the sake of strict correctness, like
using <code>void 0</code> instead of <code>undefined</code> or <code>[].indexOf.call(array, x)</code> instead of
<code>array.indexOf(x)</code>.
If you’re still on CoffeeScript version 1, you’ll see more issues: that compiler
also removes inline comments and doesn’t attempt to use newer JS features like
classes and destructuring.</li>
</ul>


<p>In short, the CoffeeScript compiler is a good compiler, but not a great codebase
conversion tool, so we decided to look for other approaches.</p>

<h2>Third idea: decaffeinate</h2>

<p>We weren’t the only company with this problem, and through some discussions, I
heard about a tool called <a href="https://github.com/decaffeinate/decaffeinate">decaffeinate</a>
that tried to solve this problem: it took
in CoffeeScript and produced modern JavaScript, at least as much as it could.
Unlike the CoffeeScript compiler, <a href="http://decaffeinate-project.org/repl/#?evaluate=true&amp;stage=full&amp;code=toolbarMouseOverHandler%20%3D%20%28fmt%29%20-%3E%0A%20%20%20%20attachFmts%20%3D%20%5B%0A%20%20%20%20%20%20%20%20%27table%27%2C%20%27day%27%2C%20%27attach%27%2C%20DATA_TABLE%2C%20DATA_TABLE_CONFIG%2C%0A%20%20%20%20%20%20%20%20REGISTRATION_TABLE%2C%20NOTE_LINKED_ASSAY_DATA%0A%20%20%20%20%5D%0A%20%20%20%20%7Bindex%2C%20subIndex%7D%20%3D%20%40state.selected%0A%20%20%20%20%0A%20%20%20%20if%20fmt%20in%20%5B%27left%27%2C%20%27center%27%2C%20%27right%27%2C%20%27important%27%5D%0A%20%20%20%20%20%20%20%20%40setState%20%7BhighlightIndex%3A%20index%7D%0A%20%20%20%20else%20if%20fmt%20%3D%3D%20%27delete%27%20and%20subIndex%20!%3D%20%27item%27%0A%20%20%20%20%20%20%20%20%40setState%20%7BhighlightIndex%3A%20index%7D%0A%20%20%20%20else%20if%20fmt%20in%20attachFmts%0A%20%20%20%20%20%20%20%20%40setState%20%7BinsertIndex%3A%20index%7D%0A%20%20%20%20return">it keeps your formatting and tries to use modern syntax and patterns</a>.</p>

<p>I installed it and tried it out on our codebase. Out of 1200 files, it failed on
about 600 of them. On the plus side, <strong>it successfully converted half of the
files</strong>.</p>

<p>It was promising, but it certainly wasn’t done. Lots of features were explicitly
not supported: <code>?.</code>, <code>for own</code> loops, loops used as expressions, complex class
bodies, and more. And most of the time, you’d get a confusing error like
“Unexpected token” with no further context.</p>

<p>I hadn’t made many GitHub contributions before, but it seemed like a reasonable
place to start. I filed some bugs, improved some error reporting, learned the
code better and better, and eventually, I was a regular contributor. For the
last year or so, I’ve been the primary maintainer.</p>

<p>If you want to try it out, the <a href="http://decaffeinate-project.org/repl/">REPL</a> is
a nice interactive environment where you can type or paste some CoffeeScript and
see what decaffeinate produces.</p>

<h2>How does decaffeinate work?</h2>

<p>Is decaffeinate a compiler? Maybe it’s a <em>trans</em>piler? (Is that really any
different?) I’d say it’s neither; it’s something else entirely. It’s similar to
a compiler, but it has different goals and, in this case, a different
architecture.</p>

<h3>The CoffeeScript compiler approach: code → AST → code</h3>

<p>First, let’s see how the CoffeeScript compiler handles some example 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='coffee'><span class='line'><span class="k">if</span> <span class="nx">isHappy</span> <span class="k">then</span> <span class="nx">cheer</span><span class="p">()</span>
</span></code></pre></td></tr></table></div></figure>


<p>First, it splits the code up into <strong>tokens</strong>: <code>IF</code>, <code>IDENTIFIER: isHappy</code>, <code>THEN</code>,
<code>IDENTIFIER: cheer</code>, <code>CALL_START</code>, <code>CALL_END</code>, <code>TERMINATOR</code>.</p>

<p>Then, it parses the tokens into an <strong>abstract syntax tree</strong> (AST):</p>

<p><img src="http://www.alangpierce.com/images/coffee_ast.png" alt="CoffeeScript AST" /></p>

<p>Each AST node then knows how to format itself into JavaScript 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='js'><span class='line'><span class="k">if</span> <span class="p">(</span><span class="nx">isHappy</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>  <span class="nx">cheer</span><span class="p">();</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>Notice that the one-liner was expanded to multiple lines. CoffeeScript doesn’t
take any formatting into account when producing output, since it throws away the
code and only uses the AST when generating JavaScript.</p>

<h3>The decaffeinate approach: targeted replacement</h3>

<p>Many of the details in decaffeinate are similar, but it focuses on <em>editing your
code, not rewriting it</em>. Rather than producing new code, it uses the AST and
tokens to generate a list of changes to the code. In this case, decaffeinate
uses the token positions to recognize that the <code>if</code> statement is a one-liner, then
makes these changes:</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=''><span class='line'>Insert "(" before "isHappy"
</span><span class='line'>Insert ")" after "isHappy"
</span><span class='line'>Delete "then "
</span><span class='line'>Insert "{ " before "cheer()"
</span><span class='line'>Insert ";" after "cheer()"
</span><span class='line'>Insert " }" after "cheer()"</span></code></pre></td></tr></table></div></figure>


<p>Those operations are then applied to the original 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='js'><span class='line'><span class="k">if</span> <span class="p">(</span><span class="nx">isHappy</span><span class="p">)</span> <span class="p">{</span> <span class="nx">cheer</span><span class="p">();</span> <span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>Your code only changes where it needs to, and in most cases, the shape of the
code is the same as before.</p>

<p>Is this the right architecture? Frankly, it’s unclear, and projects like
<a href="https://prettier.io/">Prettier</a> have made a compelling argument that codebases
should simply have zero manual formatting anyway. But it’s the architecture
decaffeinate went with.</p>

<h2>Is it even possible?</h2>

<p>When building an automatic translation from one programming language to another,
you run into an uncomfortable possibility: <strong>the problem you’re solving might be
impossible</strong>.</p>

<p>Let’s take an example. Ideally, CoffeeScript classes can always be converted to
JavaScript classes. Here’s one CoffeeScript class that uses a feature you may
not have seen:</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>
</pre></td><td class='code'><pre><code class='coffee'><span class='line'><span class="k">class</span> <span class="nx">Giraffe</span>
</span><span class='line'>  <span class="k">if</span> <span class="nx">ENABLE_LOUD_GIRAFFES</span>
</span><span class='line'>    <span class="nv">roar: </span><span class="nf">-&gt;</span>
</span><span class='line'>      <span class="k">return</span> <span class="s">&#39;ROAR!!!&#39;</span>
</span><span class='line'>  <span class="k">else</span>
</span><span class='line'>    <span class="nv">roar: </span><span class="nf">-&gt;</span>
</span><span class='line'>      <span class="k">return</span> <span class="s">&#39;roar...&#39;</span>
</span></code></pre></td></tr></table></div></figure>


<p>Yep, you can do that in CoffeeScript! Not only can you conditionally define
methods, you can run arbitrary code at class setup time. JS classes can only
consist of plain methods (for now), so there simply isn’t a way to do this. You
can try, and you’ll get a syntax error:</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='js'><span class='line'><span class="kr">class</span> <span class="nx">Giraffe</span> <span class="p">{</span>
</span><span class='line'>  <span class="k">if</span> <span class="p">(</span><span class="nx">ENABLE_LOUD_GIRAFFES</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>    <span class="nx">roar</span><span class="p">()</span> <span class="p">{</span>  <span class="c1">// &lt;- Unexpected token, expected ; (3:11)</span>
</span><span class='line'>      <span class="k">return</span> <span class="s1">&#39;ROAR!!!&#39;</span><span class="p">;</span>
</span><span class='line'>    <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="nx">roar</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'>      <span class="k">return</span> <span class="s1">&#39;roar...&#39;</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></code></pre></td></tr></table></div></figure>


<p>If you’re moving this code over manually, you’d think to yourself “I guess that
trick doesn’t work in JavaScript, so I’ll rethink the code”, but that’s not
possible with an automated tool.</p>

<p>So how should a tool like decaffeinate approach this? There are a few options:</p>

<ol>
<li>Fall back to the CoffeeScript implementation. That’s not so unreasonable, but
ideally CS classes would always become JS classes. It’s also not as easy as it
sounds, given the different architectures.</li>
<li>Throw an error, saying that this syntax isn’t supported. Anyone wanting to run
decaffeinate on code like this needs to dumb down the code first.</li>
<li>Find some trick to make it work anyway.</li>
</ol>


<p>#3 is where decaffeinate really shines: there are lots of little tricks to make
the code look as good as possible while still being correct.</p>

<h2>Case study: converting array comprehensions</h2>

<p>Let’s take a look at some CoffeeScript 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='coffee'><span class='line'><span class="nv">colors = </span><span class="p">(</span><span class="nx">marker</span><span class="p">.</span><span class="nx">color</span> <span class="k">for</span> <span class="nx">marker</span> <span class="k">in</span> <span class="nx">getMarkers</span><span class="p">())</span>
</span></code></pre></td></tr></table></div></figure>


<p>Looks pretty clean (although you’ll get an <a href="http://coffeescript.org/#try:%23%20Creates%20an%20array%20called%20%60colors%60.%0Acolors%20%3D%20%28marker.color%20for%20marker%20in%20getMarkers%28%29%29%0A%0A%23%20Assigns%20to%20%60colors%60%20in%20each%20loop%20iteration.%0Acolors%20%3D%20marker.color%20for%20marker%20in%20getMarkers%28%29">unpleasant surprise</a> if you forget the
parens). JavaScript doesn’t have array comprehensions, so we’ll need to find
some alternative.</p>

<p>Here’s how the CoffeeScript compiler handles 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>
</pre></td><td class='code'><pre><code class='js'><span class='line'><span class="kd">var</span> <span class="nx">colors</span><span class="p">,</span> <span class="nx">marker</span><span class="p">;</span>
</span><span class='line'><span class="nx">colors</span> <span class="o">=</span> <span class="p">(</span><span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'>  <span class="kd">var</span> <span class="nx">i</span><span class="p">,</span> <span class="nx">len</span><span class="p">,</span> <span class="nx">ref</span><span class="p">,</span> <span class="nx">results</span><span class="p">;</span>
</span><span class='line'>  <span class="nx">ref</span> <span class="o">=</span> <span class="nx">getMarkers</span><span class="p">();</span>
</span><span class='line'>  <span class="nx">results</span> <span class="o">=</span> <span class="p">[];</span>
</span><span class='line'>  <span class="k">for</span> <span class="p">(</span><span class="nx">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="nx">len</span> <span class="o">=</span> <span class="nx">ref</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span> <span class="nx">i</span> <span class="o">&lt;</span> <span class="nx">len</span><span class="p">;</span> <span class="nx">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>    <span class="nx">marker</span> <span class="o">=</span> <span class="nx">ref</span><span class="p">[</span><span class="nx">i</span><span class="p">];</span>
</span><span class='line'>    <span class="nx">results</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="nx">marker</span><span class="p">.</span><span class="nx">color</span><span class="p">);</span>
</span><span class='line'>  <span class="p">}</span>
</span><span class='line'>  <span class="k">return</span> <span class="nx">results</span><span class="p">;</span>
</span><span class='line'><span class="p">})();</span>
</span></code></pre></td></tr></table></div></figure>


<p>Yuck. It works, but it certainly wouldn’t pass code review. Here’s what we
really want:</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='js'><span class='line'><span class="kr">const</span> <span class="nx">colors</span> <span class="o">=</span> <span class="nx">getMarkers</span><span class="p">().</span><span class="nx">map</span><span class="p">((</span><span class="nx">marker</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="nx">marker</span><span class="p">.</span><span class="nx">color</span><span class="p">);</span>
</span></code></pre></td></tr></table></div></figure>


<p>Looks pretty clean, and not too different from the original code. But is it
<em>correct</em>? It certainly looks right, but would you be willing to run this
transformation (<code>a for b in c</code> to <code>c.map(b =&gt; a)</code>) on hundreds of thousands of lines
of code? As it turns out, <strong>it’s not correct</strong>. If you want, you can stop reading
and think about what goes wrong.</p>

<p>I implemented this transformation, ran decaffeinate on a few thousand lines of
code from work, did lots of testing, including existing automated tests, and it
still ended up causing a crash in production.</p>

<p>Here’s the old CoffeeScript:</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='coffee'><span class='line'><span class="nv">cids = </span><span class="p">(</span><span class="nx">$</span><span class="p">(</span><span class="nx">row</span><span class="p">).</span><span class="nx">attr</span><span class="p">(</span><span class="s">&#39;data-id&#39;</span><span class="p">)</span> <span class="k">for</span> <span class="nx">row</span> <span class="k">in</span> <span class="nx">$el</span><span class="p">.</span><span class="nx">find</span><span class="p">(</span><span class="s">&#39;.alignment-row&#39;</span><span class="p">))</span>
</span></code></pre></td></tr></table></div></figure>


<p>And here’s the new JavaScript:</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='js'><span class='line'><span class="kd">let</span> <span class="nx">cids</span> <span class="o">=</span> <span class="nx">$el</span><span class="p">.</span><span class="nx">find</span><span class="p">(</span><span class="s1">&#39;.alignment-row&#39;</span><span class="p">).</span><span class="nx">map</span><span class="p">((</span><span class="nx">row</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="nx">$</span><span class="p">(</span><span class="nx">row</span><span class="p">).</span><span class="nx">attr</span><span class="p">(</span><span class="s1">&#39;data-id&#39;</span><span class="p">));</span>
</span></code></pre></td></tr></table></div></figure>


<p>The fundamental problem here is that <strong>you might not be working with an array</strong>. In
this case, it was a jQuery collection, where <code>map</code> exists, but doesn’t produce an
array.</p>

<p>This problem is all over the place in CoffeeScript: every time you iterate
through something in CoffeeScript, it needs to be array-like. That means you
need <code>arr.length</code>, <code>arr[0]</code>, <code>arr[1]</code>, etc. When ES2015 came around, they decided to
do things differently: they created the <em>iterable protocol</em>. Any object that wants
to be iterable can expose a <code>Symbol.iterator</code> function that describes how to
iterate through the object. That’s what JavaScript uses for iteration when you
use <code>for (const rhino of rhinos)</code> or <code>children = [...children, baby]</code>. Arrays are
both array-like and iterable, but plenty of JS objects are array-like but not
iterable, and even more objects don’t have <code>map</code> (or have a <code>map</code> that works
differently). Strings, jQuery collections, and FileList (but only in Safari) can
all cause problems here.</p>

<p>Fortunately, there’s a simple built-in function that converts array-like objects
to true arrays: <code>Array.from</code>. To systematically avoid this problem, we can throw
in <code>Array.from</code> anywhere we iterate over anything, and <a href="http://decaffeinate-project.org/repl/#?evaluate=true&amp;stage=full&amp;code=for%20rhino%20in%20rhinos%0A%20%20console.log%20rhino%0Achildren%20%3D%20%5Bchildren...%2C%20baby%5D%0Acids%20%3D%20%28%24%28row%29.attr%28%27data-id%27%29%20for%20row%20in%20%24el.find%28%27.alignment-row%27%29%29">this is what decaffeinate does</a>.</p>

<p>This is one of the toughest design questions of decaffeinate: how important is
correctness <em>really</em>? If a bug only comes up every few thousand lines of code, do
we really want to defensively add <code>Array.from</code> on <em>all</em> iteration operators?</p>

<p>After a lot of thinking, I decided that <strong>yes, <a href="https://github.com/decaffeinate/decaffeinate/blob/master/docs/correctness-issues.md">decaffeinate should be completely correct on all reasonable code</a></strong>. There’s a judgement call about what is
“reasonable”, but decaffeinate needs to be trustworthy. decaffeinate’s goal is
to speed up the conversion from CoffeeScript to JS, and if you need to
extensively manually test your code after decaffeinate, it will take much, much
longer. decaffeinate needs to be as stable as any compiler.</p>

<p>If you use decaffeinate, you’ll probably see <code>Array.from</code> all over the place. You
can disable it with the <code>--loose</code> option, but I’d recommend instead looking through
the resulting code and only removing <code>Array.from</code> when you’re confident that the
object you’re working with is already an array.</p>

<h2>Reaching super-stability</h2>

<p>Between July and December 2016, decaffeinate slowly got more and more stable
when run on the Benchling code. 500 files failing, then 350, then 200, then 50,
then 10, then 5, then 0. After some cheers and excitement, I ran the tests for
the newly-decaffeinated codebase, and they crashed immediately. More work to do,
I guess. I fixed a bug, I fixed another bug, I tracked down and <a href="https://github.com/eslint/eslint/pull/7811">fixed an ESLint bug</a>, I upgraded Babel to work around a Babel bug, I kept on iterating, and
finally it got to a point of the tests passing.</p>

<p>So now what? decaffeinate seemed to work great on the code that was covered by
tests, but what about the code that wasn’t covered by tests? I could write
100,000 lines of tests to try to get full code coverage, but that might take a
while. I needed to find <em>more test cases for decaffeinate</em>, and fortunately, the
internet has no shortage of CoffeeScript code. I set up a build system that
would run decaffeinate on a bunch of projects, patch them to use Babel, then run
all of the tests. A <a href="https://github.com/decaffeinate/decaffeinate#status">status board on the README</a> was also a good motivating factor
and a good way to see progress. Here were some of the results early on:</p>

<p><img src="http://www.alangpierce.com/images/decaffeinate_tests_before.png" alt="decaffeinate tests with many errors" /></p>

<p>Testing out decaffeinate on codebases with a wide variety of authors and coding
styles worked out great, and setting up the tests allowed me to discover the
most critical bugs. There were <a href="https://github.com/decaffeinate/decaffeinate/issues/867">lots</a> <a href="https://github.com/decaffeinate/decaffeinate/issues/858">and</a> <a href="https://github.com/decaffeinate/decaffeinate/issues/878">lots</a> <a href="https://github.com/decaffeinate/decaffeinate/issues/902">of</a> <a href="https://github.com/decaffeinate/decaffeinate/issues/882">bugs</a>, but after a few months, I
finally got everything working:</p>

<p><img src="http://www.alangpierce.com/images/decaffeinate_tests_after.png" alt="decaffeinate tests, all passing" /></p>

<p>It’s rare that you ever get to say that a software project is complete, but I
think this is one of those times. Technically, there’s still a bit more that
would be useful, and I did some follow-up work to add a suggestions system and
clean up usage, but decaffeinate is now in maintenance mode.</p>

<h2>Getting to zero</h2>

<p>With decaffeinate stable, we were finally at a point where it wasn’t crazy to
run it on large swaths of code without extensive testing or review. So what do
you do when you have a tool like that and 150,000 lines of CoffeeScript to
convert? Somehow, converting it all at once seemed a little worrying.</p>

<p>Here’s the strategy we took: every Tuesday, we’d pick off a large chunk of code
and run it through decaffeinate, first about 5000 lines, then larger and larger
chunks, up to 20,000 lines at once. We always had a 100%-machine-automated set
of commits, then two of us scanned through the converted code and made any safe
cleanups we could find. That did not mean blindly removing all usages of
<code>Array.from</code> or other decaffeinate artifacts; it meant fixing formatting, removing
unused variables, renaming autogenerated variables to other names, etc. The code
at the end wasn’t pristine, but it was JavaScript, and it was much better than
what the CoffeeScript compiler gives.</p>

<p>The stability work paid off, and after repeating this process for about 10
weeks, we finally were able to get it completely to zero with very few issues.
That also meant that it was possible to remove CoffeeScript from the build
system, disable CoffeeLint, and delete our CoffeeScript style guide.</p>

<p>In a sense, the job still isn’t done. We still have lots of files with
decaffeinate artifacts and disabled lint rules that should eventually be
manually cleaned up. One of our biggest auto-converted files starts with this:</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>
</pre></td><td class='code'><pre><code class='js'><span class='line'><span class="cm">/* eslint-disable</span>
</span><span class='line'><span class="cm">    camelcase,</span>
</span><span class='line'><span class="cm">    consistent-return,</span>
</span><span class='line'><span class="cm">    default-case,</span>
</span><span class='line'><span class="cm">    func-names,</span>
</span><span class='line'><span class="cm">    new-cap,</span>
</span><span class='line'><span class="cm">    no-case-declarations,</span>
</span><span class='line'><span class="cm">    no-cond-assign,</span>
</span><span class='line'><span class="cm">    no-multi-assign,</span>
</span><span class='line'><span class="cm">    no-return-assign,</span>
</span><span class='line'><span class="cm">    no-sequences,</span>
</span><span class='line'><span class="cm">    no-shadow,</span>
</span><span class='line'><span class="cm">    no-unused-vars,</span>
</span><span class='line'><span class="cm">    no-use-before-define,</span>
</span><span class='line'><span class="cm">    no-var,</span>
</span><span class='line'><span class="cm">    one-var,</span>
</span><span class='line'><span class="cm">    prefer-const,</span>
</span><span class='line'><span class="cm">    prefer-rest-params,</span>
</span><span class='line'><span class="cm">    react/no-is-mounted,</span>
</span><span class='line'><span class="cm">    vars-on-top,</span>
</span><span class='line'><span class="cm">*/</span>
</span><span class='line'><span class="c1">// TODO: This file was created by bulk-decaffeinate.</span>
</span><span class='line'><span class="c1">// Fix any style issues and re-enable lint.</span>
</span><span class='line'><span class="cm">/*</span>
</span><span class='line'><span class="cm"> * decaffeinate suggestions:</span>
</span><span class='line'><span class="cm"> * DS101: Remove unnecessary use of Array.from</span>
</span><span class='line'><span class="cm"> * DS102: Remove unnecessary code created because of implicit returns</span>
</span><span class='line'><span class="cm"> * DS103: Rewrite code to no longer use __guard__</span>
</span><span class='line'><span class="cm"> * DS104: Avoid inline assignments</span>
</span><span class='line'><span class="cm"> * DS201: Simplify complex destructure assignments</span>
</span><span class='line'><span class="cm"> * DS202: Simplify dynamic range loops</span>
</span><span class='line'><span class="cm"> * DS204: Change includes calls to have a more natural evaluation order</span>
</span><span class='line'><span class="cm"> * DS205: Consider reworking code to avoid use of IIFEs</span>
</span><span class='line'><span class="cm"> * DS207: Consider shorter variations of null checks</span>
</span><span class='line'><span class="cm"> * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md</span>
</span><span class='line'><span class="cm"> */</span>
</span></code></pre></td></tr></table></div></figure>


<p>So it’s not perfect, but it’s pretty easy to do the remaining cleanup work as
you go.</p>

<p>Let’s compare my original estimate with the actual cost of converting 200,000
lines of code:</p>

<p><strong>Estimated cost without decaffeinate:</strong> 6,400 hours, 800 bugs.</p>

<p><strong>Actual cost with decaffeinate:</strong> ~100 hours, ~5 bugs.</p>

<p>(Not including the work on decaffeinate, which was in my spare time. 😄).</p>

<p>Those 100 hours were mostly spent spot-checking and cleaning up the resulting
JS, code reviewing those cleanups, manually testing the relevant features, and
deploying the changes gradually to reduce risk. 2000 lines of code per hour
seemed like a safe rate, but theoretically, it could have all been done at once,
and if you’re in a hurry, you could probably go much faster.</p>

<h2>What went wrong?</h2>

<p>decaffeinate is extremely stable, but the conversion process still wasn’t
without its bugs. By far, the largest source of bugs was <strong>human error</strong>. Let’s look
at some code, before and after decaffeinate:</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='coffee'><span class='line'><span class="nv">_clearWorkspace: </span><span class="nf">(itemIdsToKeep = []) -&gt;</span>
</span><span class='line'>  <span class="nx">@_closeAllFilesExcept</span> <span class="nf">(itemFileId) -&gt;</span> <span class="nx">itemFileId</span> <span class="k">in</span> <span class="nx">itemIdsToKeep</span>
</span><span class='line'>  <span class="k">return</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>
</pre></td><td class='code'><pre><code class='js'><span class='line'><span class="nx">_clearWorkspace</span><span class="p">(</span><span class="nx">itemIdsToKeep</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>  <span class="k">if</span> <span class="p">(</span><span class="nx">itemIdsToKeep</span> <span class="o">==</span> <span class="kc">null</span><span class="p">)</span> <span class="p">{</span> <span class="nx">itemIdsToKeep</span> <span class="o">=</span> <span class="p">[];</span> <span class="p">}</span>
</span><span class='line'>  <span class="k">this</span><span class="p">.</span><span class="nx">_closeAllFilesExcept</span><span class="p">(</span><span class="nx">itemFileId</span> <span class="o">=&gt;</span> <span class="nb">Array</span><span class="p">.</span><span class="nx">from</span><span class="p">(</span><span class="nx">itemIdsToKeep</span><span class="p">).</span><span class="nx">includes</span><span class="p">(</span><span class="nx">itemFileId</span><span class="p">));</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>decaffeinate moved the default param to an <code>if</code> statement <a href="https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md#ds105-use-default-params-and-defaults-within-assignments-when-possible">in order to be
technically correct</a>, wrapped <code>itemIdsToKeep</code> in <code>Array.from</code>, and changed the <code>in</code>
operator to the <code>includes</code> method. The <code>if</code> statement and the <code>Array.from</code> could both
use cleanup, and in this case we played it safe and only removed the <code>Array.from</code>,
since it clearly seemed like an array:</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>
</pre></td><td class='code'><pre><code class='js'><span class='line'><span class="nx">_clearWorkspace</span><span class="p">(</span><span class="nx">itemIdsToKeep</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>  <span class="k">if</span> <span class="p">(</span><span class="nx">itemIdsToKeep</span> <span class="o">==</span> <span class="kc">null</span><span class="p">)</span> <span class="p">{</span> <span class="nx">itemIdsToKeep</span> <span class="o">=</span> <span class="p">[];</span> <span class="p">}</span>
</span><span class='line'>  <span class="k">this</span><span class="p">.</span><span class="nx">_closeAllFilesExcept</span><span class="p">(</span><span class="nx">itemFileId</span> <span class="o">=&gt;</span> <span class="nx">itemIdsToKeep</span><span class="p">.</span><span class="nx">includes</span><span class="p">(</span><span class="nx">itemFileId</span><span class="p">));</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>As it turns out, <code>itemIdsToKeep</code> was <strong>not</strong> always an array. Purely by mistake, it
could sometimes be a <em>DOM event</em> instead. Both CoffeeScript and <code>Array.from</code>
silently treat it as the empty array in that case, but removing <code>Array.from</code>
exposed the crash.</p>

<p>This is an example of a theme that occurred a number of times: <strong>decaffeinate
tends to break on code that is already buggy</strong>.</p>

<p>Let’s look at another example. Here’s some CoffeeScript before and JavaScript
after:</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='coffee'><span class='line'><span class="nv">parse: </span><span class="nf">(response) -&gt;</span>
</span><span class='line'>  <span class="nv">response.features = </span><span class="k">new</span> <span class="nx">selectables</span><span class="p">.</span><span class="nx">Collection</span><span class="p">(</span><span class="nx">response</span><span class="p">.</span><span class="nx">features</span><span class="p">)</span>
</span><span class='line'>  <span class="k">return</span> <span class="nx">response</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>
</pre></td><td class='code'><pre><code class='js'><span class='line'><span class="nx">parse</span><span class="p">(</span><span class="nx">response</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>  <span class="nx">response</span><span class="p">.</span><span class="nx">features</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">selectables</span><span class="p">.</span><span class="nx">Collection</span><span class="p">(</span><span class="nx">response</span><span class="p">.</span><span class="nx">features</span><span class="p">);</span>
</span><span class='line'>  <span class="k">return</span> <span class="nx">response</span><span class="p">;</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>Seems pretty simple, right? What could go wrong?</p>

<p>As it turns out, the problem wasn’t so much a conversion error as an unexpected
consequence in switching compilers: <strong>switching from CoffeeScript to Babel enables
strict mode</strong>. Without strict mode, assigning to a non-writable property is a
no-op, and in strict mode it crashes. In this case, <code>response</code> was supposed to be
an object, but instead was sometimes <em>the empty string</em>, which meant that the
assignment simply did nothing. This was just a bug, but it was a benign bug
before and switching to Babel made it a crashing bug.</p>

<p>How can you avoid running into these same problems? Some ideas:</p>

<ul>
<li>Try to defer extensive manual cleanups until you’re working heavily with the
code and are comfortable testing all of its edge cases. Over and over, we found
that a cleanup that seemed safe actually had subtle flaws, and often times it
was best to just go with the decaffeinate output.</li>
<li>You may want to move to strict mode separately from moving to JS. One way to do
this is with the <a href="https://github.com/genify/babel-plugin-transform-remove-strict-mode">babel-plugin-transform-remove-strict-mode</a> Babel plugin. That
will keep you on the lookout for the types of errors that arise in strict mode.</li>
</ul>


<h2>Other things to know before using decaffeinate</h2>

<p>Here are some more things to keep in mind:</p>

<ul>
<li><p>The hardest problem that decaffeinate had to solve is handling <code>this</code> before <code>super</code>
in constructors, which is allowed in CS but not in JS. There’s a <a href="https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md#ds001-remove-babeltypescript-constructor-workaround">hack</a> to trick
Babel and TypeScript into allowing it, but it’s an ugly hack that you should
remove ASAP after running decaffeinate.</p></li>
<li><p>To help run decaffeinate along with other tools, I wrote a tool called
<a href="https://github.com/decaffeinate/bulk-decaffeinate">bulk-decaffeinate</a> that runs decaffeinate, several jscodeshift transforms (e.g.
converting code to JSX), <code>eslint --fix</code> and several other steps. You’ll probably
want to either use that tool or one you write yourself, since decaffeinate is
more of a building block.</p></li>
<li><p>There have been some great previous blog posts on decaffeinate: <a href="https://blog.bugsnag.com/converting-a-large-react-codebase-from-coffeescript-to-es6/">Converting a large React Codebase from Coffeescript to ES6</a> and
<a href="https://eng.datafox.com/javascript/2017/07/18/decaffeinating-large-coffeescript-codebase/">Decaffeinating a Large CoffeeScript Codebase Without Losing Sleep</a>.</p></li>
<li><p>The decaffeinate docs have some pages to help you through the process: the
<a href="https://github.com/decaffeinate/decaffeinate/blob/master/docs/conversion-guide.md">Conversion Guide</a> has some practical advice on running decaffeinate on a big
codebase, and the Cleanup <a href="https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md">Suggestions page</a> lists most of the subtleties you’ll
see in the converted code. You can also drop in on <a href="https://gitter.im/decaffeinate/Lobby">Gitter</a> to ask questions!</p></li>
</ul>


<p>Every project and team is different, though, so regardless of how you approach
it, you’ll likely need some real effort and care. But hopefully, once the
conversion strategy, the configuration, and any other details are figured out,
the gruntwork will all be safely handled by decaffeinate!</p>

<h2>Migration tools let you focus on what’s important</h2>

<p>Programming is full of tradeoffs, and a common pitfall is to focus too much on
your code when you should be focusing on the real problem that you’re solving.
Whether it’s formatting, variable names, code structure, or even what
programming language to use, none of it matters if the product doesn’t actually
help people. Big code migrations can sometimes feel necessary and benefit in the
long run, but they can also be a big distraction and a massive time sink. It’s
often an awkward tradeoff, but with solid migration tools like decaffeinate, you
can get the best of both worlds: you can benefit from the latest tools and
practices while still focusing your time and brainpower on solving real problems
and helping people.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Adventures in Go: Accessing Unexported Functions]]></title>
    <link href="http://www.alangpierce.com/blog/2016/03/17/adventures-in-go-accessing-unexported-functions/"/>
    <updated>2016-03-17T19:00:00-07:00</updated>
    <id>http://www.alangpierce.com/blog/2016/03/17/adventures-in-go-accessing-unexported-functions</id>
    <content type="html"><![CDATA[<p>I&rsquo;ve been learning the Go programming language in my favorite way: by writing a
Go interpreter in Go. The source code so far is
<a href="https://github.com/alangpierce/apgo">on GitHub</a>, but the point of this post is
to tell the story of a particularly interesting challenge I ran into:
programmatically accessing unexported (a.k.a. private) functions in other
packages. In the process of figuring this out, I learned about lots of escape
hatches and limitations of Go. The result of the adventure is a little library I
made and put on GitHub called
<a href="https://github.com/alangpierce/go-forceexport">go-forceexport</a>. If you want a
TLDR, you can just read the source code, but hopefully you&rsquo;ll find the adventure
interesting as well!</p>

<p>My perspective in this post is someone who has plenty of experience with
programming both low-level and high-level languages, but is new to the Go
language and curious about its internals and how it compares to other languages.
In both the exploration process and the process of writing this post, I learned
quite a bit about the right way to think about Go. Hopefully by reading this
you&rsquo;ll be able to learn some of those lessons and also share the same curiosity.</p>

<h2>What are unexported functions are and why would I want to call one?</h2>

<p>In Go, capitalization matters, and determines whether a name can be accessed
from the outside world. For example:</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>
</pre></td><td class='code'><pre><code class='go'><span class='line'><span class="kd">func</span> <span class="nx">thisFunctionIsUnexported</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'>    <span class="nx">fmt</span><span class="p">.</span><span class="nx">Println</span><span class="p">(</span><span class="s">&quot;This function starts with a &#39;t&#39; and can only be called from this package.&quot;</span><span class="p">)</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="kd">func</span> <span class="nx">ThisFunctionIsExported</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'>    <span class="nx">fmt</span><span class="p">.</span><span class="nx">Println</span><span class="p">(</span><span class="s">&quot;This function starts with a &#39;T&#39; and can be called from anywhere.&quot;</span><span class="p">)</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>Other languages use the terms &ldquo;private&rdquo; and &ldquo;public&rdquo; for this distinction, but
in Go, they&rsquo;re called <strong>unexported</strong> and <strong>exported</strong>.</p>

<p>But what about when you just want to hack and explore, and you can&rsquo;t easily
modify the code in question? In Python, you might see a name starting with an
underscore, like <code>_this_function_is_private</code>, meaning that it&rsquo;s rude to call it
from the outside world, but the runtime doesn&rsquo;t try to stop you. In Java, you
can generally defeat the <code>private</code> keyword using reflection and the
<a href="http://docs.oracle.com/javase/6/docs/api/java/lang/reflect/AccessibleObject.html#setAccessible%28boolean%29">setAccessible</a>
method. Neither of these are good practice in professional code, but the
flexibility is nice if you&rsquo;re trying to figure out what&rsquo;s going wrong in a
library or if you want to build a proof of concept that you&rsquo;ll later make more
professional.</p>

<p>It also can be used as a substitute when other ways of exploring aren&rsquo;t
available. In Python, nothing is compiled, so you can add print statements to
the standard library or hack the code in other ways and it&rsquo;ll just work. Java
has an excellent debugging story, so you can learn a lot about library code by
stepping through it in an IDE. In Go, neither of these approaches are very
pleasant (as far as I&rsquo;ve seen), so calling internal functions can sometimes be
the next best thing.</p>

<p>In my specific case, the milestone I was trying to achieve was for my interpeter
to be able to successfully run the <code>time.Now</code> function in the standard library.
Let&rsquo;s take a look at the relevant part of
<a href="https://golang.org/src/time/time.go">time.go</a>:</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>
</pre></td><td class='code'><pre><code class='go'><span class='line'><span class="c1">// Provided by package runtime.</span>
</span><span class='line'><span class="kd">func</span> <span class="nx">now</span><span class="p">()</span> <span class="p">(</span><span class="nx">sec</span> <span class="kt">int64</span><span class="p">,</span> <span class="nx">nsec</span> <span class="kt">int32</span><span class="p">)</span>
</span><span class='line'>
</span><span class='line'><span class="c1">// Now returns the current local time.</span>
</span><span class='line'><span class="kd">func</span> <span class="nx">Now</span><span class="p">()</span> <span class="nx">Time</span> <span class="p">{</span>
</span><span class='line'>    <span class="nx">sec</span><span class="p">,</span> <span class="nx">nsec</span> <span class="o">:=</span> <span class="nx">now</span><span class="p">()</span>
</span><span class='line'>    <span class="k">return</span> <span class="nx">Time</span><span class="p">{</span><span class="nx">sec</span> <span class="o">+</span> <span class="nx">unixToInternal</span><span class="p">,</span> <span class="nx">nsec</span><span class="p">,</span> <span class="nx">Local</span><span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>The unexported function <code>now</code> is implemented in assembly language and gets the
time as a pair of primitive values. The exported function <code>Now</code> wraps that
result in a struct called <code>Time</code> with some convenience methods on it (not
shown).</p>

<p>So what does it take to get an interpreter to correctly evaluate <code>time.Now</code>?
We&rsquo;ll need at least these pieces:</p>

<ul>
<li>Parse the file into a syntax tree. Go&rsquo;s <code>parser</code> and <code>ast</code> packages are a big
help here.</li>
<li>Transform the struct definition for <code>Time</code> (defined elsewhere in the file) and
its methods into some representation known to the interpreter.</li>
<li>Implement multiple assignment, struct creation, and the other operations used
in <code>Now</code>.</li>
<li>While evaluating line 6, my interpreter should notice that <code>now</code> doesn&rsquo;t have
a Go implementation, and prefer to just call the real <code>time.now</code>. (There are
other possible approaches, but this one seemed reasonable.)</li>
</ul>


<p>To prove that that last bullet point was possible, I wanted to write a quick
dummy program that just called <code>time.now</code> (even if it needed some hacky
mechanism), but this ended up being a <em>lot</em> harder than I was expecting. Most
discussions on the internet basically said &ldquo;don&rsquo;t do that&rdquo;, but I decided that I
wouldn&rsquo;t give up so easily.</p>

<p>A related goal is that I wanted a way to take a string name of a function and
get that function back. It&rsquo;s worth noting that it&rsquo;s totally unclear if I should
expect this problem to be solvable in the first place. In C, there&rsquo;s no way to
do it, in Java it&rsquo;s doable, and in higher-level scripting languages it&rsquo;s
typically pretty easy. Go seems to be somewhere between C and Java in terms of
the reflection capabilities that I expect, so I might be attempting something
that simply can&rsquo;t be done.</p>

<h2>Attempt #1: <code>reflect</code></h2>

<p>Reflection is the answer in Java, so maybe in Go it&rsquo;s the same way? Sure enough,
Go has a great <code>reflect</code> package that works in a lot of cases, and even lets you
read unexported struct fields by name, but it doesn&rsquo;t seem to have any way to
provide access to top-level functions (exported or unexported).</p>

<p>In a language like Python, an expression like <code>time.now</code> would take the <code>time</code>
object and pull off a field called <code>now</code>. So you might hope to do something like
this:</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='go'><span class='line'><span class="nx">reflect</span><span class="p">.</span><span class="nx">ValueOf</span><span class="p">(</span><span class="nx">time</span><span class="p">).</span><span class="nx">MethodByName</span><span class="p">(</span><span class="s">&quot;now&quot;</span><span class="p">).</span><span class="nx">Call</span><span class="p">([]</span><span class="nx">reflect</span><span class="p">.</span><span class="nx">Value</span><span class="p">{})</span>
</span></code></pre></td></tr></table></div></figure>


<p>But alas, in Go, <code>time.now</code> is resolved at compile time, and <code>time</code> isn&rsquo;t its
own object that can be accessed like that. So it seems like <code>reflect</code> doesn&rsquo;t
provide an easy answer here.</p>

<h2>Attempt #2: <code>runtime</code></h2>

<p>While I was exploring, I noticed <code>runtime.FuncForPC</code> as a way to
<a href="http://stackoverflow.com/questions/7052693/how-to-get-the-name-of-a-function-in-go">programmatically get the name of any function</a>:</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='go'><span class='line'><span class="nx">runtime</span><span class="p">.</span><span class="nx">FuncForPC</span><span class="p">(</span><span class="nx">reflect</span><span class="p">.</span><span class="nx">ValueOf</span><span class="p">(</span><span class="nx">f</span><span class="p">).</span><span class="nx">Pointer</span><span class="p">()).</span><span class="nx">Name</span><span class="p">()</span>
</span></code></pre></td></tr></table></div></figure>


<p>I dug into the implementation, and sure enough, the Go <code>runtime</code> package keeps a
table of all functions and their names, provided by the linker. Relevant
snippets from <a href="https://golang.org/src/runtime/symtab.go">symtab.go</a>:</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>
</pre></td><td class='code'><pre><code class='go'><span class='line'><span class="kd">var</span> <span class="nx">firstmoduledata</span> <span class="nx">moduledata</span>  <span class="c1">// linker symbol</span>
</span><span class='line'>
</span><span class='line'><span class="kd">func</span> <span class="nx">findmoduledatap</span><span class="p">(</span><span class="nx">pc</span> <span class="kt">uintptr</span><span class="p">)</span> <span class="o">*</span><span class="nx">moduledata</span> <span class="p">{</span>
</span><span class='line'>    <span class="k">for</span> <span class="nx">datap</span> <span class="o">:=</span> <span class="o">&amp;</span><span class="nx">firstmoduledata</span><span class="p">;</span> <span class="nx">datap</span> <span class="o">!=</span> <span class="kc">nil</span><span class="p">;</span> <span class="nx">datap</span> <span class="p">=</span> <span class="nx">datap</span><span class="p">.</span><span class="nx">next</span> <span class="p">{</span>
</span><span class='line'>        <span class="o">...</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="kd">func</span> <span class="nx">findfunc</span><span class="p">(</span><span class="nx">pc</span> <span class="kt">uintptr</span><span class="p">)</span> <span class="o">*</span><span class="nx">_func</span> <span class="p">{</span>
</span><span class='line'>    <span class="nx">datap</span> <span class="o">:=</span> <span class="nx">findmoduledatap</span><span class="p">(</span><span class="nx">pc</span><span class="p">)</span>
</span><span class='line'>    <span class="o">...</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="kd">func</span> <span class="nx">FuncForPC</span><span class="p">(</span><span class="nx">pc</span> <span class="kt">uintptr</span><span class="p">)</span> <span class="o">*</span><span class="nx">Func</span> <span class="p">{</span>
</span><span class='line'>    <span class="k">return</span> <span class="p">(</span><span class="o">*</span><span class="nx">Func</span><span class="p">)(</span><span class="nx">unsafe</span><span class="p">.</span><span class="nx">Pointer</span><span class="p">(</span><span class="nx">findfunc</span><span class="p">(</span><span class="nx">pc</span><span class="p">)))</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>The <code>moduledata</code> struct isn&rsquo;t particularly friendly, but it looks like if I
could access it, then I should, theoretically, be able to loop through it to
find a pointer to a function with name <code>"time.now"</code>. With a function pointer, it
should hopefully be possible to find a way to call it.</p>

<p>Unfortunately, we&rsquo;re at the same place we started. I can&rsquo;t access
<code>firstmoduledata</code>, <code>findmoduledatap</code>, or <code>findfunc</code> for the same reason that I
can&rsquo;t access <code>time.now</code>. I looked through the package to find some place where
maybe it leaks a useful pointer, but I couldn&rsquo;t find anything. Drat.</p>

<p>If I was desperate, I might attempt to guess function pointers and call
<code>FuncForPC</code> until I find one with that right name. But that seemed like a recipe
for disaster, so I decided to look at other approaches.</p>

<h2>Attempt #3: jump down to assembly language</h2>

<p>An escape hatch that should definitely work is to just write my code in assembly
language. It should be possible to make an assembly function that calls
<code>time.now</code> then connect that function to a Go function. I cloned the Go source
code and took a look at the
<a href="https://golang.org/src/runtime/sys_darwin_amd64.s">Darwin AMD64 implementation</a>
of <code>time.now</code> itself to see what it was like:</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='c-objdump'><span class='line'><span class="c1">// func now() (sec int64, nsec int32)</span>
</span><span class='line'><span class="n">TEXT</span> <span class="n">time</span><span class="err">·</span><span class="n">now</span><span class="p">(</span><span class="n">SB</span><span class="p">),</span><span class="n">NOSPLIT</span><span class="p">,</span><span class="err">$</span><span class="mi">0</span><span class="o">-</span><span class="mi">12</span>
</span><span class='line'>    <span class="n">CALL</span>    <span class="n">nanotime</span><span class="o">&lt;&gt;</span><span class="p">(</span><span class="n">SB</span><span class="p">)</span>
</span><span class='line'>
</span><span class='line'>    <span class="c1">// generated code for</span>
</span><span class='line'>    <span class="c1">//    func f(x uint64) (uint64, uint64) { return x/1000000000, x%100000000 }</span>
</span><span class='line'>    <span class="c1">// adapted to reduce duplication</span>
</span><span class='line'>    <span class="n">MOVQ</span>    <span class="n">AX</span><span class="p">,</span> <span class="n">CX</span>
</span><span class='line'>    <span class="n">MOVQ</span>    <span class="err">$</span><span class="mi">1360296554856532783</span><span class="p">,</span> <span class="n">AX</span>
</span><span class='line'>    <span class="n">MULQ</span>    <span class="n">CX</span>
</span><span class='line'>    <span class="n">ADDQ</span>    <span class="n">CX</span><span class="p">,</span> <span class="n">DX</span>
</span><span class='line'>    <span class="n">RCRQ</span>    <span class="err">$</span><span class="mi">1</span><span class="p">,</span> <span class="n">DX</span>
</span><span class='line'>    <span class="n">SHRQ</span>    <span class="err">$</span><span class="mi">29</span><span class="p">,</span> <span class="n">DX</span>
</span><span class='line'>    <span class="n">MOVQ</span>    <span class="n">DX</span><span class="p">,</span> <span class="n">sec</span><span class="o">+</span><span class="mi">0</span><span class="p">(</span><span class="n">FP</span><span class="p">)</span>
</span><span class='line'>    <span class="n">IMULQ</span>   <span class="err">$</span><span class="mi">1000000000</span><span class="p">,</span> <span class="n">DX</span>
</span><span class='line'>    <span class="n">SUBQ</span>    <span class="n">DX</span><span class="p">,</span> <span class="n">CX</span>
</span><span class='line'>    <span class="n">MOVL</span>    <span class="n">CX</span><span class="p">,</span> <span class="n">nsec</span><span class="o">+</span><span class="mi">8</span><span class="p">(</span><span class="n">FP</span><span class="p">)</span>
</span><span class='line'>    <span class="n">RET</span>
</span></code></pre></td></tr></table></div></figure>


<p>Ugh. Maybe I shouldn&rsquo;t be scared off by assembly, but learning the calling
conventions and writing a separate wrapper for every function I wanted to call
for every architecture didn&rsquo;t seem pleasant. I decided to defer that idea and
look at other options. Having a solution in pure Go would certainly be ideal.</p>

<h2>Attempt #4: CGo</h2>

<p>Another escape hatch that seemed promising is
<a href="http://blog.golang.org/c-go-cgo">CGo</a>, which is Go&rsquo;s mechanism for directly
calling C functions from Go code. Here&rsquo;s a first attempt:</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='go'><span class='line'><span class="cm">/*</span>
</span><span class='line'><span class="cm">int time·now();</span>
</span><span class='line'><span class="cm">int time_now_wrapper() {</span>
</span><span class='line'><span class="cm">    return time·now();</span>
</span><span class='line'><span class="cm">}</span>
</span><span class='line'><span class="cm">*/</span>
</span><span class='line'><span class="kn">import</span> <span class="s">&quot;C&quot;</span>
</span><span class='line'>
</span><span class='line'><span class="kd">func</span> <span class="nx">callTimeNow</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'>    <span class="nx">C</span><span class="p">.</span><span class="nx">time_now_wrapper</span><span class="p">()</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>And here&rsquo;s the error that it gives:</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=''><span class='line'>Undefined symbols for architecture x86_64:
</span><span class='line'>  "_time·now", referenced from:
</span><span class='line'>      _time_now_wrapper in foo.cgo2.o
</span><span class='line'>      __cgo_b552a62968a6_Cfunc_time_now_wrapper in foo.cgo2.o
</span><span class='line'>ld: symbol(s) not found for architecture x86_64
</span><span class='line'>clang: error: linker command failed with exit code 1 (use -v to see invocation)</span></code></pre></td></tr></table></div></figure>


<p>Hmm, it seems to be putting an underscore before every function name, which
isn&rsquo;t really what I want. Maybe there&rsquo;s a way around that, but dealing with
multiple return values in <code>time·now</code> seemed like it may be another barrier, and
from my reading, CGo calls have a lot of overhead because it&rsquo;s doing a lot of
translation work so that you can integrate with existing C code. In Java speak,
it seems like it&rsquo;s JNA, not JNI. So while CGo seems useful, it looks like it&rsquo;s
not really the solution to my problem.</p>

<h2>Attempt #5: <code>go:linkname</code></h2>

<p>As I was digging through the standard library source code I saw something
interesting in the <code>runtime</code> package in
<a href="https://golang.org/src/runtime/stubs.go">stubs.go</a>:</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='go'><span class='line'><span class="c1">//go:linkname time_now time.now</span>
</span><span class='line'><span class="kd">func</span> <span class="nx">time_now</span><span class="p">()</span> <span class="p">(</span><span class="nx">sec</span> <span class="kt">int64</span><span class="p">,</span> <span class="nx">nsec</span> <span class="kt">int32</span><span class="p">)</span>
</span></code></pre></td></tr></table></div></figure>


<p>Interesting! I had seen semantically-meaningful comments like this before (like
with the CGo example, and also in other places), but I hadn&rsquo;t seen this one. It
looks like it&rsquo;s saying &ldquo;linker, please use <code>time.now</code> as the implementation of
<code>runtime.time_now</code>&rdquo;. Sure enough, the
<a href="https://golang.org/cmd/compile/#hdr-Compiler_Directives">documentation</a>
suggests that this works, as long as your file imports <code>unsafe</code>. So I tried it
out:</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>
</pre></td><td class='code'><pre><code class='go'><span class='line'><span class="kn">package</span> <span class="nx">main</span>
</span><span class='line'>
</span><span class='line'><span class="kn">import</span> <span class="p">(</span>
</span><span class='line'>    <span class="s">&quot;fmt&quot;</span>
</span><span class='line'>    <span class="nx">_</span> <span class="s">&quot;unsafe&quot;</span>
</span><span class='line'><span class="p">)</span>
</span><span class='line'>
</span><span class='line'><span class="c1">//go:linkname time_now time.now</span>
</span><span class='line'><span class="kd">func</span> <span class="nx">time_now</span><span class="p">()</span> <span class="p">(</span><span class="nx">sec</span> <span class="kt">int64</span><span class="p">,</span> <span class="nx">nsec</span> <span class="kt">int32</span><span class="p">)</span>
</span><span class='line'>
</span><span class='line'><span class="kd">func</span> <span class="nx">main</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'>    <span class="nx">sec</span><span class="p">,</span> <span class="nx">nsec</span> <span class="o">:=</span> <span class="nx">time_now</span><span class="p">()</span>
</span><span class='line'>    <span class="nx">fmt</span><span class="p">.</span><span class="nx">Println</span><span class="p">(</span><span class="nx">sec</span><span class="p">,</span> <span class="nx">nsec</span><span class="p">)</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>Let&rsquo;s see what happens:</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=''><span class='line'># command-line-arguments
</span><span class='line'>./sandbox.go:9: missing function body for "time_now"</span></code></pre></td></tr></table></div></figure>


<p>Drat. Isn&rsquo;t the missing function body the <em>whole point</em> of the bodyless syntax
to allow for externally-implemented functions? The
<a href="https://golang.org/ref/spec#Function_declarations">spec</a> certainly seems to
think that it&rsquo;s valid.</p>

<p>Just to see what would happen, I replaced the empty function body with a dummy
implementation:</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>
</pre></td><td class='code'><pre><code class='go'><span class='line'><span class="c1">//go:linkname time_now time.now</span>
</span><span class='line'><span class="kd">func</span> <span class="nx">time_now</span><span class="p">()</span> <span class="p">(</span><span class="nx">sec</span> <span class="kt">int64</span><span class="p">,</span> <span class="nx">nsec</span> <span class="kt">int32</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>    <span class="k">return</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>Then I tried again and got this error:</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=''><span class='line'># command-line-arguments
</span><span class='line'>2016/03/16 22:50:31 duplicate symbol time.now (types 1 and 1) in main and /usr/local/Cellar/go/1.6/libexec/pkg/darwin_amd64/runtime.a(sys_darwin_amd64)</span></code></pre></td></tr></table></div></figure>


<p>When I don&rsquo;t implement the function, it complains that there&rsquo;s no
implementation, but when I do implement it, it complains that the function is
implemented twice! How frustrating!</p>

<h2>Getting <code>go:linkname</code> to work</h2>

<p>For a while, it seemed like the <code>go:linkname</code> approach wasn&rsquo;t going to work out,
but then I noticed something suspicious: the error formatting is different. It
looks like the &ldquo;missing function body&rdquo; error is from the compiler, but the
&ldquo;duplicate symbol&rdquo; error is from the linker. Why would the compiler care about a
function body being missing, if it&rsquo;s the linker&rsquo;s job to make sure every symbol
gets an implementation?</p>

<p>I decided to dig into the code for the compiler to see why it might be
generating this error. Here&rsquo;s what I found in
<a href="https://golang.org/src/cmd/compile/internal/gc/pgen.go">pgen.go</a>:</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>
</pre></td><td class='code'><pre><code class='go'><span class='line'><span class="kd">func</span> <span class="nx">compile</span><span class="p">(</span><span class="nx">fn</span> <span class="o">*</span><span class="nx">Node</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>    <span class="o">...</span>
</span><span class='line'>    <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="nx">fn</span><span class="p">.</span><span class="nx">Nbody</span><span class="p">.</span><span class="nx">Slice</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">if</span> <span class="nx">pure_go</span> <span class="o">!=</span> <span class="mi">0</span> <span class="o">||</span> <span class="nx">strings</span><span class="p">.</span><span class="nx">HasPrefix</span><span class="p">(</span><span class="nx">fn</span><span class="p">.</span><span class="nx">Func</span><span class="p">.</span><span class="nx">Nname</span><span class="p">.</span><span class="nx">Sym</span><span class="p">.</span><span class="nx">Name</span><span class="p">,</span> <span class="s">&quot;init.&quot;</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>            <span class="nx">Yyerror</span><span class="p">(</span><span class="s">&quot;missing function body for %q&quot;</span><span class="p">,</span> <span class="nx">fn</span><span class="p">.</span><span class="nx">Func</span><span class="p">.</span><span class="nx">Nname</span><span class="p">.</span><span class="nx">Sym</span><span class="p">.</span><span class="nx">Name</span><span class="p">)</span>
</span><span class='line'>            <span class="k">return</span>
</span><span class='line'>        <span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>Something is causing that inner <code>if</code> statement to evaluate to <code>true</code>, and my
function doesn&rsquo;t have to do with <code>init</code>, so it looks like <code>pure_go</code> is nonzero
when it should be zero. Searching for <code>pure_go</code> shows this compiler flag:</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='go'><span class='line'><span class="nx">obj</span><span class="p">.</span><span class="nx">Flagcount</span><span class="p">(</span><span class="s">&quot;complete&quot;</span><span class="p">,</span> <span class="s">&quot;compiling complete package (no C or assembly)&quot;</span><span class="p">,</span> <span class="o">&amp;</span><span class="nx">pure_go</span><span class="p">)</span>
</span></code></pre></td></tr></table></div></figure>


<p>Makes sense: if your code doesn&rsquo;t have any way of defining external functions,
then it&rsquo;s friendlier to give an error at compile time with the location of the
problem. But it looks like <code>go:linkname</code> was overlooked somewhere in the
process. It certainly is a bit of an edge case.</p>

<p>After some searching, I found the culprit in
<a href="https://golang.org/src/cmd/go/build.go">build.go</a>:</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>
</pre></td><td class='code'><pre><code class='go'><span class='line'><span class="nx">extFiles</span> <span class="o">:=</span> <span class="nb">len</span><span class="p">(</span><span class="nx">p</span><span class="p">.</span><span class="nx">CgoFiles</span><span class="p">)</span> <span class="o">+</span> <span class="nb">len</span><span class="p">(</span><span class="nx">p</span><span class="p">.</span><span class="nx">CFiles</span><span class="p">)</span> <span class="o">+</span> <span class="nb">len</span><span class="p">(</span><span class="nx">p</span><span class="p">.</span><span class="nx">CXXFiles</span><span class="p">)</span> <span class="o">+</span> <span class="nb">len</span><span class="p">(</span><span class="nx">p</span><span class="p">.</span><span class="nx">MFiles</span><span class="p">)</span> <span class="o">+</span> <span class="nb">len</span><span class="p">(</span><span class="nx">p</span><span class="p">.</span><span class="nx">FFiles</span><span class="p">)</span> <span class="o">+</span> <span class="nb">len</span><span class="p">(</span><span class="nx">p</span><span class="p">.</span><span class="nx">SFiles</span><span class="p">)</span> <span class="o">+</span> <span class="nb">len</span><span class="p">(</span><span class="nx">p</span><span class="p">.</span><span class="nx">SysoFiles</span><span class="p">)</span> <span class="o">+</span> <span class="nb">len</span><span class="p">(</span><span class="nx">p</span><span class="p">.</span><span class="nx">SwigFiles</span><span class="p">)</span> <span class="o">+</span> <span class="nb">len</span><span class="p">(</span><span class="nx">p</span><span class="p">.</span><span class="nx">SwigCXXFiles</span><span class="p">)</span>
</span><span class='line'><span class="o">...</span>
</span><span class='line'><span class="k">if</span> <span class="nx">extFiles</span> <span class="o">==</span> <span class="mi">0</span> <span class="p">{</span>
</span><span class='line'>    <span class="nx">gcargs</span> <span class="p">=</span> <span class="nb">append</span><span class="p">(</span><span class="nx">gcargs</span><span class="p">,</span> <span class="s">&quot;-complete&quot;</span><span class="p">)</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>So it&rsquo;s just counting the number of non-Go files of each type. Since I&rsquo;m only
compiling with Go files, it assumes that every function needs a body. But on the
plus side, the code suggests a workaround: just add a file of any of those
types. I already know how to use CGo, so let&rsquo;s try 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>
</pre></td><td class='code'><pre><code class='go'><span class='line'><span class="kn">package</span> <span class="nx">main</span>
</span><span class='line'>
</span><span class='line'><span class="kn">import</span> <span class="p">(</span>
</span><span class='line'>    <span class="s">&quot;C&quot;</span>
</span><span class='line'>    <span class="s">&quot;fmt&quot;</span>
</span><span class='line'>    <span class="nx">_</span> <span class="s">&quot;unsafe&quot;</span>
</span><span class='line'><span class="p">)</span>
</span><span class='line'>
</span><span class='line'><span class="c1">//go:linkname time_now time.now</span>
</span><span class='line'><span class="kd">func</span> <span class="nx">time_now</span><span class="p">()</span> <span class="p">(</span><span class="nx">sec</span> <span class="kt">int64</span><span class="p">,</span> <span class="nx">nsec</span> <span class="kt">int32</span><span class="p">)</span>
</span><span class='line'>
</span><span class='line'><span class="kd">func</span> <span class="nx">main</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'>    <span class="nx">sec</span><span class="p">,</span> <span class="nx">nsec</span> <span class="o">:=</span> <span class="nx">time_now</span><span class="p">()</span>
</span><span class='line'>    <span class="nx">fmt</span><span class="p">.</span><span class="nx">Println</span><span class="p">(</span><span class="nx">sec</span><span class="p">,</span> <span class="nx">nsec</span><span class="p">)</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>And here&rsquo;s what happens when you try to build 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>
</pre></td><td class='code'><pre><code class=''><span class='line'>main.main: call to external function main.time_now
</span><span class='line'>main.main: main.time_now: not defined
</span><span class='line'>main.main: undefined: main.time_now</span></code></pre></td></tr></table></div></figure>


<p>A different error! Now the linker is complaining that the function doesn&rsquo;t
exist. After some experimentation, I discovered that CGo seems to cause
<code>go:linkname</code> to be disabled for that file. If I remove the import of <code>"C"</code> and
move it to another file, then compile the two together, then I get this output:</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=''><span class='line'>1458197809 407398202</span></code></pre></td></tr></table></div></figure>


<p>It worked! If your only goal is to get access to <code>time.now</code>, then this is good
enough, but I&rsquo;m hoping that I can go a bit further.</p>

<h2>Looking up functions by name</h2>

<p>Now that I know that <code>go:linkname</code> works, I can use it to access the
<code>firstmoduledata</code> structure mentioned in attempt #2, which is a table containing
information on all compiled functions in the binary. My hope is that I can use
it to write a function that takes a function name as a string, like
<code>"time.now"</code>, and provides that function.</p>

<p>One problem is that <code>runtime.firstmoduledata</code> has type <code>runtime.moduledata</code>,
which is an unexported type, so I can&rsquo;t use it in my code. But as a total hack,
I <em>can</em> just copy the struct to my code (or, at least, enough of it to keep the
alignment correct) and pretend that my struct is the real thing. From there, I
can pretty much copy the code from the <code>runtime</code> package to do a full scan
through the list of functions until I find the right one:</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='go'><span class='line'><span class="kd">func</span> <span class="nx">FindFuncWithName</span><span class="p">(</span><span class="nx">name</span> <span class="kt">string</span><span class="p">)</span> <span class="p">(</span><span class="kt">uintptr</span><span class="p">,</span> <span class="kt">error</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>    <span class="k">for</span> <span class="nx">moduleData</span> <span class="o">:=</span> <span class="o">&amp;</span><span class="nx">Firstmoduledata</span><span class="p">;</span> <span class="nx">moduleData</span> <span class="o">!=</span> <span class="kc">nil</span><span class="p">;</span> <span class="nx">moduleData</span> <span class="p">=</span> <span class="nx">moduleData</span><span class="p">.</span><span class="nx">next</span> <span class="p">{</span>
</span><span class='line'>        <span class="k">for</span> <span class="nx">_</span><span class="p">,</span> <span class="nx">ftab</span> <span class="o">:=</span> <span class="k">range</span> <span class="nx">moduleData</span><span class="p">.</span><span class="nx">ftab</span> <span class="p">{</span>
</span><span class='line'>            <span class="nx">f</span> <span class="o">:=</span> <span class="p">(</span><span class="o">*</span><span class="nx">runtime</span><span class="p">.</span><span class="nx">Func</span><span class="p">)(</span><span class="nx">unsafe</span><span class="p">.</span><span class="nx">Pointer</span><span class="p">(</span><span class="o">&amp;</span><span class="nx">moduleData</span><span class="p">.</span><span class="nx">pclntable</span><span class="p">[</span><span class="nx">ftab</span><span class="p">.</span><span class="nx">funcoff</span><span class="p">]))</span>
</span><span class='line'>            <span class="k">if</span> <span class="nx">f</span><span class="p">.</span><span class="nx">Name</span><span class="p">()</span> <span class="o">==</span> <span class="nx">name</span> <span class="p">{</span>
</span><span class='line'>                <span class="k">return</span> <span class="nx">f</span><span class="p">.</span><span class="nx">Entry</span><span class="p">(),</span> <span class="kc">nil</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 class="k">return</span> <span class="mi">0</span><span class="p">,</span> <span class="nx">fmt</span><span class="p">.</span><span class="nx">Errorf</span><span class="p">(</span><span class="s">&quot;Invalid function name: %s&quot;</span><span class="p">,</span> <span class="nx">name</span><span class="p">)</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>This seems to work! This 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>
</pre></td><td class='code'><pre><code class='go'><span class='line'><span class="nx">ptr</span><span class="p">,</span> <span class="nx">_</span> <span class="o">:=</span> <span class="nx">FindFuncWithName</span><span class="p">(</span><span class="s">&quot;math.Sqrt&quot;</span><span class="p">)</span>
</span><span class='line'><span class="nx">fmt</span><span class="p">.</span><span class="nx">Printf</span><span class="p">(</span><span class="s">&quot;Found pointer 0x%x\nNormal function: %s&quot;</span><span class="p">,</span> <span class="nx">ptr</span><span class="p">,</span> <span class="nx">math</span><span class="p">.</span><span class="nx">Sqrt</span><span class="p">)</span>
</span></code></pre></td></tr></table></div></figure>


<p>prints this:</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=''><span class='line'>Found pointer 0x104250
</span><span class='line'>Normal function: %!s(func(float64) float64=0x104250)</span></code></pre></td></tr></table></div></figure>


<p>So the underlying code pointer is correct! Now we just need to figure out how to
use it&hellip;</p>

<h2>Calling a function by pointer</h2>

<p>You would think that having a function pointer would be the end of the story.
In C you could just cast the pointer value to the right function type, then call
it. But Go isn&rsquo;t quite so generous. For one, Go normally doesn&rsquo;t just let you
cast between types like that, but <code>unsafe.Pointer</code> can be used to circumvent
some safety checks. You might try just casting it to a function of the proper
type:</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='go'><span class='line'><span class="nx">ptr</span><span class="p">,</span> <span class="nx">_</span> <span class="o">:=</span> <span class="nx">FindFuncWithName</span><span class="p">(</span><span class="s">&quot;time.now&quot;</span><span class="p">)</span>
</span><span class='line'><span class="nx">timeNow</span> <span class="o">:=</span> <span class="p">(</span><span class="kd">func</span><span class="p">()</span> <span class="p">(</span><span class="kt">int64</span><span class="p">,</span> <span class="kt">int32</span><span class="p">))(</span><span class="nx">unsafe</span><span class="p">.</span><span class="nx">Pointer</span><span class="p">(</span><span class="nx">ptr</span><span class="p">))</span>
</span><span class='line'><span class="nx">sec</span><span class="p">,</span> <span class="nx">msec</span> <span class="o">:=</span> <span class="nx">timeNow</span><span class="p">()</span>
</span></code></pre></td></tr></table></div></figure>


<p>But that type of cast doesn&rsquo;t compile; pointers can&rsquo;t be cast to functions, not
even using <code>unsafe.Pointer</code>. What if we literally cast it to a pointer to a
<code>func</code> type?</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='go'><span class='line'><span class="nx">ptr</span><span class="p">,</span> <span class="nx">_</span> <span class="o">:=</span> <span class="nx">FindFuncWithName</span><span class="p">(</span><span class="s">&quot;time.now&quot;</span><span class="p">)</span>
</span><span class='line'><span class="nx">timeNow</span> <span class="o">:=</span> <span class="p">(</span><span class="o">*</span><span class="kd">func</span><span class="p">()</span> <span class="p">(</span><span class="kt">int64</span><span class="p">,</span> <span class="kt">int32</span><span class="p">))(</span><span class="nx">unsafe</span><span class="p">.</span><span class="nx">Pointer</span><span class="p">(</span><span class="nx">ptr</span><span class="p">))</span>
</span><span class='line'><span class="nx">sec</span><span class="p">,</span> <span class="nx">msec</span> <span class="o">:=</span> <span class="p">(</span><span class="o">*</span><span class="nx">timeNow</span><span class="p">)()</span>
</span></code></pre></td></tr></table></div></figure>


<p>This compiles, but crashes at runtime:</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=''><span class='line'>unexpected fault address 0xb01dfacedebac1e
</span><span class='line'>fatal error: fault
</span><span class='line'>[signal 0xb code=0x1 addr=0xb01dfacedebac1e pc=0x7e450]</span></code></pre></td></tr></table></div></figure>


<p>(Look at that fault address. Apparently someone
<a href="https://golang.org/src/runtime/signal_amd64x.go">had a sense of humor</a>.)</p>

<p>This isn&rsquo;t a surprising outcome; functions in Go are first-class values, so
their implementation is naturally more interesting than in C. When you pass
around a <code>func</code>, you&rsquo;re not just passing around a code pointer, you&rsquo;re passing
around a <em>function value</em> of some sort, and we&rsquo;ll need to come up with a
function value somehow if we&rsquo;re to have any hope of calling our function. That
function value needs to have our pointer as its underlying code pointer.</p>

<p>I didn&rsquo;t see any obvious ways to create a function value from scratch, so I
figured I&rsquo;d take a different approach: take an existing function value and hack
the code pointer to be the one I want. After spending some time reading
<a href="http://research.swtch.com/interfaces">how interfaces work</a> in Go and reading
the implementation of the <a href="https://golang.org/src/reflect/value.go">reflect</a>
library, an approach that seemed promising was to treat the function as an
<code>interface{}</code> (that&rsquo;s Go&rsquo;s equivalent of <code>Object</code> or <code>void*</code> or <code>any</code>: a type
that includes every other type), which internally stores it as a (type, pointer)
pair. Then I could pull the pointer off and work with it reliably. The <code>reflect</code>
source code suggests that the <em>code pointer</em> (the pointer to the actual machine
code) is the first value in a function object.</p>

<p>So, as a first attempt, I created a dummy function called <code>timeNow</code> then defined
some structs to make it easy to swap out its code pointer with the real
<code>time.now</code> code pointer:</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>
</pre></td><td class='code'><pre><code class='go'><span class='line'><span class="kd">func</span> <span class="nx">timeNow</span><span class="p">()</span> <span class="p">(</span><span class="kt">int64</span><span class="p">,</span> <span class="kt">int32</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>    <span class="k">return</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="kd">type</span> <span class="nx">Interface</span> <span class="kd">struct</span> <span class="p">{</span>
</span><span class='line'>    <span class="nx">typ</span>     <span class="nx">unsafe</span><span class="p">.</span><span class="nx">Pointer</span>
</span><span class='line'>    <span class="nx">funcPtr</span> <span class="o">*</span><span class="nx">Func</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="kd">type</span> <span class="nx">Func</span> <span class="kd">struct</span> <span class="p">{</span>
</span><span class='line'>    <span class="nx">codePtr</span> <span class="kt">uintptr</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="kd">func</span> <span class="nx">main</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'>    <span class="nx">timeNowCodePtr</span><span class="p">,</span> <span class="nx">_</span> <span class="o">:=</span> <span class="nx">FindFuncWithName</span><span class="p">(</span><span class="s">&quot;time.now&quot;</span><span class="p">)</span>
</span><span class='line'>    <span class="kd">var</span> <span class="nx">timeNowInterface</span> <span class="kd">interface</span><span class="p">{}</span> <span class="p">=</span> <span class="nx">timeNow</span>
</span><span class='line'>    <span class="nx">timeNowInterfacePtr</span> <span class="o">:=</span> <span class="p">(</span><span class="o">*</span><span class="nx">Interface</span><span class="p">)(</span><span class="nx">unsafe</span><span class="p">.</span><span class="nx">Pointer</span><span class="p">(</span><span class="o">&amp;</span><span class="nx">timeNowInterface</span><span class="p">))</span>
</span><span class='line'>    <span class="nx">timeNowInterfacePtr</span><span class="p">.</span><span class="nx">funcPtr</span><span class="p">.</span><span class="nx">codePtr</span> <span class="p">=</span> <span class="nx">timeNowCodePtr</span>
</span><span class='line'>    <span class="nx">sec</span><span class="p">,</span> <span class="nx">msec</span> <span class="o">:=</span> <span class="nx">timeNow</span><span class="p">()</span>
</span><span class='line'>    <span class="nx">fmt</span><span class="p">.</span><span class="nx">Println</span><span class="p">(</span><span class="nx">sec</span><span class="p">,</span> <span class="nx">msec</span><span class="p">)</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>And, as you might guess, it crashed:</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=''><span class='line'>unexpected fault address 0x129e80
</span><span class='line'>fatal error: fault
</span><span class='line'>[signal 0xa code=0x2 addr=0x129e80 pc=0x20be]</span></code></pre></td></tr></table></div></figure>


<p>After some experimenting, I discovered that the crash was happening <em>even
without calling the function</em>. The crash was from the line
<code>timeNowInterfacePtr.funcPtr.codePtr = timeNowCodePtr</code>. After double-checking
that the pointers were what I expect, I realized the problem: the function
object I was modifying was probably in the code segment, in read-only memory.
Just like how the machine code isn&rsquo;t going to change, Go expects that the
<code>timeNow</code> function value isn&rsquo;t going to change at runtime. What I really needed
to do was <em>allocate</em> a function object on the heap so that I could safely change
its underlying code pointer.</p>

<p>So how do you dynamically allocate a function in Go? That&rsquo;s what lambdas are
for, right? Let&rsquo;s try using one! Instead of the top-level <code>timeNow</code>, we can
write our <code>main</code> function like this (the only difference is the new definition
of <code>timeNow</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>
</pre></td><td class='code'><pre><code class='go'><span class='line'><span class="kd">func</span> <span class="nx">main</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'>    <span class="nx">timeNowCodePtr</span><span class="p">,</span> <span class="nx">_</span> <span class="o">:=</span> <span class="nx">FindFuncWithName</span><span class="p">(</span><span class="s">&quot;time.now&quot;</span><span class="p">)</span>
</span><span class='line'>    <span class="nx">timeNow</span> <span class="o">:=</span> <span class="kd">func</span><span class="p">()</span> <span class="p">(</span><span class="kt">int64</span><span class="p">,</span> <span class="kt">int32</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span> <span class="p">}</span>
</span><span class='line'>    <span class="kd">var</span> <span class="nx">timeNowInterface</span> <span class="kd">interface</span><span class="p">{}</span> <span class="p">=</span> <span class="nx">timeNow</span>
</span><span class='line'>    <span class="nx">timeNowInterfacePtr</span> <span class="o">:=</span> <span class="p">(</span><span class="o">*</span><span class="nx">Interface</span><span class="p">)(</span><span class="nx">unsafe</span><span class="p">.</span><span class="nx">Pointer</span><span class="p">(</span><span class="o">&amp;</span><span class="nx">timeNowInterface</span><span class="p">))</span>
</span><span class='line'>    <span class="nx">timeNowInterfacePtr</span><span class="p">.</span><span class="nx">funcPtr</span><span class="p">.</span><span class="nx">codePtr</span> <span class="p">=</span> <span class="nx">timeNowCodePtr</span>
</span><span class='line'>    <span class="nx">sec</span><span class="p">,</span> <span class="nx">msec</span> <span class="o">:=</span> <span class="nx">timeNow</span><span class="p">()</span>
</span><span class='line'>    <span class="nx">fmt</span><span class="p">.</span><span class="nx">Println</span><span class="p">(</span><span class="nx">sec</span><span class="p">,</span> <span class="nx">msec</span><span class="p">)</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>And, again, it crashes. I&rsquo;ve seen how lambdas work in other languages, so I
suspected why: when a lambda takes in no outside variables, there&rsquo;s no need to
do an allocation each time, so a common optimization is to just have a single
shared instance for simple lambdas like the one I wrote, so probably I&rsquo;m again
trying to write to the code segment. To work around this, we can trick the
compiler into allocating a new function object each time by making the function
a real closure and pulling in a variable from the outer scope (even a trivial
one):</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='go'><span class='line'><span class="kd">func</span> <span class="nx">main</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'>    <span class="nx">timeNowCodePtr</span><span class="p">,</span> <span class="nx">_</span> <span class="o">:=</span> <span class="nx">FindFuncWithName</span><span class="p">(</span><span class="s">&quot;time.now&quot;</span><span class="p">)</span>
</span><span class='line'>    <span class="kd">var</span> <span class="nx">x</span> <span class="kt">int64</span> <span class="p">=</span> <span class="mi">0</span>
</span><span class='line'>    <span class="nx">timeNow</span> <span class="o">:=</span> <span class="kd">func</span><span class="p">()</span> <span class="p">(</span><span class="kt">int64</span><span class="p">,</span> <span class="kt">int32</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="nx">x</span><span class="p">,</span> <span class="mi">0</span> <span class="p">}</span>
</span><span class='line'>    <span class="kd">var</span> <span class="nx">timeNowInterface</span> <span class="kd">interface</span><span class="p">{}</span> <span class="p">=</span> <span class="nx">timeNow</span>
</span><span class='line'>    <span class="nx">timeNowInterfacePtr</span> <span class="o">:=</span> <span class="p">(</span><span class="o">*</span><span class="nx">Interface</span><span class="p">)(</span><span class="nx">unsafe</span><span class="p">.</span><span class="nx">Pointer</span><span class="p">(</span><span class="o">&amp;</span><span class="nx">timeNowInterface</span><span class="p">))</span>
</span><span class='line'>    <span class="nx">timeNowInterfacePtr</span><span class="p">.</span><span class="nx">funcPtr</span><span class="p">.</span><span class="nx">codePtr</span> <span class="p">=</span> <span class="nx">timeNowCodePtr</span>
</span><span class='line'>    <span class="nx">sec</span><span class="p">,</span> <span class="nx">msec</span> <span class="o">:=</span> <span class="nx">timeNow</span><span class="p">()</span>
</span><span class='line'>    <span class="nx">fmt</span><span class="p">.</span><span class="nx">Println</span><span class="p">(</span><span class="nx">sec</span><span class="p">,</span> <span class="nx">msec</span><span class="p">)</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>And it works!</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=''><span class='line'>1458245880 151691912</span></code></pre></td></tr></table></div></figure>


<h2>Turning it into a library</h2>

<p>This code is almost useful, but wouldn&rsquo;t really work as a library yet because it
would require the function&rsquo;s type to be hard-coded into the library. We could
have the library caller pass in a function that will be modified, but that has
gotchas like the read-only memory problem I ran into above.</p>

<p>Instead, I looked around at possible API approaches, and I got some nice
inspiration from the example code for
<a href="https://golang.org/pkg/reflect/#MakeFunc">reflect.MakeFunc</a>.</p>

<p>We&rsquo;ll try writing a <code>GetFunc</code> function that can be used like this:</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='go'><span class='line'><span class="kd">var</span> <span class="nx">timeNow</span> <span class="kd">func</span><span class="p">()</span> <span class="p">(</span><span class="kt">int64</span><span class="p">,</span> <span class="kt">int32</span><span class="p">)</span>
</span><span class='line'><span class="nx">GetFunc</span><span class="p">(</span><span class="o">&amp;</span><span class="nx">timeNow</span><span class="p">,</span> <span class="s">&quot;time.now&quot;</span><span class="p">)</span>
</span><span class='line'><span class="nx">sec</span><span class="p">,</span> <span class="nx">msec</span> <span class="o">:=</span> <span class="nx">timeNow</span><span class="p">()</span>
</span></code></pre></td></tr></table></div></figure>


<p>But how can <code>GetFunc</code> allocate a function value? Above, we used a lambda
expression, but that doesn&rsquo;t work if the type isn&rsquo;t known until runtime.</p>

<p>Reflection to the rescue! We can call <code>reflect.MakeFunc</code> to create a function
value with a particular type. In this case, we don&rsquo;t really care what the
implementation is because we&rsquo;re going to be modifying its code pointer anyway.
We end up with a <code>reflect.Value</code> object with a memory layout like this:</p>

<p><img src="http://www.alangpierce.com/images/function_pointer_diagram.png" alt="Function pointer layout" /></p>

<p>The <code>ptr</code> field in the <code>reflect.Value</code> definition is unexported, but we can <em>use
reflection on the <code>reflect.Value</code></em> to get it, then treat it as a pointer to a
function object, then modify that function object&rsquo;s code pointer to be what we
want. The full code looks like this:</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='go'><span class='line'><span class="kd">type</span> <span class="nx">Func</span> <span class="kd">struct</span> <span class="p">{</span>
</span><span class='line'>    <span class="nx">codePtr</span> <span class="kt">uintptr</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="kd">func</span> <span class="nx">CreateFuncForCodePtr</span><span class="p">(</span><span class="nx">outFuncPtr</span> <span class="kd">interface</span><span class="p">{},</span> <span class="nx">codePtr</span> <span class="kt">uintptr</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>    <span class="c1">// outFuncPtr is a pointer to a function, and outFuncVal acts as *outFuncPtr.</span>
</span><span class='line'>    <span class="nx">outFuncVal</span> <span class="o">:=</span> <span class="nx">reflect</span><span class="p">.</span><span class="nx">ValueOf</span><span class="p">(</span><span class="nx">outFuncPtr</span><span class="p">).</span><span class="nx">Elem</span><span class="p">()</span>
</span><span class='line'>    <span class="nx">newFuncVal</span> <span class="o">:=</span> <span class="nx">reflect</span><span class="p">.</span><span class="nx">MakeFunc</span><span class="p">(</span><span class="nx">outFuncVal</span><span class="p">.</span><span class="nx">Type</span><span class="p">(),</span> <span class="kc">nil</span><span class="p">)</span>
</span><span class='line'>    <span class="nx">funcValuePtr</span> <span class="o">:=</span> <span class="nx">reflect</span><span class="p">.</span><span class="nx">ValueOf</span><span class="p">(</span><span class="nx">newFuncVal</span><span class="p">).</span><span class="nx">FieldByName</span><span class="p">(</span><span class="s">&quot;ptr&quot;</span><span class="p">).</span><span class="nx">Pointer</span><span class="p">()</span>
</span><span class='line'>    <span class="nx">funcPtr</span> <span class="o">:=</span> <span class="p">(</span><span class="o">*</span><span class="nx">Func</span><span class="p">)(</span><span class="nx">unsafe</span><span class="p">.</span><span class="nx">Pointer</span><span class="p">(</span><span class="nx">funcValuePtr</span><span class="p">))</span>
</span><span class='line'>    <span class="nx">funcPtr</span><span class="p">.</span><span class="nx">codePtr</span> <span class="p">=</span> <span class="nx">codePtr</span>
</span><span class='line'>    <span class="nx">outFuncVal</span><span class="p">.</span><span class="nx">Set</span><span class="p">(</span><span class="nx">newFuncVal</span><span class="p">)</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>And that&rsquo;s it! That function modifies its argument to be the function at
<code>codePtr</code>. Implementing the main <code>GetFunc</code> API is just a matter of tying
together <code>FindFuncWithName</code> and <code>CreateFuncForCodePtr</code>; details are in the
<a href="https://github.com/alangpierce/go-forceexport/blob/master/forceexport.go">source code</a>.</p>

<h2>Future steps and lessons learned</h2>

<p>This API still isn&rsquo;t ideal; the library user still needs to know the type in
advance, and if they get it wrong, there will be horrible consequences at
runtime. At the end of the day, the library isn&rsquo;t significantly more useful than
<code>go:linkname</code>, but it has some advantages, and is a good starting point for more
interesting tricks. It&rsquo;s potentially possible, but probably harder, to make a
function that takes a <code>string</code> and returns a <code>reflect.Value</code> of the function,
which would be ideal. But that&rsquo;s out of scope for now. Also, the
<a href="https://github.com/alangpierce/go-forceexport#use-cases-and-pitfalls">README</a>
has a number of other warnings and things to consider. For example, this
approach will sometimes completely break due to function inlining.</p>

<p>Go is certainly in an interesting place in the space of languages. It&rsquo;s dynamic
enough that it&rsquo;s not crazy to look up a function by name, but it&rsquo;s much more
performance-focused than, say, Java. The reflection capabilities are good for a
systems language, but sometimes the better escape hatch is to just use
<code>unsafe.Pointer</code>.</p>

<p>I&rsquo;d be happy to hear any feedback or corrections in the comments below. Like I
mentioned, I&rsquo;m still learning all of this stuff, so I probably overlooked some
things and got some terminology wrong.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[BigBingo: Khan Academy's New BigQuery-backed A/B Testing Framework]]></title>
    <link href="http://www.alangpierce.com/blog/2014/07/07/bigbingo-khan-academys-new-bigquery-backed-a-b-testing-framework/"/>
    <updated>2014-07-07T12:00:00-07:00</updated>
    <id>http://www.alangpierce.com/blog/2014/07/07/bigbingo-khan-academys-new-bigquery-backed-a-b-testing-framework</id>
    <content type="html"><![CDATA[<p>In late January, I joined Khan Academy as the third member of the
infrastructure team. We were just starting a big performance push, so I spent my
first week or two improving our
<a href="https://github.com/kamens/gae_mini_profiler">profiling tools</a> and finding and fixing some easy
slow spots (including speeding up the home page by over a second). However, every time I profiled
any page, I found that the A/B testing framework,
<a href="https://github.com/kamens/gae_bingo">GAE/Bingo</a>, was always one of the
slowest pieces. I had some ideas on how to make some incremental improvements to speed
it up, but instead, I was given a much more ambitious project: to rethink
and rewrite the whole A/B testing system from scratch. I had plenty of
sources of guidance and advice, but I, the new guy, was to be the sole owner and author of the
new system. I was up for the task, but it was nevertheless a bit daunting.</p>

<p>Instead of the old strategy of keeping the A/B test data continuously
up-to-date using memcache (and periodically flushing to the App Engine
datastore), the new system would report events by simply logging
them, and those log statements would eventually make their way into
<a href="https://developers.google.com/bigquery/">Google BigQuery</a> through an hourly
<a href="https://github.com/Khan/appengine-mapreduce">MapReduce</a> job based on
<a href="https://code.google.com/p/log2bq/">log2bq</a>. From there, the real A/B test
processing would be done completely in SQL using BigQuery queries. Since we
were revamping GAE/Bingo using BigQuery, there was an obvious name: BigBingo.</p>

<p>Of course, that three-sentence description leaves out pretty much all of the
details and makes some dangerous assumptions, but the high-level plan ended up
working (with some tweaks), and I&rsquo;m happy to say that all A/B tests at Khan Academy are now
running under BigBingo, and the last remnants of the old GAE/Bingo system are finally
being removed. In this post, I&rsquo;ll talk about why a rewrite was so important, how
we think about A/B testing, and some specific points of the design and
architecture of BigBingo. There are some additional cool details that are probably
deserving of their own blog post, so look out for those in the future.</p>

<h2>BigBingo is fast!</h2>

<p>Most developers at Khan Academy had a sense that the old GAE/Bingo system was slow and BigBingo
would improve overall performance, but I doubt anybody expected that the
improvement would be as dramatic as it was. When I finally flipped the switch to
turn off GAE/Bingo, the average latency across <em>all</em> requests went from a little
over 300ms to a little under 200ms. The most important pages had even better
results, but I&rsquo;ll let the pictures do the talking:</p>

<p>The logged-in homepage got twice as fast:</p>

<p><img src="http://www.alangpierce.com/images/logged_in_homepage.png" alt="Logged-in homepage percentiles" /></p>

<p>The logged-out homepage improved even more:</p>

<p><img src="http://www.alangpierce.com/images/logged_out_homepage.png" alt="Logged-out homepage percentiles" /></p>

<p>And our memcache went from &ldquo;worryingly overloaded&rdquo; to &ldquo;doing great&rdquo;:</p>

<p><img src="http://www.alangpierce.com/images/memcache_usage.png" alt="Memcache compute units" /></p>

<p>Of course, making the site faster makes users happier, but it has another big
benefit: cost savings. If requests can be processed twice as fast, we only need
half as many App Engine instances running at a given time, so our App Engine
bill drops significantly. Since Khan Academy is a nonprofit running off of
donations, it&rsquo;s important to us to have an efficient infrastructure so we can
focus our money on improving education, not upkeep.</p>

<h2>A/B testing at Khan Academy</h2>

<p>A/B testing isn&rsquo;t just some occasional tool at Khan Academy; it&rsquo;s an important
part of our engineering culture, and almost any change that we care about goes
through an A/B test first, often multiple A/B tests. Right now, there are 57
A/B tests actively running, which is an average of about two active A/B tests
per developer.</p>

<p>Unlike &ldquo;traditional&rdquo; A/B testing (which tends to maximize simple metrics like
ad clicks, purchases, etc.), Khan Academy&rsquo;s A/B testing tries to maximize
student <em>learning</em>. That means that we try out much more advanced changes than
just little UI tweaks, and measuring success is a huge challenge by itself.
Here are some examples of A/B tests we do:</p>

<ul>
<li>We have a <a href="http://mattfaus.com/2014/07/khan-academy-mastery-mechanics/">sophisticated system</a>
that tries to understand a student&rsquo;s knowledge level and recommend the best
exercises for them, and we&rsquo;re always making little improvements to it. For
example, we recently tried out a new system to detect when users are below
their learning edge and advance them through the material more quickly.
Learners under the new system progressed further, as expected, and they almost
always stayed at their advanced level rather than being demoted, so we rolled
out the new algorithm to all users.</li>
<li>We&rsquo;ve been experimenting with providing message snippets to teach our users
that learning makes them not just more knowledgeable, but smarter
as well. This specific motivational approach turns out to be surprisingly
effective, and results in increased site usage and learning outcomes, so we&rsquo;re
trying out various different approaches to deliver the message in the most
effective way.</li>
<li>We recently switched the homepage background to one we liked better. It didn&rsquo;t improve any
metrics noticeably, but the A/B test verified that it didn&rsquo;t hurt anything
either, so we kept the new background. We run lots of little experiments like this one.</li>
</ul>


<h2>What&rsquo;s different about BigBingo?</h2>

<p>In the years since GAE/Bingo was written, the devs at KA learned
<a href="http://bjk5.com/post/28269263789/lessons-learned-a-b-testing-with-gae-bingo">a thing or two</a>
about the right way to do A/B testing and what an A/B testing framework should really do, so
BigBingo diverges from GAE/Bingo in a few important ways.</p>

<h3>The data</h3>

<p>Here&rsquo;s what you&rsquo;d see when looking at the latest results of an old GAE/Bingo
experiment (I added a red box to indicate the &ldquo;real&rdquo; data; everything else is derived
from those numbers):</p>

<p><img src="http://www.alangpierce.com/images/gae_bingo.png" alt="GAE/Bingo Dashboard" /></p>

<p>For clear-cut results, a few numbers will do just fine, but what do you do when
the results are unexpected or completely nonsensical? In GAE/Bingo, the best
thing you could do was shrug and speculate about what happened. BigBingo is
different: we keep around all raw results (user-specific conversion totals) as well as
the source logs and the intermediate data used to determine those results. Since
it&rsquo;s all in BigQuery, investigating anomalies is just a matter of doing some
digging using SQL.</p>

<p>Keeping the raw data also makes it easy to do more advanced analysis
after-the-fact:</p>

<ul>
<li>Instead of just using the mean number of conversions, you can look at more
interesting statistics like the median, percentiles, and standard deviation,
and you can ignore outliers.</li>
<li>You can cross-reference A/B test participation with more sophisticated
metrics, like the
<a href="https://sites.google.com/a/khanacademy.org/forge/khan-academy-data-science-public-documentation/learning-gain">learning gain</a>
metric that the data science team is working on.</li>
<li>You can segment your analysis based on any property you can come up with. For
example, you might want to focus on only new users or only long-term users.</li>
</ul>


<h3>Some other differences</h3>

<ul>
<li>Instead of experiments needing to pick their metrics up-front, every
experiment automatically tracks <em>every</em> conversion (currently we have about 200
of them).</li>
<li>Since KA already has a culture of A/B testing, BigBingo encourages
high-quality experiments rather than focusing on making experiments as easy as
possible. Every experiment has an owner assigned and a description explaining
what the experiment is for and the experimental hypothesis. When an A/B test is
stopped, the author is forced to fill in a conclusion. Whenever an experiment
starts or finishes, a notification is sent to the entire team, so it&rsquo;s easy to see what
kinds of ideas everyone else is trying out and how they are going.</li>
<li>BigBingo doesn&rsquo;t try to be real-time, which makes the implementation much
simpler. After all, up-to-the-minute A/B test results are
<a href="http://bjk5.com/post/12829339471/a-b-testing-still-works-sarcastic-phew">pretty useless</a>
anyway.</li>
<li>The use of memcache counters added
<a href="http://bjk5.com/post/36567537399/dangers-of-using-memcache-counters-for-a-b-tests">a little bit of complexity</a>
to GAE/Bingo, which I was happy to get rid of. Not only were there complex
details, running BigBingo and GAE/Bingo side-by-side revealed some additional
race conditions in GAE/Bingo that weren&rsquo;t known yet.</li>
</ul>


<h2>Implementation</h2>

<p>Here&rsquo;s a big-picture overview of what BigBingo looks like:</p>

<p><img src="http://www.alangpierce.com/images/architecture.png" alt="The architecture" /></p>

<p>Here&rsquo;s how the data flows from a user-facing request to BigQuery, then to the
dashboard UI:</p>

<ol>
<li>When a user enters into an A/B test, that event is recorded through a log
statement. The user&rsquo;s alternative is chosen through a deterministic function
similar to <code>hash(experiment_name + user_id) % num_alternatives</code>, so no RPCs are
necessary to coordinate that information.</li>
<li>When a user triggers a conversion event, it is recorded through a log
statement.</li>
<li>In the hourly LogToBigQuery log export process, the raw log events (called
&ldquo;bingo events&rdquo;) are parsed and extracted into custom BigQuery columns to be
included in the normal request logs tables.</li>
<li>Every two hours, the BigBingo Summarize task runs and processes the new logs
to compute the latest A/B test numbers, following a few rules:

<ul>
<li>If a user participates multiple times in an A/B test (which is common),
only the earliest event counts.</li>
<li>A conversion event only counts for an experiment if the event happened
after the user first participated in the experiment.</li>
<li>For each conversion, BigBingo computes both the total number of times the
conversion was triggered and the total number of distinct users that
triggered the conversion.</li>
</ul>
</li>
<li>The latest data is cleaned up and copied to a &ldquo;publish&rdquo; dataset where it can
be conveniently accessed.</li>
<li>The BigBingo dashboard, a web UI, queries these results to disply all data
about a given experiment: the historical participant and conversion numbers, as
well as p-values for each alternative.</li>
</ol>


<p>Most of the details are reasonably straightforward, but I&rsquo;ll dig into what&rsquo;s
probably the most controversial aspect of this architecture: the decision to
use Google BigQuery for all storage and processing.</p>

<h3>About BigQuery</h3>

<p>If you&rsquo;re not familiar with BigQuery, it&rsquo;s a hosted Google service (really an
externalization of an internal Google service called
<a href="http://research.google.com/pubs/pub36632.html">Dremel</a>) that allows
you to import giant datasets and run nearly-arbitrary SQL queries on them.
BigQuery is way faster than MapReduce-based SQL engines like Hive: you&rsquo;re
borrowing thousands of machines from Google for just the duration of your
query, and all work is done in-memory, so queries tend to finish in just a few
seconds. The primary use case for BigQuery is for human users to manually dig
into data, but I&rsquo;ll show how it can also be used to build stateful data
pipelines.</p>

<p>BigQuery supports nearly all SQL, but don&rsquo;t let that fool you into thinking it&rsquo;s
anything close to a relational database! It has a small set of primitives that&rsquo;s
different from anything I&rsquo;ve worked with before:</p>

<table>
<thead>
<tr>
<th> Operation </th>
<th> Price </th>
</tr>
</thead>
<tbody>
<tr>
<td> Import CSV/JSON data into a table </td>
<td> Free</td>
</tr>
<tr>
<td> Run a SELECT query </td>
<td> 0.5 cents per GB in all columns touched</td>
</tr>
<tr>
<td> Store a query result as a new table </td>
<td> Free</td>
</tr>
<tr>
<td> Apppend query results to the end of a table </td>
<td> Free</td>
</tr>
<tr>
<td> Copy a table </td>
<td> Free</td>
</tr>
</tbody>
</table>


<p><br /></p>

<p>There are
<a href="https://developers.google.com/bigquery/docs/reference/v2/">a few more operations</a>
that are less common, but the ones I listed are the most common ones.</p>

<p>Notice anything missing? No transactions? Not even a way to update or delete
rows? No way to pull out a single row without paying for the whole table? How
can you possibly keep track of A/B test results in such a restricted system?
You&rsquo;re pretty much stuck with the following rule:</p>

<p><strong>To update a table, you must completely rebuild it from scratch with the new
values.</strong></p>

<h3>That&rsquo;s crazy, right?</h3>

<p>It certainly feels like an architectural sin to rebuild all of your data over
and over, but it&rsquo;s not as unreasonable as you might think. BigQuery is quite
cost-efficient (some rough numbers suggest that it&rsquo;s more than 10x as
cost-efficient as MapReduce running on App Engine), and there are lots of
little tricks you can do to reduce the size of your tables. By designing the
table schemas with space-efficiency in mind, I was able to reduce BigBingo&rsquo;s
data usage from 1TB ($5 per query) to 50GB (25 cents per query). (I&rsquo;ll go over
the details in a future blog post.)</p>

<p>There are also some huge usability advantages to using BigQuery over
another batch processing system like MapReduce:</p>

<ul>
<li>When I was designing the queries and schema, I could try things out on real
production data from within the BigQuery web UI and get results back in
seconds. This meant that I could work through almost all architectural details
before having to write a line of Python code.</li>
<li>Once I did start to write code, I could run the full job completely from my
laptop, with no need to push code out to servers in order to iterate. Whenever
a query had a problem, it showed up in the &ldquo;Query History&rdquo; section of the
BigQuery web UI, and I could easily debug it there.</li>
<li>Sanity-checking the intermediate steps and hunting down problems in the data
was easy because everything was immediately accessible through SQL.</li>
</ul>


<h3>Taking advantage of immutable storage</h3>

<p>At first, having to deal with only immutable tables felt like an annoying
restriction that I just had to live with, but as soon as I started thinking
about making the system robust, immutability was a huge benefit. When thinking
through the details, I discovered some important lessons:</p>

<ul>
<li><strong>Never append to the end of a table. Keep tables immutable and queries
idempotent.</strong></li>
<li><strong>A table&rsquo;s name should exactly define its contents.</strong></li>
</ul>


<p>This is probably best explained by looking at a simple data pipeline similar to
BigBingo. First, I&rsquo;ll give a straightforward but fragile approach, then show
how it can be improved to take advantage of BigQuery&rsquo;s architecture.</p>

<p><strong>Goal:</strong> Keep track of the median number of problems solved, problems
attempted, and hints taken across all users.</p>

<p>Every hour, the following queries are done to update the <code>latest_medians</code>
table:</p>

<p><strong>Step 1:</strong> Extract the events from the logs table into a table called
<code>new_event_totals</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>
</pre></td><td class='code'><pre><code class='sql'><span class='line'><span class="c1">-- Results are written to new_event_totals.</span>
</span><span class='line'><span class="k">SELECT</span>
</span><span class='line'>    <span class="n">user_id</span><span class="p">,</span>
</span><span class='line'>    <span class="c1">-- Count the number of times the event column matches each event name.</span>
</span><span class='line'>    <span class="k">SUM</span><span class="p">(</span><span class="n">event</span> <span class="o">=</span> <span class="ss">&quot;problem_correct&quot;</span><span class="p">)</span> <span class="k">AS</span> <span class="n">problem_correct_count</span><span class="p">,</span>
</span><span class='line'>    <span class="k">SUM</span><span class="p">(</span><span class="n">event</span> <span class="o">=</span> <span class="ss">&quot;problem_attempt&quot;</span><span class="p">)</span> <span class="k">AS</span> <span class="n">problem_attempt_count</span><span class="p">,</span>
</span><span class='line'>    <span class="k">SUM</span><span class="p">(</span><span class="n">event</span> <span class="o">=</span> <span class="ss">&quot;hint_taken&quot;</span><span class="p">)</span> <span class="k">AS</span> <span class="n">hint_taken_count</span><span class="p">,</span>
</span><span class='line'><span class="k">FROM</span> <span class="n">logs_2014_07_01</span>
</span><span class='line'><span class="k">WHERE</span> <span class="n">time</span> <span class="o">&gt;=</span> <span class="mi">1404194400</span> <span class="k">AND</span> <span class="n">time</span> <span class="o">&lt;</span> <span class="mi">1404198000</span>
</span><span class='line'><span class="k">GROUP</span> <span class="k">EACH</span> <span class="k">BY</span> <span class="n">user_id</span>  <span class="c1">-- GROUP EACH BY is just a large-scale GROUP BY</span>
</span></code></pre></td></tr></table></div></figure>


<p><strong>Step 2:</strong> Combine <code>new_event_totals</code> with the previous <code>full_event_totals</code>
table to make the new <code>full_event_totals</code> table:</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='sql'><span class='line'><span class="c1">-- Results are written to full_event_totals by querying to a temp table and</span>
</span><span class='line'><span class="c1">-- copying over full_event_totals.</span>
</span><span class='line'><span class="k">SELECT</span>
</span><span class='line'>    <span class="n">user_id</span><span class="p">,</span>
</span><span class='line'>    <span class="k">SUM</span><span class="p">(</span><span class="n">problem_correct_count</span><span class="p">)</span> <span class="k">AS</span> <span class="n">problem_correct_count</span><span class="p">,</span>
</span><span class='line'>    <span class="k">SUM</span><span class="p">(</span><span class="n">problem_attempt_count</span><span class="p">)</span> <span class="k">AS</span> <span class="n">problem_attempt_count</span><span class="p">,</span>
</span><span class='line'>    <span class="k">SUM</span><span class="p">(</span><span class="n">hint_taken_count</span><span class="p">)</span> <span class="k">AS</span> <span class="n">hint_taken_count</span><span class="p">,</span>
</span><span class='line'><span class="k">FROM</span> <span class="n">new_event_totals</span><span class="p">,</span> <span class="n">full_event_totals</span> <span class="c1">-- UNION ALL</span>
</span><span class='line'><span class="k">GROUP</span> <span class="k">EACH</span> <span class="k">BY</span> <span class="n">user_id</span>
</span></code></pre></td></tr></table></div></figure>


<p><strong>Step 3:</strong> Find the median of each metric, and write the result to a table
called <code>latest_medians</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='sql'><span class='line'><span class="c1">-- Results are written to latest_medians.</span>
</span><span class='line'><span class="k">SELECT</span>
</span><span class='line'>    <span class="n">NTH</span><span class="p">(</span><span class="mi">50</span><span class="p">,</span> <span class="n">QUANTILES</span><span class="p">(</span><span class="n">problem_correct_count</span><span class="p">,</span> <span class="mi">100</span><span class="p">))</span> <span class="k">AS</span> <span class="n">median_problems_correct</span><span class="p">,</span>
</span><span class='line'>    <span class="n">NTH</span><span class="p">(</span><span class="mi">50</span><span class="p">,</span> <span class="n">QUANTILES</span><span class="p">(</span><span class="n">problem_attempt_count</span><span class="p">,</span> <span class="mi">100</span><span class="p">))</span> <span class="k">AS</span> <span class="n">median_problems_attempted</span><span class="p">,</span>
</span><span class='line'>    <span class="n">NTH</span><span class="p">(</span><span class="mi">50</span><span class="p">,</span> <span class="n">QUANTILES</span><span class="p">(</span><span class="n">hint_taken_count</span><span class="p">,</span> <span class="mi">100</span><span class="p">))</span> <span class="k">AS</span> <span class="n">median_hints_taken</span><span class="p">,</span>
</span><span class='line'><span class="k">FROM</span> <span class="n">full_event_totals</span>
</span></code></pre></td></tr></table></div></figure>


<p>This code ends up working, but it doesn&rsquo;t handle failure very well:</p>

<ul>
<li>Step 2 isn&rsquo;t idempotent. For certain errors (e.g. a connection timeout when
submitting the query), there&rsquo;s no way to know for sure if it&rsquo;s safe to retry,
or if it succeeded in the first place.</li>
<li>If the job fails between steps 2 and 3, it can&rsquo;t be safely retried, so you
need to either manually re-run step 3 or live with out-of-date results for an
hour.</li>
<li>If the job fails before step 2 finishes and isn&rsquo;t retried before the
next job runs, the event_totals table will lose all events from that hour.</li>
<li>If the logs weren&rsquo;t successfully loaded into BigQuery, Step 1 will think that
nothing happend in that hour and will silently compute the wrong results.</li>
</ul>


<p>To solve all of these problems, just <strong>include a timestamp in each table&rsquo;s
name</strong>. The background job then takes as a parameter the particular hour to
process, rather than trying to figure out what the &ldquo;latest&rdquo; hour is. Here&rsquo;s
what it would do if you run it with the hour from 6:00 to 7:00 on July 1:</p>

<p><strong>Step 1:</strong> Read from <code>logs_2014_07_01_06</code> (the logs for 6:00 to 7:00 on July
1) and write to the table <code>new_event_totals_logs_2014_07_01_06</code> (the new events
for 6:00 to 7:00 on July 1).</p>

<p><strong>Step 2:</strong> Read from <code>new_event_totals_logs_2014_07_01_06</code>
and <code>full_event_totals_2014_07_01_06</code> and write to the table
<code>full_event_totals_2014_07_01_07</code> (the full totals as of 7:00 on July 1).</p>

<p><strong>Step 3:</strong> Read from <code>full_event_totals_2014_07_01_07</code> and write to the table
<code>latest_medians_2014_07_01_07</code> (the medians as of 7:00 on July 1).</p>

<p>The job takes the hour to process as a parameter, and reads the previous hour&rsquo;s
tables to generate that hour&rsquo;s tables. Making three new tables per hour may
seem wasteful, but it&rsquo;s actually <strong>just as easy and cheap as the previous
scheme</strong>. The main problem is that the tables will just accumulate over time,
so you&rsquo;ll rack up storage costs. Fortunately, BigQuery makes it easy to give an
expiration time to tables, so you can set them to be automatically deleted
after a week (or however long you want to keep them).</p>

<p>The core BigBingo job has 7 queries/tables instead of 3, but it is designed
with the same strategy of keeping all old tables, and this strategy has helped
tremendously and kept BigBingo&rsquo;s data consistent in the face of all sorts of
errors:</p>

<ul>
<li>Various transient errors (connection timeouts, internal BigQuery errors,
etc.) have caused the whole BigBingo job to occasionally fail, and in these
cases, it&rsquo;s <em>always</em> safe to just retry the job.</li>
<li>The log import process has sometimes failed and sometimes taken too long
to run, and in both situations, BigBingo automatically fails (and sends an
email reporting the failure) because the data it depends on isn&rsquo;t ready yet.</li>
<li>Whenever BigBingo fails, all future BigBingo jobs fail (rather than computing
incorrect data) until the data is caught up.</li>
<li>Sometimes two instances of the job end up running at the same time. Since the
intermediate data is all timestamped, this doesn&rsquo;t cause any problems.</li>
<li>One time, when retrying a failed job, I accidentally gave an incorrect UNIX
timestamp. The wrong hour was processed, but it didn&rsquo;t hurt data integrity at
all.</li>
<li>In one or two cases, bugs have made the data actually incorrect for a while.
Repairing the system is easy: just fix the bug and re-run the BigBingo job from
before the bug was introduced.</li>
</ul>


<p>The system is completely foolproof: I could replace cron with a thousand
monkeys repeatedly triggering BigBingo jobs with random UNIX timestamps, and
the system would still eventually make progress and remain completely
consistent (although it would be a little less cost-efficient). That level of
safety means I can stop worrying about maintenance and focus on more important
things.</p>

<h2>Where&rsquo;s the source code?</h2>

<p>Ideally, BigBingo would be a self-contained open-source library, but it
currently has enough dependencies on internal KA infrastructure that it&rsquo;s both
hard to make general and would be a bit difficult to use in isolation anyway.</p>

<p>That said, there&rsquo;s no reason I can&rsquo;t share the code, so
<a href="https://gist.github.com/alangpierce/f0ad63643b446a4f84ad">here&rsquo;s a Gist with pretty much all of the code</a>
(at the time of this blog post). I put an MIT license on it, so feel free to
base work off of it or use any of the self-contained pieces.</p>

<p>Khan Academy has
<a href="https://github.com/Khan">lots of open-source projects</a>, and it&rsquo;s not out of
the question for BigBingo to be made truly open source in the future, so let me
know in the comments if you think you would use it.</p>

<h2>That&rsquo;s all for now</h2>

<p>Curious about any more details? Think we&rsquo;re doing A/B testing all wrong?
Let me know in the comments!</p>
]]></content>
  </entry>
  
</feed>
