<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"> 
<head>
<title>Economic Interpreter for Haskell</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="pandoc" />
<meta name="copyright" content="Copyright &#169; 2008-2011 Péter Diviánszky" />
<link rel="shortcut icon" href="icon.ico" />
<script src="common_en.js" charset="utf-8" type="text/javascript"></script> 
<link rel="stylesheet" href="common.css" type="text/css" />
</head>
<body onload="javascript:resetForms(); javascript:slidy_init();">
<div><h1 class="cover">Economic Interpreter for Haskell</h1>
<div id="info"></div>
<ul>
<li><a href="#introduction">Introduction</a></li>
<li><a href="#about-hint">About <code>hint</code></a></li>
<li><a href="#the-first-try">The First Try</a></li>
<li><a href="#batch-processing">Batch Processing</a></li>
<li><a href="#many-requests">Many Requests</a></li>
<li><a href="#economic-use">Economic Use</a></li>
<li><a href="#experiences">Experiences</a></li>
<li><a href="#source-code">Source Code</a></li>
</ul>
</div>
<div class="section level1" id="introduction">
<h1><a href="#introduction">Introduction</a></h1>
<p>I needed a Haskell interpreter for evaluating students’ exercises.<br />It had to be fast because I use it online with AJAX like this (edit the expression and hit enter):</p>
<div class="indent"><form class="resetinterpreter" action="javascript:getOne('c=eval&amp;f=Economic_en.hs','2322c31cbb6e973c2119d790a6ac5181','2322c31cbb6e973c2119d790a6ac5181');"><code class="prompt">Test&gt; </code><input class="interpreter" type="text" size="60" maxlength="1000" id="tarea2322c31cbb6e973c2119d790a6ac5181" value="1 + 1" /><br /><div class="answer" id="res2322c31cbb6e973c2119d790a6ac5181"><code class="result">2</code><code> :: </code><code class="type">Integer</code></div></form></div>
<p>The most obvious choice was the <a href="http://hackage.haskell.org/package/hint"><code>hint</code></a> Haskell interpreter, but I had to learn how to use it economically. In this post I write down what I learnt.</p>
</div>
<div class="section level1" id="about-hint">
<h1><a href="#about-hint">About <code>hint</code></a></h1>
<p><code>hint</code> is quite easy to use, we have an <code>Interpreter</code> monad with basic actions like type inference, module imports and evaluation of strings as Haskell expressions. At the end we can run the <code>Interpreter</code> action in <code>IO</code>.</p>
<p>The interesting part is that there is an <code>interpret</code> function which interpret strings as Haskell expressions but does not evaluate them!</p>
<pre class="sourceCode haskell"><code class="sourceCode haskell"><span class="ot">interpret ::</span> <span class="dt">Typeable</span> a <span class="ot">=&gt;</span> <span class="dt">String</span> <span class="ot">-&gt;</span> a <span class="ot">-&gt;</span> <span class="dt">Interpreter</span> a</code></pre>
<p>(I specialized the type of <code>interpret</code> to be more comprehensible.)<br />The second argument is a witness for the type system that the result type is not polymorph, it will not be used during the computation.</p>
<p>So we give a <code>String</code> in and we can tell what we would like to get: an <code>Int</code>, an <code>[Int]</code> or a <code>Dynamic</code> value. If there is no type error (no fail in the <code>Interpreter</code> monad), we get an <em>unevaluated</em> value of the given type. Finally this was the solution to my problem.</p>
</div>
<div class="section level1" id="the-first-try">
<h1><a href="#the-first-try">The First Try</a></h1>
<p>First I started a new <code>Interpreter</code> action for each request in parallel. This was too slow for me because basically it started a new GHCi every time which have to load its libraries. Try <code>time ghc -e &quot;1+1&quot;</code> on your machine, it will tell you how slow it is.</p>
<p>I show you an ASCII picture about the situation (boxes are interpreter actions, <code>=</code> signs denote interpretation and evaluation of strings):</p>
<pre><code> ___________
|           |
|    [====] |
|___________|
     ___________
    |           |
    |    [====] |
    |___________|
   ___________________
  |                   |
  |    [============] |
  |___________________|</code></pre>
</div>
<div class="section level1" id="batch-processing">
<h1><a href="#batch-processing">Batch Processing</a></h1>
<p>Fortunately we can run any <code>IO</code> action in <code>Interpreter</code> with <code>liftIO</code>. I set up a channel and send the strings to the interpreter through the channel. The interpreter send back the results via mutable variables (these answer-variables are sent to the interpreter paired with the strings.)</p>
<pre><code> _______________________________
|                           
|    [====] [==]  [========] 
|_______________________________</code></pre>
<p>This is a good solution but something is missing!</p>
</div>
<div class="section level1" id="many-requests">
<h1><a href="#many-requests">Many Requests</a></h1>
<p>I had many strings to interpret in parallel and I wanted to interpret them separately to decrease response time.</p>
<p>First I started worker threads with a constantly running <code>Interpreter</code> action in each. I noticed that memory consumption grew linearly with the number of worker threads which was not good because <code>Interpreter</code> need quite a lot memory.</p>
<pre><code> _______________________________
|                           
|     [==]  [====] [======] 
|_______________________________
 _______________________________
|                           
|    [====]   [==] [========] 
|_______________________________
 _______________________________
|                           
|      [===] [=]   [======] 
|_______________________________</code></pre>
</div>
<div class="section level1" id="economic-use">
<h1><a href="#economic-use">Economic Use</a></h1>
<p>The final solution was straightforward.</p>
<p>I use <em>only one</em> worker thread, I send it the strings through the channel and it send back <em>unevaluated</em> <code>Dynamic</code> values! Finally I evaluate the <code>Dynamic</code> values in parallel (in <em>one</em> GHC runtime, so memory consumption does not grow that much).</p>
<p>The throughput of this architecture depends on the speed of parsing and typechecking of GHC which is quite fast for small strings.</p>
<pre><code> _______________________________
|Interpreter
|    [=] [=]  [=] [=] [=] 
|______|___|____|___|___|_______
       |   |    |   |   |
 GHC   |   |    |   |   [====]
 runtime   |    |   |
       |   |    |   [========]
       |   |    |
       |   |    [=====]
       |   |
       |   [============]
       |
       [=====]</code></pre>
<p>Module reloads needs more time with <code>hint</code> so I try to avoid that in the worker thread; if the next request need exactly the same module imports then the environment will be not be cleared.</p>
</div>
<div class="section level1" id="experiences">
<h1><a href="#experiences">Experiences</a></h1>
<p>I use the <code>hint</code> interpreter in a <code>snap</code> server on a 2 core 3.20GHz Intel Xeon CPU, on a 64 bit freeBSD operating system. This is not the only application which run on this machine. The machine has 2 GB RAM, but my application is allowed to use maximum 500 MB, and it typically use 200-300 MB memory.</p>
<p>So far it interpreted approximately half million strings, 3000 strings/hour during heaviest use so far. (I did not measure the upper limit.) The throughput could be increased with more worker threads (but then memory consumption will increase too). I have no statistics about response times but it should be under 0.1s on the average.</p>
</div>
<div class="section level1" id="source-code">
<h1><a href="#source-code">Source Code</a></h1>
<p>The source code will be released on HackageDB with the server application, stay tuned!</p>
</div>
<div><h1><a href="Overview_en.xml">Back to the main page</a></h1>
<p><em><a href="Overview_en.xml">Main page</a></em></p>
</div>
</body>
</html>

