<br><br><div class="gmail_quote">On Sun, Feb 26, 2012 at 1:36 PM, Yves Parès <span dir="ltr">&lt;<a href="mailto:yves.pares@gmail.com">yves.pares@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">
Hello,<br>When I was using C code from Python, the overhead put on calling C code by Python was significant.<br>To simplify, say I have on C-side two procedures f and g, I do all the stuff to call them in a row from Python, well I&#39;m better off factorizing: adding on C side a wrapper h procedure that calls them both, and then call h from Python, because then I will have half as much overhead:<br>


<br>Instead of SwitchToC -&gt; call f -&gt; SwitchToPython -&gt; SwitchToC -&gt; call g -&gt; SwitchToPython,<br>the factorization leads to SwitchToC -&gt; call f -&gt; call g -&gt; SwitchToPython,<br>which gives the same result yet is different performance-wise because each switching has a cost.<br>


<br>This is painful, because if another time I have to call f and j (another function), then I have to make another wrapper.<br><br>In Haskell world, now, given that my functions f and g would have been imported using <b>unsafe</b>:<br>


<br>foreign import unsafe &quot;f&quot; f :: Thing -&gt; Foo -&gt; IO ()<br>foreign import unsafe &quot;g&quot; g :: Stuff -&gt; Bar -&gt; IO ()<br>foreign import unsafe &quot;h&quot; h :: Thing -&gt; Foo -&gt; Stuff -&gt; Bar -&gt; IO ()<br>


<br>Are<br>doStuff = f x y &gt;&gt; g z w<br>and<br>doStuff = h x y z w<br>equivalent, or is there an overhead (e.g. due to IO monad, or due to the way the FFI does the calls) when compiled (if need be with optimizations) with GHC? <br>
</blockquote><div><br></div><div>Each unsafe call to FFI should be pretty fast - I have measured it to be about 15ns on my computer (~30-50 clock cycles). Assuming C implementation of (f;g) and h take about the same time in C, first version of doStuff would likely be a bit slower than second version because of one additional FFI call - I would expect it to take ~15ns more on my computer. From what I have seen in my code, GHC optimizes away IO monad when compiled with -O2 flag. So, impact of IO monad on performance should usually be negligible/close to zero.</div>
<div><br></div><div>Keep in mind that unsafe call to FFI will block the OS capability used up for that FFI thread until that FFI call returns (more here: <a href="http://blog.melding-monads.com/category/haskell/">http://blog.melding-monads.com/category/haskell/</a>). So, if it takes long time to execute, you might want to use the safe version instead. I have seen safe version take about ~150ns in my tests.</div>
<div><br></div><div>Like Jason said, you could create a micro-benchmark to see the difference. For example, like below:</div><div><br></div><div><pre style="margin-top:0px;margin-bottom:0px;font-size:13px;text-align:left;background-color:rgb(255,255,255)">
<span class="hs-conid" style="color:rgb(79,67,113)">Haskell</span> <span class="hs-varid" style="color:rgb(51,51,51)">code</span><span class="hs-conop">:</span>

<pre style="margin-top:0px;margin-bottom:0px"><span class="hs-keyword" style="color:rgb(57,116,96)">import</span> <span class="hs-conid" style="color:rgb(79,67,113)">Control</span><span class="hs-varop" style="color:rgb(51,51,51)">.</span><span class="hs-conid" style="color:rgb(79,67,113)">Monad</span> <span class="hs-layout">(</span><span class="hs-varid" style="color:rgb(51,51,51)">forM_</span><span class="hs-layout">)</span>
<span class="hs-keyword" style="color:rgb(57,116,96)">import</span> <span class="hs-conid" style="color:rgb(79,67,113)">Foreign</span><span class="hs-varop" style="color:rgb(51,51,51)">.</span><span class="hs-conid" style="color:rgb(79,67,113)">C</span><span class="hs-varop" style="color:rgb(51,51,51)">.</span><span class="hs-conid" style="color:rgb(79,67,113)">Types</span> <span class="hs-layout">(</span><span class="hs-conid" style="color:rgb(79,67,113)">CInt</span><span class="hs-layout">)</span>
<span class="hs-keyword" style="color:rgb(57,116,96)">import</span> <span class="hs-conid" style="color:rgb(79,67,113)">Data</span><span class="hs-varop" style="color:rgb(51,51,51)">.</span><span class="hs-conid" style="color:rgb(79,67,113)">Time</span><span class="hs-varop" style="color:rgb(51,51,51)">.</span><span class="hs-conid" style="color:rgb(79,67,113)">Clock</span> <span class="hs-layout">(</span><span class="hs-varid" style="color:rgb(51,51,51)">diffUTCTime</span><span class="hs-layout">,</span> <span class="hs-varid" style="color:rgb(51,51,51)">getCurrentTime</span><span class="hs-layout">)</span>
<span class="hs-keyword" style="color:rgb(57,116,96)">import</span> <span class="hs-conid" style="color:rgb(79,67,113)">Foreign</span><span class="hs-varop" style="color:rgb(51,51,51)">.</span><span class="hs-conid" style="color:rgb(79,67,113)">C</span>


<span class="hs-keyword" style="color:rgb(57,116,96)">foreign</span> <span class="hs-keyword" style="color:rgb(57,116,96)">import</span> <span class="hs-keyword" style="color:rgb(57,116,96)">ccall</span> <span class="hs-keyword" style="color:rgb(57,116,96)">safe</span> <span class="hs-str" style="color:rgb(54,99,84)">&quot;print&quot;</span>
  <span class="hs-varid" style="color:rgb(51,51,51)">printsafe</span> <span class="hs-keyglyph">::</span> <span class="hs-conid" style="color:rgb(79,67,113)">CInt</span> <span class="hs-keyglyph">-&gt;</span> <span class="hs-conid" style="color:rgb(79,67,113)">IO</span> <span class="hs-conid" style="color:rgb(79,67,113)">()</span>
<span class="hs-keyword" style="color:rgb(57,116,96)">foreign</span> <span class="hs-keyword" style="color:rgb(57,116,96)">import</span> <span class="hs-keyword" style="color:rgb(57,116,96)">ccall</span> <span class="hs-keyword" style="color:rgb(57,116,96)">unsafe</span> <span class="hs-str" style="color:rgb(54,99,84)">&quot;print&quot;</span>
  <span class="hs-varid" style="color:rgb(51,51,51)">printunsafe</span> <span class="hs-keyglyph">::</span> <span class="hs-conid" style="color:rgb(79,67,113)">CInt</span> <span class="hs-keyglyph">-&gt;</span> <span class="hs-conid" style="color:rgb(79,67,113)">IO</span> <span class="hs-conid" style="color:rgb(79,67,113)">()</span>


<span class="hs-definition">main</span> <span class="hs-keyglyph">=</span> <span class="hs-keyword" style="color:rgb(57,116,96)">do</span>
  <span class="hs-keyword" style="color:rgb(57,116,96)">let</span>  <span class="hs-varid" style="color:rgb(51,51,51)">l</span> <span class="hs-keyglyph">=</span> <span class="hs-num" style="color:rgb(79,67,113)">50000</span>
  <span class="hs-varid" style="color:rgb(51,51,51)">a</span> <span class="hs-keyglyph">&lt;-</span> <span class="hs-varid" style="color:rgb(51,51,51)">getCurrentTime</span>
  <span class="hs-varid" style="color:rgb(51,51,51)">forM_</span> <span class="hs-keyglyph">[</span><span class="hs-num" style="color:rgb(79,67,113)">1</span><span class="hs-keyglyph">..</span><span class="hs-varid" style="color:rgb(51,51,51)">l</span><span class="hs-keyglyph">]</span> <span class="hs-varop" style="color:rgb(51,51,51)">$</span> <span class="hs-keyglyph">\</span><span class="hs-varid" style="color:rgb(51,51,51)">x</span> <span class="hs-keyglyph">-&gt;</span> <span class="hs-varid" style="color:rgb(51,51,51)">printsafe</span> <span class="hs-varid" style="color:rgb(51,51,51)">x</span>
  <span class="hs-varid" style="color:rgb(51,51,51)">b</span> <span class="hs-keyglyph">&lt;-</span> <span class="hs-varid" style="color:rgb(51,51,51)">getCurrentTime</span>
  <span class="hs-varid" style="color:rgb(51,51,51)">forM_</span> <span class="hs-keyglyph">[</span><span class="hs-num" style="color:rgb(79,67,113)">1</span><span class="hs-keyglyph">..</span><span class="hs-varid" style="color:rgb(51,51,51)">l</span><span class="hs-keyglyph">]</span> <span class="hs-varop" style="color:rgb(51,51,51)">$</span> <span class="hs-keyglyph">\</span><span class="hs-varid" style="color:rgb(51,51,51)">x</span> <span class="hs-keyglyph">-&gt;</span> <span class="hs-varid" style="color:rgb(51,51,51)">printunsafe</span> <span class="hs-varid" style="color:rgb(51,51,51)">x</span>
  <span class="hs-varid" style="color:rgb(51,51,51)">c</span> <span class="hs-keyglyph">&lt;-</span> <span class="hs-varid" style="color:rgb(51,51,51)">getCurrentTime</span>

  <span class="hs-varid" style="color:rgb(51,51,51)">print</span> <span class="hs-varop" style="color:rgb(51,51,51)">$</span> <span class="hs-str" style="color:rgb(54,99,84)">&quot;safe call average overhead &quot;</span> <span class="hs-varop" style="color:rgb(51,51,51)">++</span> <span class="hs-varid" style="color:rgb(51,51,51)">show</span> <span class="hs-layout">(</span><span class="hs-layout">(</span><span class="hs-varid" style="color:rgb(51,51,51)">diffUTCTime</span> <span class="hs-varid" style="color:rgb(51,51,51)">b</span> <span class="hs-varid" style="color:rgb(51,51,51)">a</span><span class="hs-layout">)</span><span class="hs-varop" style="color:rgb(51,51,51)">/</span><span class="hs-varid" style="color:rgb(51,51,51)">fromIntegral</span> <span class="hs-varid" style="color:rgb(51,51,51)">l</span><span class="hs-layout">)</span>
  <span class="hs-varid" style="color:rgb(51,51,51)">print</span> <span class="hs-varop" style="color:rgb(51,51,51)">$</span> <span class="hs-str" style="color:rgb(54,99,84)">&quot;unsafe call average overhead &quot;</span> <span class="hs-varop" style="color:rgb(51,51,51)">++</span> <span class="hs-varid" style="color:rgb(51,51,51)">show</span> <span class="hs-layout">(</span><span class="hs-layout">(</span><span class="hs-varid" style="color:rgb(51,51,51)">diffUTCTime</span> <span class="hs-varid" style="color:rgb(51,51,51)">c</span> <span class="hs-varid" style="color:rgb(51,51,51)">b</span><span class="hs-layout">)</span><span class="hs-varop" style="color:rgb(51,51,51)">/</span><span class="hs-varid" style="color:rgb(51,51,51)">fromIntegral</span> <span class="hs-varid" style="color:rgb(51,51,51)">l</span><span class="hs-layout">)</span>

<br></pre></pre><pre style="margin-top:0px;margin-bottom:0px;font-size:13px;text-align:left;background-color:rgb(255,255,255)"><span class="hs-conid" style="color:rgb(79,67,113)">C</span> <span class="hs-varid" style="color:rgb(51,51,51)">code</span><span class="hs-conop">:</span>

<span class="hs-cpp">#include &lt;stdio.h&gt;</span>

<span class="hs-definition">void</span> <span class="hs-varid" style="color:rgb(51,51,51)">print</span><span class="hs-layout">(</span><span class="hs-varid" style="color:rgb(51,51,51)">int</span> <span class="hs-varid" style="color:rgb(51,51,51)">x</span><span class="hs-layout">)</span><span class="hs-layout">{</span>
  <span class="hs-varid" style="color:rgb(51,51,51)">return</span><span class="hs-layout">;</span>
<span class="hs-layout">}</span></pre></div></div>