Skip to content

Instantly share code, notes, and snippets.

@NicolasT
Last active October 15, 2015 23:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save NicolasT/ccc4946478bf33d27f5f to your computer and use it in GitHub Desktop.
Save NicolasT/ccc4946478bf33d27f5f to your computer and use it in GitHub Desktop.
CRC32 benchmark
*.o
*.hi
crc32_bench
#include <smmintrin.h>
unsigned int crc32_intel(const unsigned int crc, const void * const data, size_t len) {
size_t todo = len;
const unsigned long long *ull = data;
unsigned long long ullresult = crc;
while(todo >= sizeof(unsigned long long)) {
ullresult = _mm_crc32_u64(ullresult, *ull);
ull++;
todo -= sizeof(unsigned long long);
}
unsigned int result = ullresult;
const unsigned int *ui = data + (len - todo);
while(todo >= sizeof(unsigned int)) {
result = _mm_crc32_u32(result, *ui);
ui++;
todo -= sizeof(unsigned int);
}
const unsigned short *us = data + (len - todo);
while(todo >= sizeof(unsigned short)) {
result = _mm_crc32_u16(result, *us);
us++;
todo -= sizeof(unsigned short);
}
const unsigned char *uc = data + (len - todo);
while(todo >= sizeof(unsigned char)) {
result = _mm_crc32_u8(result, *uc);
uc++;
todo -= sizeof(unsigned char);
}
return result;
}
module Main (main) where
import Data.Word (Word32)
import Foreign.C (CChar, CInt(..), CULong(..))
import Foreign.Ptr (Ptr)
import System.IO.Unsafe (unsafePerformIO)
import Data.ByteString (ByteString)
import qualified Data.ByteString as BS
import Criterion.Main
foreign import ccall unsafe "zlib.h crc32" c_crc32_zlib :: CULong -> Ptr a -> CInt -> CULong
foreign import ccall unsafe "crc32_intel" c_crc32_intel :: CULong -> Ptr a -> CInt -> CULong
runBench :: (CULong -> Ptr CChar -> CInt -> CULong) -> ByteString -> Word32
runBench fn bs = unsafePerformIO go
where
go = BS.useAsCStringLen bs $ \(ptr, len) ->
pure $ fromIntegral $ fn 0 ptr (fromIntegral len)
main :: IO ()
main = defaultMain [
bgroup "crc32 1M" [ bench "zlib" $ nf (runBench c_crc32_zlib) bs1M
, bench "intel" $ nf (runBench c_crc32_intel) bs1M
]
]
where
bs1M = BS.pack $ take (1024 * 1024) $ cycle [minBound .. maxBound]
BIN = crc32_bench
OBJ = crc32.o crc32_bench.o
HI = crc32_bench.hi
default: $(BIN)
%.o: %.c
$(CC) -O3 -mavx -Wall -Werror -c -o $@ $<
crc32_bench: crc32.o crc32_bench.hs
stack ghc -- --make -O2 -lz -o $@ $^
clean:
rm -f $(OBJ)
rm -f $(HI)
rm -f $(BIN)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment