<div dir="ltr"><br><br><div class="gmail_quote">On Thu, Sep 20, 2012 at 7:25 PM, Gregory Collins <span dir="ltr">&lt;<a href="mailto:greg@gregorycollins.net" target="_blank">greg@gregorycollins.net</a>&gt;</span> wrote:<br>

<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Hey Michael,<div><br></div><div>BTW -- you&#39;re getting crap performance here because of the fromEnum/toEnum in toLowerC, which does checks. An updated version using unsafeChr is faster than your bsToLower call: <a href="https://gist.github.com/3756876" target="_blank">https://gist.github.com/3756876</a></div>


<div><br></div><blockquote style="margin:0 0 0 40px;border:none;padding:0px"><div><div>master /home/gdc/tmp/haskell/chr/gist-3756876 ⚠ $ ./bench </div></div><div><div>warming up</div></div><div><div>estimating clock resolution...</div>


</div><div><div>mean is 1.290661 us (640001 iterations)</div></div><div><div>found 2935 outliers among 639999 samples (0.5%)</div></div><div><div>  2541 (0.4%) high severe</div></div><div><div>estimating cost of a clock call...</div>


</div><div><div>mean is 31.63774 ns (13 iterations)</div></div><div><div>found 2 outliers among 13 samples (15.4%)</div></div><div><div>  2 (15.4%) high mild</div></div><div><div><br></div></div><div><div>benchmarking Char8</div>


</div><div><div>mean: 145.1935 us, lb 141.4375 us, ub 149.8138 us, ci 0.950</div></div><div><div>std dev: 21.28567 us, lb 18.14038 us, ub 23.87625 us, ci 0.950</div></div><div><div>found 22 outliers among 100 samples (22.0%)</div>


</div><div><div>  22 (22.0%) high severe</div></div><div><div>variance introduced by outliers: 89.411%</div></div><div class="im"><div><div>variance is severely inflated by outliers</div></div><div><div><br></div></div><div>

<div>benchmarking Char8 toLowerC</div>
</div></div><div><div>mean: 12.74308 us, lb 12.24657 us, ub 13.31365 us, ci 0.950</div></div><div><div>std dev: 2.712828 us, lb 2.434402 us, ub 2.904232 us, ci 0.950</div></div><div><div>variance introduced by outliers: 94.689%</div>


</div><div class="im"><div><div>variance is severely inflated by outliers</div></div><div><div><br></div></div></div><div><div>benchmarking bsToLower</div></div><div><div>mean: 20.68829 us, lb 20.66869 us, ub 20.70941 us, ci 0.950</div>

</div><div>
<div>std dev: 104.5939 ns, lb 95.37577 ns, ub 120.6401 ns, ci 0.950</div></div></blockquote><div><br></div><div>G.</div><div><div><div class="h5"><br><div class="gmail_quote">On Thu, Sep 20, 2012 at 5:01 PM, Michael Snoyman <span dir="ltr">&lt;<a href="mailto:michael@snoyman.com" target="_blank">michael@snoyman.com</a>&gt;</span> wrote:<br>


<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Well... let&#39;s test it out:<br>
<br>
benchmarking Char8<br>
mean: 333.0050 us, lb 329.2846 us, ub 336.2362 us, ci 0.950<br>
std dev: 17.73400 us, lb 15.69876 us, ub 19.45947 us, ci 0.950<br>
variance introduced by outliers: 51.452%<br>
variance is severely inflated by outliers<br>
<br>
benchmarking Char8 toLowerC<br>
mean: 117.1571 us, lb 116.8739 us, ub 117.4219 us, ci 0.950<br>
std dev: 1.394150 us, lb 1.189928 us, ub 1.649276 us, ci 0.950<br>
<br>
benchmarking Word8<br>
mean: 41.01667 us, lb 40.94708 us, ub 41.09468 us, ci 0.950<br>
std dev: 378.4175 ns, lb 335.4655 ns, ub 462.6281 ns, ci 0.950<br>
<br>
benchmarking bsToLower<br>
mean: 37.37589 us, lb 37.24453 us, ub 37.48697 us, ci 0.950<br>
std dev: 616.5653 ns, lb 513.7510 ns, ub 752.8996 ns, ci 0.950<br>
<div>found 9 outliers among 100 samples (9.0%)<br>
</div>  3 (3.0%) low severe<br>
  4 (4.0%) low mild<br>
  2 (2.0%) high mild<br>
variance introduced by outliers: 9.426%<br>
variance is slightly inflated by outliers<br>
<br>
So a specialized `Char -&gt; Char` function helps, but doesn&#39;t completely<br>
close the performance gap. (Updates at the same gist[1].)<br>
<br>
I disagree with a problem with an extra package: this is such a<br>
low-level detail that average users don&#39;t need to really be aware of<br>
the existence of the package, and I think the marginal increase in<br>
compile times shouldn&#39;t cause any issues. I used to worry much more<br>
about adding extra packages to the mix, but with the more recent<br>
versions of cabal-install and the community&#39;s general improvement in<br>
handling dependency hell, I see less of a reason to do so.<br>
<br>
That said, I think having specialized toLower/toUpper in a central<br>
place- perhaps even bytestring itself- would be a good thing.<br>
<br>
Michael<br>
<br>
[1] <a href="https://gist.github.com/3756212" target="_blank">https://gist.github.com/3756212</a><br>
<div><div><br>
On Thu, Sep 20, 2012 at 5:47 PM, Gregory Collins<br>
&lt;<a href="mailto:greg@gregorycollins.net" target="_blank">greg@gregorycollins.net</a>&gt; wrote:<br>
&gt; This is, of course, not an apples-to-apples test:<br>
&gt;<br>
&gt; Prelude Data.Char&gt; toUpper &#39;χ&#39;<br>
&gt; &#39;\935&#39;<br>
&gt; Prelude Data.Char&gt; putStrLn (&#39;\935&#39;:[])<br>
&gt; Χ<br>
&gt;<br>
&gt;<br>
&gt; ...which I suppose is the point. I wonder whether a version of<br>
&gt; toUpper/toLower on Char restricted to ASCII values would have the same<br>
&gt; performance here.<br>
&gt;<br>
&gt; We only call toLower explicitly in one place in snap-server, but where this<br>
&gt; would be nice to fix is for HTTP headers, where I think we are all using<br>
&gt; case-insensitive (which just calls &quot;map toLower&quot;). Probably we should send<br>
&gt; Bas a patch to optimize the FoldCase instance for ByteString.<br>
&gt;<br>
&gt; Personally I would prefer not to have yet another tiny package here, as the<br>
&gt; package zoo has enough creatures in it as it is. Do we think we have a real<br>
&gt; problem here beyond the toUpper/toLower case? I suspect that for most other<br>
&gt; uses of Data.ByteString.Char8 the conversion is a no-op.<br>
&gt;<br>
&gt; G<br>
&gt;<br>
&gt; On Thu, Sep 20, 2012 at 4:17 PM, Michael Snoyman &lt;<a href="mailto:michael@snoyman.com" target="_blank">michael@snoyman.com</a>&gt;<br>
&gt; wrote:<br>
&gt;&gt;<br>
&gt;&gt; On Thu, Sep 20, 2012 at 2:10 PM, Michael Snoyman &lt;<a href="mailto:michael@snoyman.com" target="_blank">michael@snoyman.com</a>&gt;<br>
&gt;&gt; wrote:<br>
&gt;&gt; &gt; On Thu, Sep 20, 2012 at 11:41 AM, Kazu Yamamoto &lt;<a href="mailto:kazu@iij.ad.jp" target="_blank">kazu@iij.ad.jp</a>&gt; wrote:<br>
&gt;&gt; &gt;&gt; Hello,<br>
&gt;&gt; &gt;&gt;<br>
&gt;&gt; &gt;&gt; ByteString is an array of Word8 but it seems to me that people tend to<br>
&gt;&gt; &gt;&gt; use the Char interface with Data.ByteString.Char8 instead of Word8<br>
&gt;&gt; &gt;&gt; interface with Data.ByteString. Since the functions defined in<br>
&gt;&gt; &gt;&gt; Data.ByteString.Char8 converts Word8 to Char and Char to Word8, it has<br>
&gt;&gt; &gt;&gt; unnecessary overhead. Yes, the overhead is ignorable in many cases,<br>
&gt;&gt; &gt;&gt; but I would like to remove it for high performance server.<br>
&gt;&gt; &gt;&gt;<br>
&gt;&gt; &gt;&gt; Why do people use Data.ByteString.Char8? I guess that there are two<br>
&gt;&gt; &gt;&gt; reasons:<br>
&gt;&gt; &gt;&gt;<br>
&gt;&gt; &gt;&gt; - There are no standard utility functions for Word8 such as &quot;isUpper&quot;<br>
&gt;&gt; &gt;&gt; - Numeric literal (e.g 72 for &#39;H&#39;) is not readable<br>
&gt;&gt; &gt;&gt;<br>
&gt;&gt; &gt;&gt; To fix these problems, I implemented the Data.Word8 module and<br>
&gt;&gt; &gt;&gt; uploaded the word8 library to Hackage:<br>
&gt;&gt; &gt;&gt;<br>
&gt;&gt; &gt;&gt;<br>
&gt;&gt; &gt;&gt; <a href="http://hackage.haskell.org/packages/archive/word8/0.0.0/doc/html/Data-Word8.html" target="_blank">http://hackage.haskell.org/packages/archive/word8/0.0.0/doc/html/Data-Word8.html</a><br>
&gt;&gt; &gt;&gt;<br>
&gt;&gt; &gt;&gt; If Michael and Bas like this, I would like to modify warp and<br>
&gt;&gt; &gt;&gt; case-insensitive to use the word8 library. What do people think this?<br>
&gt;&gt; &gt;&gt;<br>
&gt;&gt; &gt;&gt; My concern is that character names start with &quot;_&quot;. Some people would<br>
&gt;&gt; &gt;&gt; dislike this convention. But I have not a better idea at this moment.<br>
&gt;&gt; &gt;&gt; Suggestions are welcome.<br>
&gt;&gt; &gt;&gt;<br>
&gt;&gt; &gt;&gt; --Kazu<br>
&gt;&gt; &gt;&gt;<br>
&gt;&gt; &gt;&gt; _______________________________________________<br>
&gt;&gt; &gt;&gt; web-devel mailing list<br>
&gt;&gt; &gt;&gt; <a href="mailto:web-devel@haskell.org" target="_blank">web-devel@haskell.org</a><br>
&gt;&gt; &gt;&gt; <a href="http://www.haskell.org/mailman/listinfo/web-devel" target="_blank">http://www.haskell.org/mailman/listinfo/web-devel</a><br>
&gt;&gt; &gt;<br>
&gt;&gt; &gt; Sounds good to me. I put together a simple benchmark to compare the<br>
&gt;&gt; &gt; performance of toLower, and the results are encouraging:<br>
&gt;&gt; &gt;<br>
&gt;&gt; &gt; benchmarking Char8<br>
&gt;&gt; &gt; mean: 38.04527 us, lb 37.94080 us, ub 38.12774 us, ci 0.950<br>
&gt;&gt; &gt; std dev: 470.9770 ns, lb 364.8254 ns, ub 748.3015 ns, ci 0.950<br>
&gt;&gt; &gt;<br>
&gt;&gt; &gt; benchmarking Word8<br>
&gt;&gt; &gt; mean: 4.807265 us, lb 4.798199 us, ub 4.816563 us, ci 0.950<br>
&gt;&gt; &gt; std dev: 47.20958 ns, lb 41.51181 ns, ub 55.07049 ns, ci 0.950<br>
&gt;&gt; &gt;<br>
&gt;&gt; &gt; I want to try throwing one more idea into the mix, I&#39;ll post with<br>
&gt;&gt; &gt; updates when I have them.<br>
&gt;&gt; &gt;<br>
&gt;&gt; &gt; So to answer your question: I&#39;d be happy to include word8 in warp :).<br>
&gt;&gt; &gt;<br>
&gt;&gt; &gt; Michael<br>
&gt;&gt; &gt;<br>
&gt;&gt; &gt;<br>
&gt;&gt; &gt; {-# LANGUAGE OverloadedStrings #-}<br>
&gt;&gt; &gt; import Criterion.Main<br>
&gt;&gt; &gt; import qualified Data.ByteString as S<br>
&gt;&gt; &gt; import qualified Data.ByteString.Char8 as S8<br>
&gt;&gt; &gt; import qualified Data.Char<br>
&gt;&gt; &gt; import qualified Data.Word8<br>
&gt;&gt; &gt;<br>
&gt;&gt; &gt; main :: IO ()<br>
&gt;&gt; &gt; main = do<br>
&gt;&gt; &gt;     input &lt;- S.readFile &quot;bench.hs&quot;<br>
&gt;&gt; &gt;     defaultMain<br>
&gt;&gt; &gt;         [ bench &quot;Char8&quot; $ whnf (S.length . S8.map Data.Char.toLower)<br>
&gt;&gt; &gt; input<br>
&gt;&gt; &gt;         , bench &quot;Word8&quot; $ whnf (S.length . S.map Data.Word8.toLower)<br>
&gt;&gt; &gt; input<br>
&gt;&gt; &gt;         ]<br>
&gt;&gt;<br>
&gt;&gt; I tried implementing a more low-level approach to try and avoid the<br>
&gt;&gt; Word8 boxing. The results improved a bit, but not significantly:<br>
&gt;&gt;<br>
&gt;&gt;<br>
&gt;&gt; benchmarking Char8<br>
&gt;&gt; mean: 318.2341 us, lb 314.5367 us, ub 320.4834 us, ci 0.950<br>
&gt;&gt; std dev: 14.48230 us, lb 10.00946 us, ub 21.22126 us, ci 0.950<br>
&gt;&gt; found 9 outliers among 100 samples (9.0%)<br>
&gt;&gt;   8 (8.0%) low severe<br>
&gt;&gt; variance introduced by outliers: 43.472%<br>
&gt;&gt; variance is moderately inflated by outliers<br>
&gt;&gt;<br>
&gt;&gt; benchmarking Word8<br>
&gt;&gt; mean: 35.79037 us, lb 35.66547 us, ub 35.92601 us, ci 0.950<br>
&gt;&gt; std dev: 665.5299 ns, lb 599.3413 ns, ub 741.6474 ns, ci 0.950<br>
&gt;&gt; variance introduced by outliers: 11.349%<br>
&gt;&gt; variance is moderately inflated by outliers<br>
&gt;&gt;<br>
&gt;&gt; benchmarking bsToLower<br>
&gt;&gt; mean: 31.49299 us, lb 31.32314 us, ub 31.65027 us, ci 0.950<br>
&gt;&gt; std dev: 835.2251 ns, lb 744.4337 ns, ub 946.1789 ns, ci 0.950<br>
&gt;&gt; variance introduced by outliers: 20.925%<br>
&gt;&gt; variance is moderately inflated by outliers<br>
&gt;&gt;<br>
&gt;&gt; Perhaps someone with more experience with this level of optimization<br>
&gt;&gt; would be able to improve the algorithm:<br>
&gt;&gt;<br>
&gt;&gt; <a href="https://gist.github.com/3756212" target="_blank">https://gist.github.com/3756212</a><br>
&gt;&gt;<br>
&gt;&gt; Michael<br>
&gt;&gt;<br>
&gt;&gt; _______________________________________________<br>
&gt;&gt; web-devel mailing list<br>
&gt;&gt; <a href="mailto:web-devel@haskell.org" target="_blank">web-devel@haskell.org</a><br>
&gt;&gt; <a href="http://www.haskell.org/mailman/listinfo/web-devel" target="_blank">http://www.haskell.org/mailman/listinfo/web-devel</a><br>
&gt;<br>
&gt;<br>
&gt;<br>
&gt;<br>
&gt; --<br>
&gt; Gregory Collins &lt;<a href="mailto:greg@gregorycollins.net" target="_blank">greg@gregorycollins.net</a>&gt;<br>
</div></div></blockquote></div><br><br clear="all"><div><br></div></div></div><span class="HOEnZb"><font color="#888888">-- <br>Gregory Collins &lt;<a href="mailto:greg@gregorycollins.net" target="_blank">greg@gregorycollins.net</a>&gt;</font></span></div>

</blockquote></div><div><br></div>Hmm... I don&#39;t get your results.<div><br></div><div><div>benchmarking Char8</div><div>mean: 394.2475 us, lb 393.1611 us, ub 395.3824 us, ci 0.950</div><div>std dev: 5.674103 us, lb 4.574321 us, ub 7.548278 us, ci 0.950</div>

<div>found 16 outliers among 100 samples (16.0%)</div><div>  1 (1.0%) low severe</div><div>  4 (4.0%) low mild</div><div>  6 (6.0%) high mild</div><div>  5 (5.0%) high severe</div><div>variance introduced by outliers: 7.517%</div>

<div>variance is slightly inflated by outliers</div><div><br></div><div>benchmarking Char8 toLowerC</div><div>mean: 81.19748 us, lb 80.95403 us, ub 81.40814 us, ci 0.950</div><div>std dev: 1.154865 us, lb 977.5925 ns, ub 1.497224 us, ci 0.950</div>

<div>found 2 outliers among 100 samples (2.0%)</div><div>  1 (1.0%) low severe</div><div>variance introduced by outliers: 7.506%</div><div>variance is slightly inflated by outliers</div><div><br></div><div>benchmarking Word8</div>

<div>mean: 43.01692 us, lb 42.94030 us, ub 43.09647 us, ci 0.950</div><div>std dev: 401.2451 ns, lb 362.3989 ns, ub 458.7243 ns, ci 0.950</div><div><br></div><div>benchmarking bsToLower</div><div>mean: 36.61481 us, lb 36.46137 us, ub 36.79378 us, ci 0.950</div>

<div>std dev: 850.7579 ns, lb 717.1316 ns, ub 1.004895 us, ci 0.950</div><div>found 16 outliers among 100 samples (16.0%)</div><div>  2 (2.0%) low mild</div><div>  10 (10.0%) high mild</div><div>  4 (4.0%) high severe</div>

<div>variance introduced by outliers: 17.062%</div><div>variance is moderately inflated by outliers</div></div><div><br></div><div>I&#39;m compiling with -O2 and running on 7.4.1, 64-bit Linux. I&#39;m uncertain what would lead to such a significant difference in our runtimes. Any chance you can include Word8 in your run?</div>

<div><br></div><div>Michael</div></div>