ForeignPtr reloaded
Donald Bruce Stewart
dons at cse.unsw.edu.au
Sun Jun 4 22:20:13 EDT 2006
duncan.coutts:
> 3: strict ByteString version, more like the original elegant pipeline
> version, quite quick.
>
> time: 0.36s
>
> import qualified Data.ByteString.Char8 as B
>
> main = print . foldl (\n l -> n + B.readInt l) 0 . B.lines =<< B.getContents
>
> 5: C version, very quick, reuses a fixed size buffer (which is possibly
> cheating as the Haskell versions will allow any line length).
>
> time: 0.15s
>
> #include <stdio.h>
> #include <stdlib.h>
>
> #define MAXLINELEN 128
>
> int
> main() {
> int sum = 0;
> char line[MAXLINELEN];
>
> while (fgets(line, MAXLINELEN, stdin)) {
> sum += atoi(line);
> }
> printf("%d\n", sum);
> return(0);
> }
>
> So our fastest version is similar code to the original naive version and
> is only half the speed of the C version.
Which is a nice result for a one liner. In fact, we can do faster still ..
here's an (ugly, unfortunately) sum.hs in the fps tests/ dir is around 3x
faster than the optimised C version. The C program is hampered by atoi being
quite slow.
{-# OPTIONS -cpp #-}
import qualified Data.ByteString as B
import Data.ByteString.Base (ByteString,unsafeTail,unsafeIndex)
import Data.Char -- seems to help!
main = print . go 0 =<< B.getContents
--
-- A faster atoi
--
#define STRICT2(f) f a b | a `seq` b `seq` False = undefined
STRICT2(go)
go i ps
| B.null ps = i
| x == 45 = neg 0 xs
| otherwise = pos (parse x) xs
where
(x, xs) = (ps `unsafeIndex` 0, unsafeTail ps)
STRICT2(neg)
neg n qs | x == 10 = go (i-n) xs
| otherwise = neg (parse x + (10 * n)) xs
where (x, xs) = (qs `unsafeIndex` 0, unsafeTail qs)
STRICT2(pos)
pos n qs | x == 10 = go (i+n) xs
| otherwise = pos (parse x + (10 * n)) xs
where (x, xs) = (qs `unsafeIndex` 0, unsafeTail qs)
parse w = fromIntegral (w - 48) :: Int
{-# INLINE parse #-}
Comparing the running times:
GCC -O2
$ time ./c < /home/dons/src/shootout/sum/in
1280000
./c < /home/dons/src/shootout/sum/in 0.67s user 0.02s system 99% cpu 0.692 total
GHC -O2
$ time ./sum < /home/dons/src/shootout/sum/in
1280000
./sum < /home/dons/src/shootout/sum/in 0.18s user 0.05s system 92% cpu 0.254 total
-- Don
More information about the Cvs-ghc
mailing list