To compile and run:
# Get Haskell/Cabal
cabal update && cabal install criterion
gcc -c -O3 Lib.c
ghc Main.hs Lib.o
./Main
| #include <stddef.h> | |
| // From http://clc-wiki.net/wiki/strchr | |
| char *strchr_c(const char *s, int c) | |
| { | |
| while (*s != (char)c) | |
| if (!*s++) | |
| return 0; | |
| return (char *)s; | |
| } | |
| // From http://clc-wiki.net/wiki/memchr | |
| void *memchr_c(const void *s, int c, size_t n) | |
| { | |
| unsigned char *p = (unsigned char*)s; | |
| while( n-- ) | |
| if( *p != (unsigned char)c ) | |
| p++; | |
| else | |
| return p; | |
| return 0; | |
| } |
| import qualified Data.ByteString as BS | |
| import qualified Data.ByteString.Unsafe as BS | |
| import Criterion.Main | |
| import Foreign | |
| import Foreign.C.Types | |
| import System.IO.Unsafe | |
| import Data.Monoid | |
| foreign import ccall unsafe "string.h memchr" memchr_std :: Ptr Word8 -> CInt -> CSize -> IO (Ptr Word8) | |
| foreign import ccall unsafe "string.h strchr" strchr_std :: Ptr Word8 -> CInt -> IO (Ptr Word8) | |
| foreign import ccall unsafe memchr_c :: Ptr Word8 -> CInt -> CSize -> IO (Ptr Word8) | |
| foreign import ccall unsafe strchr_c :: Ptr Word8 -> CInt -> IO (Ptr Word8) | |
| ignoreSize f a b _ = f a b | |
| cstr i = BS.replicate i 32 <> BS.singleton 64 <> BS.replicate i 32 <> BS.singleton 0 | |
| funs = | |
| [("memchr_std", memchr_std) | |
| ,("strchr_std", ignoreSize strchr_std) | |
| ,("memchr_c", memchr_c) | |
| ,("strchr_c", ignoreSize strchr_c)] | |
| main = defaultMain | |
| [ seq bs $ bench (show i ++ " " ++ name) $ whnfIO $ test fun bs | |
| | i <- [1,10,100,1000,10000,100000,1000000,10000000] | |
| , let bs = cstr i | |
| , (name, fun) <- funs] | |
| {-# NOINLINE test #-} | |
| test fun bs = | |
| BS.unsafeUseAsCStringLen bs $ \(ptr,len) -> | |
| fun (castPtr ptr) 64 (fromIntegral len) |