<div>makeSessionBackend calls &quot;getKey&quot; from clientsession:</div><div><br></div><a href="http://hackage.haskell.org/packages/archive/clientsession/0.8.0/doc/html/src/Web-ClientSession.html#getKey">http://hackage.haskell.org/packages/archive/clientsession/0.8.0/doc/html/src/Web-ClientSession.html#getKey</a><br>

<br>Looking at that function no wonder it is a bottleneck:<div><br></div><div><pre><span class="hs-comment" style="color:green">-- | Get a key from the given text file.</span>
<a name="line-146"></a><span class="hs-comment" style="color:green">--</span>
<a name="line-147"></a><span class="hs-comment" style="color:green">-- If the file does not exist or is corrupted a random key will</span>
<a name="line-148"></a><span class="hs-comment" style="color:green">-- be generated and stored in that file.</span>
<a name="line-149"></a><span class="hs-definition">getKey</span> <span class="hs-keyglyph" style="color:red">::</span> <span class="hs-conid">FilePath</span>     <span class="hs-comment" style="color:green">-- ^ File name where key is stored.</span>
<a name="line-150"></a>       <span class="hs-keyglyph" style="color:red">-&gt;</span> <span class="hs-conid">IO</span> <span class="hs-conid">Key</span>       <span class="hs-comment" style="color:green">-- ^ The actual key.</span>
<a name="line-151"></a><span class="hs-definition">getKey</span> <span class="hs-varid">keyFile</span> <span class="hs-keyglyph" style="color:red">=</span> <span class="hs-keyword" style="color:blue">do</span>
<a name="line-152"></a>    <span class="hs-varid">exists</span> <span class="hs-keyglyph" style="color:red">&lt;-</span> <span class="hs-varid">doesFileExist</span> <span class="hs-varid">keyFile</span>
<a name="line-153"></a>    <span class="hs-keyword" style="color:blue">if</span> <span class="hs-varid">exists</span>
<a name="line-154"></a>        <span class="hs-keyword" style="color:blue">then</span> <span class="hs-conid">S</span><span class="hs-varop">.</span><span class="hs-varid">readFile</span> <span class="hs-varid">keyFile</span> <span class="hs-varop">&gt;&gt;=</span> <span class="hs-varid">either</span> <span class="hs-layout" style="color:red">(</span><span class="hs-varid">const</span> <span class="hs-varid">newKey</span><span class="hs-layout" style="color:red">)</span> <span class="hs-varid">return</span> <span class="hs-varop">.</span> <span class="hs-varid">initKey</span>
<a name="line-155"></a>        <span class="hs-keyword" style="color:blue">else</span> <span class="hs-varid">newKey</span>
<a name="line-156"></a>  <span class="hs-keyword" style="color:blue">where</span>
<a name="line-157"></a>    <span class="hs-varid">newKey</span> <span class="hs-keyglyph" style="color:red">=</span> <span class="hs-keyword" style="color:blue">do</span>
<a name="line-158"></a>        <span class="hs-layout" style="color:red">(</span><span class="hs-varid">bs</span><span class="hs-layout" style="color:red">,</span> <span class="hs-varid">key&#39;</span><span class="hs-layout" style="color:red">)</span> <span class="hs-keyglyph" style="color:red">&lt;-</span> <span class="hs-varid">randomKey</span>
<a name="line-159"></a>        <span class="hs-conid">S</span><span class="hs-varop">.</span><span class="hs-varid">writeFile</span> <span class="hs-varid">keyFile</span> <span class="hs-varid">bs</span>
<a name="line-160"></a>        <span class="hs-varid">return</span> <span class="hs-varid">key&#39;</span></pre><div><br></div><div>Plenty of syscalls, reading and parsing the same file over and over again. Perhaps the default should be to store the key within the foundation datatype at startup?</div>

<div><br></div><div>Best regards,</div><div>Krzysztof Skrzętnicki</div><br><div class="gmail_quote">On Sat, Sep 1, 2012 at 10:37 AM, Lorenzo Bolla <span dir="ltr">&lt;<a href="mailto:lbolla@gmail.com" target="_blank">lbolla@gmail.com</a>&gt;</span> wrote:<br>

<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div class="HOEnZb"><div class="h5">On Fri, Aug 31, 2012 at 10:13:20PM -0300, Felipe Almeida Lessa wrote:<br>
&gt; [Forwarding to Yesod&#39;s mailing list as well.  I&#39;ll copy all of the<br>
&gt; original text below for those who aren&#39;t on haskell-beginners.]<br>
&gt;<br>
&gt; On Fri, Aug 31, 2012 at 11:24 AM, Lorenzo Bolla &lt;<a href="mailto:lbolla@gmail.com">lbolla@gmail.com</a>&gt; wrote:<br>
&gt; &gt; Hi all,<br>
&gt; &gt;<br>
&gt; &gt; This is a question specific to the Yesod framework, but simple enough<br>
&gt; &gt; (I hope) to be considered a beginner question...<br>
&gt; &gt;<br>
&gt; &gt; I am puzzled by the performance of these two very simple web-servers,<br>
&gt; &gt; one written in Warp and another written in Yesod:<br>
&gt; &gt;<br>
&gt; &gt; === YESOD ===<br>
&gt; &gt;<br>
&gt; &gt; {-# LANGUAGE TypeFamilies, QuasiQuotes, MultiParamTypeClasses,<br>
&gt; &gt; TemplateHaskell #-}<br>
&gt; &gt; import Yesod<br>
&gt; &gt;<br>
&gt; &gt; data HelloWorld = HelloWorld<br>
&gt; &gt;<br>
&gt; &gt; mkYesod &quot;HelloWorld&quot; [parseRoutes|<br>
&gt; &gt; / HomeR GET<br>
&gt; &gt; |]<br>
&gt; &gt;<br>
&gt; &gt; instance Yesod HelloWorld<br>
&gt; &gt;<br>
&gt; &gt; getHomeR :: Handler RepHtml<br>
&gt; &gt; getHomeR = defaultLayout [whamlet|$newline always<br>
&gt; &gt; Hello World!<br>
&gt; &gt; |]<br>
&gt; &gt;<br>
&gt; &gt; main :: IO ()<br>
&gt; &gt; -- main = warpDebug 3000 HelloWorld<br>
&gt; &gt; main = warp 3000 HelloWorld<br>
&gt; &gt;<br>
&gt; &gt; === WARP ===<br>
&gt; &gt;<br>
&gt; &gt; {-# LANGUAGE OverloadedStrings #-}<br>
&gt; &gt;<br>
&gt; &gt; import Network.Wai<br>
&gt; &gt; import Network.HTTP.Types<br>
&gt; &gt; import Network.Wai.Handler.Warp (run)<br>
&gt; &gt; import Data.ByteString.Lazy.Char8 ()<br>
&gt; &gt;<br>
&gt; &gt; app :: Application<br>
&gt; &gt; app _ = return $ responseLBS<br>
&gt; &gt;     status200<br>
&gt; &gt;     [(&quot;Content-Type&quot;, &quot;text/html&quot;)]<br>
&gt; &gt;     &quot;Hello, Warp!&quot;<br>
&gt; &gt;<br>
&gt; &gt; main :: IO ()<br>
&gt; &gt; main = do<br>
&gt; &gt;     putStrLn &quot;<a href="http://localhost:8080/" target="_blank">http://localhost:8080/</a>&quot;<br>
&gt; &gt;     run 8080 app<br>
&gt; &gt;<br>
&gt; &gt; ===<br>
&gt; &gt;<br>
&gt; &gt; I&#39;ve tested both using httperf:<br>
&gt; &gt; $&gt; httperf --hog --client=0/1 --server=localhost --port=3000 --uri=/<br>
&gt; &gt; --rate=1000 --send-buffer=4096 --recv-buffer=16384 --num-conns=100<br>
&gt; &gt; --num-calls=100 --burst-length=20<br>
&gt; &gt;<br>
&gt; &gt; and I got very different results:<br>
&gt; &gt;<br>
&gt; &gt; YESOD: Request rate: 4048.0 req/s (0.2 ms/req)<br>
&gt; &gt; WARP: Request rate: 33656.2 req/s (0.0 ms/req)<br>
&gt; &gt;<br>
&gt; &gt; Now, I understand that Yesod is expected to be slower than the &quot;raw&quot;<br>
&gt; &gt; Warp, but I wasn&#39;t expecting a 10x slowdown, especially for such a<br>
&gt; &gt; trivial Yesod app (no db, no auth, etc.).<br>
&gt; &gt;<br>
&gt; &gt; [<br>
&gt; &gt; Compilation command was: ghc -Wall -O2 --make yesod.hs<br>
&gt; &gt; $ yesod version<br>
&gt; &gt; yesod-core version:1.1.0<br>
&gt; &gt; ]<br>
&gt; &gt;<br>
&gt; &gt; What is going on?<br>
&gt; &gt;<br>
&gt; &gt; Thanks,<br>
&gt; &gt; L.<br>
&gt;<br>
&gt; This is actually a rather tricky and interesting question =).<br>
&gt;<br>
&gt; My knee-jerk reaction is &quot;profile!&quot;.  Profiling will give you more<br>
&gt; clues about where the time is being spent.<br>
&gt;<br>
&gt; As Bryce said, you&#39;re using defaultLayout and Hamlet, which should<br>
&gt; slow things down.  Also, you&#39;re implicitly using clientsession, you<br>
&gt; may try setting makeSessionBackend [1] to &#39;const $ return Nothing&#39; and<br>
&gt; see what kind of performance you get.<br>
&gt;<br>
&gt; Cheers!<br>
&gt;<br>
&gt; [1] <a href="http://hackage.haskell.org/packages/archive/yesod-core/1.1.1.1/doc/html/Yesod-Core.html#v:makeSessionBackend" target="_blank">http://hackage.haskell.org/packages/archive/yesod-core/1.1.1.1/doc/html/Yesod-Core.html#v:makeSessionBackend</a><br>


&gt;<br>
&gt; --<br>
&gt; Felipe.<br>
<br>
</div></div>Good catch Felipe!<br>
It looks like `makeSessionBackend` is horribly slow... These are the numbers on<br>
my box:<br>
<br>
Warp<br>
    10250 req/s<br>
<br>
Yesod<br>
    hamlet: 848 req/s<br>
    no-hamlet: 940 req/s (getHomeR = return ∘ RepPlain ∘ toContent $ &quot;Hello World!&quot;)<br>
    no-session: 8000 req/s (makeSessionBackend = const $ return Nothing)<br>
<span class="HOEnZb"><font color="#888888"><br>
L.<br>
<br>
--<br>
Lorenzo Bolla<br>
<a href="http://lbolla.info" target="_blank">http://lbolla.info</a><br>
</font></span><div class="HOEnZb"><div class="h5"><br>
_______________________________________________<br>
Beginners mailing list<br>
<a href="mailto:Beginners@haskell.org">Beginners@haskell.org</a><br>
<a href="http://www.haskell.org/mailman/listinfo/beginners" target="_blank">http://www.haskell.org/mailman/listinfo/beginners</a><br>
</div></div></blockquote></div><br></div>