[Haskell-cafe] Performance and STUArrays
Dominic Steinitz
dominic.steinitz at blueyonder.co.uk
Sun Apr 22 09:06:00 EDT 2007
I've been playing around some more trying improve the performance of the SHA1
implmentation in the crypto library. I've isolated one of the functions and
implemented it using
a) unfold
and
b) STUArray
The STUArray implementation is about twice as fast but I was expecting an
order of magnitude improvement given I thought I would have been allocating
16 x 80 new 32 bit words with unfold but nothing with the STUArray.
Should I have been disappointed?
dom at heisenberg:~/sha12> time ./arrTest 17 STUArray > /dev/null
real 0m11.102s
user 0m9.129s
sys 0m0.112s
dom at heisenberg:~/sha12> time ./arrTest 17 Unfold > /dev/null
real 0m18.381s
user 0m16.361s
sys 0m0.212s
Dominic.
import Data.Bits
import Data.List
import Data.Word
import Control.Monad.ST
import Data.Array.ST
import System
import System.IO
data Word160 = Word160 !Word32 !Word32 !Word32 !Word32 !Word32
deriving (Eq, Show)
ss :: Word160
ss = Word160 0x67452301 0xefcdab89 0x98badcfe 0x10325476 0xc3d2e1f0
test :: [Word32]
test = [0x61626380, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000018]
tests :: Int -> [[Word32]]
tests n = map (\n -> n:[0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x18]) [1..2^n]
rotL :: Bits b => Int -> b -> b
rotL = flip rotateL
v1 :: a -> [Word32] -> [Word32]
v1 ss xs = take 80 (n xs)
where
h [w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14, w15]
=
Just (w0,[w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13,
w14, w15, (rotL 1 (w0 `xor` w2 `xor` w8 `xor` w13))])
n = unfoldr h
v2 ss xs = vs
where
us =
do w <- newArray (0,79) 0 :: ST s (STUArray s Int Word32)
let initLoop 15 = writeArray w 15 (xs!!15)
initLoop n =
do writeArray w n (xs!!n)
initLoop (n+1)
mainLoop 79 = nextW 79
mainLoop n =
do nextW n
mainLoop (n+1)
nextW n =
do wm16 <- readArray w (n-16)
wm14 <- readArray w (n-14)
wm8 <- readArray w (n-8)
wm3 <- readArray w (n-3)
writeArray w n (rotL 1 (wm3 `xor` wm8 `xor` wm14 `xor`
wm16))
initLoop 0
mainLoop 16
getElems w
vs = runST us
test1 n = map (v1 ss) (tests n)
test2 n = map (v2 ss) (tests n)
data TestType = Unfold | STUArray
deriving (Eq, Read, Show)
main =
do progName <- getProgName
args <- getArgs
if length args /= 2
then putStrLn ("Usage: " ++ progName ++ " <testSize> <testType>")
else do let n = read (args!!0)
t = read (args!!1)
if t == Unfold
then putStrLn (show (test1 n))
else putStrLn (show (test2 n))
More information about the Haskell-Cafe
mailing list