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) |