[Haskell-cafe] my take at knucleotide

Gregory Collins greg at gregorycollins.net
Sun Mar 24 20:12:57 CET 2013


What happens to performance if you compile and link with "cabal install
--constraint='hashable < 1.2'" ?

G


On Sun, Mar 24, 2013 at 4:08 PM, Branimir Maksimovic <bmaxa at hotmail.com>wrote:

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


-- 
Gregory Collins <greg at gregorycollins.net>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.haskell.org/pipermail/haskell-cafe/attachments/20130324/48a46911/attachment.htm>


More information about the Haskell-Cafe mailing list