<html>
<head>
<style><!--
.hmmessage P
{
margin:0px;
padding:0px
}
body.hmmessage
{
font-size: 12pt;
font-family:Calibri
}
--></style></head>
<body class='hmmessage'><div dir='ltr'>Hi, I have tried to implement knucleotide benchmark program this time:<div><a href="http://benchmarksgame.alioth.debian.org/u64q/performance.php?test=knucleotide">http://benchmarksgame.alioth.debian.org/u64q/performance.php?test=knucleotide</a></div><div><br></div><div>Implementation is shorter (uses hashtable from hashtables package),</div><div>but two time slower then current Haskell entry ( which is too low level</div><div>for my taste :)).</div><div>What is&nbsp;interesting&nbsp;is that if I try to place Int64 as a key to</div><div>hash table, performance is even slower.</div><div>Strange that dropping and taking from bytestring would be</div><div>faster than packing string in 64 bit int and directly indexing.</div><div><br></div><div>If someone can see something that can bring performance on par</div><div>with current haskell entry , I would post it , otherwise no point,</div><div>except that program is shorter and not low level.</div><div><br></div><div><div>{-# Language BangPatterns #-}</div><div>--</div><div>-- The Computer Language Benchmarks Game</div><div>-- http://benchmarksgame.alioth.debian.org/</div><div>--</div><div>-- Contributed by Branimir Maksimovic</div><div>--</div><div>import Data.Char</div><div>import Data.List</div><div>import Data.IORef</div><div>import qualified Data.HashTable.IO as H</div><div>import qualified Data.ByteString.Char8 as S</div><div>import Control.Concurrent</div><div>import Text.Printf</div><div><br></div><div>main = do</div><div>&nbsp; &nbsp; s &lt;- S.getContents</div><div>&nbsp; &nbsp; let content = (S.map toUpper . S.concat . tail .</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; dropWhile (\l-&gt;not $ S.isPrefixOf (S.pack "&gt;THREE") l) .</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; S.lines) s</div><div>&nbsp; &nbsp; mapM_ (execute content) actions</div><div><br></div><div>data Actions = I Int | S String</div><div>actions = [I 1,I 2,</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;S "GGT",S "GGTA",S "GGTATT",S "GGTATTTTAATT",S "GGTATTTTAATTTATAGT"]</div><div>execute content (I i) = writeFrequencies content i</div><div>execute content (S s) = writeCount content s</div><div><br></div><div>writeFrequencies input size = do</div><div>&nbsp; &nbsp; ht &lt;- tcalculate input size</div><div>&nbsp; &nbsp; lst &lt;- H.foldM (\lst (k,v)-&gt;do&nbsp;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; v' &lt;- readIORef v</div><div>&nbsp; &nbsp; &nbsp; &nbsp; return $ insertBy (\(_,x) (_,y)-&gt;y `compare` x) (k,v') lst) [] ht</div><div>&nbsp; &nbsp; let sum = fromIntegral ((S.length input) + 1 - size)</div><div>&nbsp; &nbsp; mapM_ (\(k,v)-&gt; do</div><div>&nbsp; &nbsp; &nbsp; &nbsp; printf "%s %.3f\n"&nbsp;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; (S.unpack k) ((100 * (fromIntegral v)/sum)::Double)) lst</div><div>&nbsp; &nbsp; putChar '\n'</div><div><br></div><div>writeCount input string = do</div><div>&nbsp; &nbsp; let size = length string</div><div>&nbsp; &nbsp; ht &lt;- tcalculate input size</div><div>&nbsp; &nbsp; res &lt;- H.lookup ht (S.pack string)</div><div>&nbsp; &nbsp; case res of&nbsp;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; Nothing -&gt; putStrLn $ string ++ " not found..."</div><div>&nbsp; &nbsp; &nbsp; &nbsp; Just v -&gt; do</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; r &lt;- readIORef v</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; printf "%d\t%s\n" r (string::String)</div><div><br></div><div>tcalculate input size = do</div><div>&nbsp; &nbsp; let&nbsp;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; l = [0..7]</div><div>&nbsp; &nbsp; &nbsp; &nbsp; actions = map (\i -&gt; (calculate input i size (length l))) l</div><div>&nbsp; &nbsp; vars &lt;- mapM (\action -&gt; do</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var &lt;- newEmptyMVar</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; forkIO $ do</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; answer &lt;- action</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; putMVar var answer</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return var) actions</div><div>&nbsp; &nbsp; result &lt;- newTable</div><div>&nbsp; &nbsp; results &lt;- mapM takeMVar vars</div><div>&nbsp; &nbsp; mapM_ (\ht -&gt; H.foldM (\lst (k,v) -&gt; do&nbsp;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; res &lt;- H.lookup lst k</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; case res of</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Nothing -&gt; do</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; r1 &lt;- readIORef v</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; r2 &lt;- newIORef r1</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; H.insert lst k r2</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Just v1 -&gt; do</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; r1 &lt;- readIORef v1</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; r2 &lt;- readIORef v</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; writeIORef v1 (r1+r2)</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return lst) result ht) results</div><div>&nbsp; &nbsp; return result</div><div>&nbsp; &nbsp;&nbsp;</div><div>calculate input beg size incr = do</div><div>&nbsp; &nbsp; ht &lt;- newTable</div><div>&nbsp; &nbsp; let</div><div>&nbsp; &nbsp; &nbsp; &nbsp; calculate' :: S.ByteString -&gt; Int -&gt; IO HashTable</div><div>&nbsp; &nbsp; &nbsp; &nbsp; calculate' str i&nbsp;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;| i &gt;= ((S.length input)+1 - size) = return ht</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;| otherwise = do</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; res &lt;- H.lookup ht k</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; case res of</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Nothing -&gt; do</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; !r &lt;- newIORef 1</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; H.insert ht k r</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Just v -&gt; do</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; !r &lt;- readIORef v</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; writeIORef v (r+1)</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; calculate' (S.drop incr str) (i+incr)</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; where k = S.take size str</div><div>&nbsp; &nbsp; calculate' (S.drop beg input) beg</div><div><br></div><div>type HashTable = H.BasicHashTable S.ByteString (IORef Int)&nbsp;</div><div>newTable :: IO HashTable</div><div>newTable = H.new</div></div><div><br></div>                                               </div></body>
</html>