[Haskell-cafe] [1/16] SBM: The Haskell and C benchmarks

Peter Firefly Brodersen Lund firefly at vax64.dk
Sat Dec 22 04:16:54 EST 2007


Here are the 48 Haskell and C benchmarks.

Don Stewart contributed three (although I had to fight a bit to make one of
them compile).  
Jules Bean (quicksilver) contributed one.
Bertram Felgenhauer (int-e) contributed three (in the form of a single file,
which I untangled).
Spencer Jannsen (sjannsen) contributed one.

wli (William Lee Irwin III) inspired me to add the getwchar benchmarks.

I used the following shell code to gather all the benchmarks:

 (for F in hs/*.hs c/*.c; \
        do echo "------------------------------"; \
           echo "$F:";                            \
           echo ;                                 \
           cat "$F";                              \
        done; \
           echo "=============================="  \
 ) > xx.txt

They are not in the same order as in the Makefile or in the reports,
unfortunately.

-Peter

------------------------------
hs/byte-bs----acc.hs:

{-# LANGUAGE BangPatterns #-}

import qualified Data.ByteString as B

cnt	:: Int -> B.ByteString -> Int
cnt !acc !bs = if B.null bs
		 then acc
	         else cnt (acc+1) (B.tail bs)

main = do s <- B.getContents
	  print (cnt 0 s)
------------------------------
hs/byte-bs----foldlx.hs:

{-# LANGUAGE BangPatterns #-}

import qualified Data.ByteString as B

cnt	:: B.ByteString -> Int
cnt !bs	= B.foldl' (\sum _ -> sum+1) 0 bs

main = do s <- B.getContents
	  print (cnt s)
------------------------------
hs/byte-bs----foldrx.hs:

{-# LANGUAGE BangPatterns #-}

import qualified Data.ByteString as B

cnt	:: B.ByteString -> Int
cnt !bs	= B.foldr' (\_ sum -> sum+1) 0 bs

main = do s <- B.getContents
	  print (cnt s)
------------------------------
hs/byte-bsl---acc.hs:

{-# LANGUAGE BangPatterns #-}

import qualified Data.ByteString.Lazy as B

cnt	:: Int -> B.ByteString -> Int
cnt !acc !bs = if B.null bs
		 then acc
	         else cnt (acc+1) (B.tail bs)

main = do s <- B.getContents
	  print (cnt 0 s)
------------------------------
hs/byte-xxxxx-acc-1.hs:

{-# LANGUAGE BangPatterns #-}

cnt	:: Int -> String -> Int
cnt !acc bs = if null bs
		 then acc
	         else cnt (acc+1) (tail bs)

main = do s <- getContents
	  print (cnt 0 s)
------------------------------
hs/byte-xxxxx-acc-2.hs:

{-# LANGUAGE BangPatterns #-}

cnt	:: Int -> String -> Int
cnt !acc !bs = if null bs
		 then acc
	         else cnt (acc+1) (tail bs)

main = do s <- getContents
	  print (cnt 0 s)
------------------------------
hs/byte-xxxxx-foldl.hs:

{-# LANGUAGE BangPatterns #-}

cnt	:: String -> Int
cnt !bs	= foldl (\sum _ -> sum+1) 0 bs

main = do s <- getContents
	  print (cnt s)
------------------------------
hs/byte-xxxxx-foldr-1.hs:

{-# LANGUAGE BangPatterns #-}

cnt	:: String -> Int
cnt bs	= foldr (\_ sum -> sum+1) 0 bs

main = do s <- getContents
	  print (cnt s)
------------------------------
hs/byte-xxxxx-foldr-2.hs:

{-# LANGUAGE BangPatterns #-}

cnt	:: String -> Int
cnt !bs	= foldr (\_ sum -> sum+1) 0 bs

main = do s <- getContents
	  print (cnt s)
------------------------------
hs/space-bs-c8-acc-1.hs:

{-# LANGUAGE BangPatterns #-}

import qualified Data.ByteString.Char8 as B

cnt	:: Int -> B.ByteString -> Int
cnt !acc bs = if B.null bs
		then acc
	        else cnt (if B.head bs == ' ' then acc+1 else acc) (B.tail bs)

main = do s <- B.getContents
	  print (cnt 0 s)
------------------------------
hs/space-bs-c8-count.hs:

-- Don Stewart
import qualified Data.ByteString.Char8 as B
main = print . B.count ' ' =<< B.getContents

------------------------------
hs/space-bs-c8-foldlx-1.hs:

{-# LANGUAGE BangPatterns #-}

import qualified Data.ByteString.Char8 as B

cnt	:: B.ByteString -> Int
cnt bs	= B.foldl' (\sum c -> if c == ' ' then sum+1 else sum) 0 bs

main = do s <- B.getContents
	  print (cnt s)
------------------------------
hs/space-bs-c8-foldlx-2.hs:

{-# LANGUAGE BangPatterns #-}

import qualified Data.ByteString.Char8 as B

main = do s <- B.getContents
	  print $ B.foldl' (\v c -> if c == ' ' then v+1 else v :: Int) 0 s

------------------------------
hs/space-bs-c8-foldrx.hs:

{-# LANGUAGE BangPatterns #-}

import qualified Data.ByteString.Char8 as B

cnt	:: B.ByteString -> Int
cnt bs	= B.foldr' (\c sum -> if c == ' ' then sum+1 else sum) 0 bs

main = do s <- B.getContents
	  print (cnt s)
------------------------------
hs/space-bs-c8-lenfil.hs:

{-# LANGUAGE BangPatterns #-}

import qualified Data.ByteString.Char8 as B

cnt	:: B.ByteString -> Int
cnt bs	= B.length (B.filter (== ' ') bs)

main = do s <- B.getContents
	  print (cnt s)
------------------------------
hs/space-bslc8-acc-1.hs:

{-# LANGUAGE BangPatterns #-}

import qualified Data.ByteString.Lazy.Char8 as B

cnt	:: Int -> B.ByteString -> Int
cnt !acc bs = if B.null bs
		then acc
	        else cnt (if B.head bs == ' ' then acc+1 else acc) (B.tail bs)

main = do s <- B.getContents
	  print (cnt 0 s)
------------------------------
hs/space-bslc8-acc-2.hs:

{-# LANGUAGE BangPatterns #-}

import qualified Data.ByteString.Lazy.Char8 as B

cnt	:: Int -> B.ByteString -> Int
cnt !acc !bs = if B.null bs
		then acc
	        else cnt (if B.head bs == ' ' then acc+1 else acc) (B.tail bs)

main = do s <- B.getContents
	  print (cnt 0 s)
------------------------------
hs/space-bslc8-acc-3.hs:

{-# LANGUAGE BangPatterns #-}
 -- this version by quicksilver

import qualified Data.ByteString.Lazy.Char8 as B

cnt	:: Int -> B.ByteString -> Int
cnt !acc bs | B.null bs        = acc
	    | B.head bs == ' ' = cnt (acc+1) (B.tail bs)
	    | otherwise        = cnt acc (B.tail bs)

main = do s <- B.getContents
	  print (cnt 0 s)

------------------------------
hs/space-bslc8-chunk-1.hs:

{-# LANGUAGE BangPatterns #-}
 -- this version by int-e

import qualified Data.ByteString.Lazy.Char8 as B
import qualified Data.ByteString.Char8 as BS
import Data.List (foldl')

cntS    :: Int -> BS.ByteString -> Int
cntS !acc !bs = case BS.uncons bs of
                    Nothing -> acc
                    Just (hd, tl) | hd == ' ' -> cntS (acc+1) tl
                                  | otherwise -> cntS acc tl

cnt     :: Int -> B.ByteString -> Int
cnt acc bs = foldl' cntS acc (B.toChunks bs)

main = do s <- B.getContents
          print $ cnt 0 s

------------------------------
hs/space-bslc8-chunk-2.hs:

{-# LANGUAGE BangPatterns #-}
 -- this version by int-e

import qualified Data.ByteString.Lazy.Char8 as B
import qualified Data.ByteString.Char8 as BS
import Data.List (foldl')

cntS'   :: Int -> BS.ByteString -> Int
cntS' !acc !bs | BS.null bs        = acc
               | BS.head bs == ' ' = cntS' (acc+1) (BS.tail bs)
               | otherwise         = cntS' acc (BS.tail bs)

cnt     :: Int -> B.ByteString -> Int
cnt acc bs = foldl' cntS' acc (B.toChunks bs)

main = do s <- B.getContents
          print $ cnt 0 s

------------------------------
hs/space-bslc8-chunk-3.hs:

{-# LANGUAGE BangPatterns #-}
 -- this version by int-e

import qualified Data.ByteString.Lazy.Char8 as B
import qualified Data.ByteString.Char8 as BS
import Data.List (foldl')

cntS''   :: Int -> BS.ByteString -> Int
cntS'' !acc !bs = BS.foldl' (\v c -> if c == ' ' then v+1 else v) acc bs

cnt     :: Int -> B.ByteString -> Int
cnt acc bs = foldl' cntS'' acc (B.toChunks bs)

main = do s <- B.getContents
          print $ cnt 0 s

------------------------------
hs/space-bslc8-chunk-4.hs:

{-# LANGUAGE BangPatterns #-}

-- Don Stewart
import qualified Data.ByteString.Lazy.Char8    as BLC8
import qualified Data.ByteString.Lazy.Internal as BLI
import qualified Data.ByteString               as B
import qualified Data.ByteString.Unsafe        as BU
import qualified Data.ByteString.Internal      as BI

cnt :: Int -> BLC8.ByteString -> Int
cnt n BLI.Empty        = n
cnt n (BLI.Chunk x xs) = cnt (n + cnt_strict 0 x) xs  -- process lazy spine
    where     -- now we can process a chunk without checking for Empty
        cnt_strict !i !s                          -- then strict chunk 
            | B.null s  = i
            | c == ' '  = cnt_strict (i+1) t
            | otherwise = cnt_strict i     t
          where
            (c,t) = (BI.w2c (BU.unsafeHead s), BU.unsafeTail s) -- no bounds check

main = do s <- BLC8.getContents; print (cnt 0 s)

------------------------------
hs/space-bslc8-count.hs:

-- Don Stewart
import qualified Data.ByteString.Lazy.Char8 as B
main = print . B.count ' ' =<< B.getContents

------------------------------
hs/space-bslc8-foldl.hs:

{-# LANGUAGE BangPatterns #-}

import qualified Data.ByteString.Lazy.Char8 as B

cnt	:: B.ByteString -> Int
cnt !bs	= B.foldl (\sum c -> if c == ' ' then sum+1 else sum) 0 bs

main = do s <- B.getContents
	  print (cnt s)
------------------------------
hs/space-bslc8-foldlx-1.hs:

{-# LANGUAGE BangPatterns #-}

import qualified Data.ByteString.Lazy.Char8 as B

cnt	:: B.ByteString -> Int
cnt bs	= B.foldl' (\sum c -> if c == ' ' then sum+1 else sum) 0 bs

main = do s <- B.getContents
	  print (cnt s)
------------------------------
hs/space-bslc8-foldlx-2.hs:

{-# LANGUAGE BangPatterns #-}

import qualified Data.ByteString.Lazy.Char8 as B

cnt	:: B.ByteString -> Int
cnt !bs	= B.foldl' (\sum c -> if c == ' ' then sum+1 else sum) 0 bs

main = do s <- B.getContents
	  print (cnt s)
------------------------------
hs/space-bslc8-foldr-1.hs:

{-# LANGUAGE BangPatterns #-}

import qualified Data.ByteString.Lazy.Char8 as B

cnt	:: B.ByteString -> Int
cnt bs	= B.foldr (\c sum -> if c == ' ' then sum+1 else sum) 0 bs

main = do s <- B.getContents
	  print (cnt s)
------------------------------
hs/space-bslc8-foldr-2.hs:

{-# LANGUAGE BangPatterns #-}

import qualified Data.ByteString.Lazy.Char8 as B

cnt	:: B.ByteString -> Int
cnt !bs	= B.foldr (\c sum -> if c == ' ' then sum+1 else sum) 0 bs

main = do s <- B.getContents
	  print (cnt s)
------------------------------
hs/space-bslc8-lenfil-1.hs:

{-# LANGUAGE BangPatterns #-}

import qualified Data.ByteString.Lazy.Char8 as B
import GHC.Int (Int64)

-- note that D.BS.Lazy.Char8.length is ByteString -> Int64
--           D.BS.C8.length is ByteString -> Int
cnt	:: B.ByteString -> Int64
cnt bs	= B.length (B.filter (== ' ') bs)

main = do s <- B.getContents
	  print (cnt s)
------------------------------
hs/space-bslc8-lenfil-2.hs:

{-# LANGUAGE BangPatterns #-}

import qualified Data.ByteString.Lazy.Char8 as B
import GHC.Int (Int64)

-- note that D.BS.Lazy.Char8.length is ByteString -> Int64
--           D.BS.C8.length is ByteString -> Int
cnt	:: B.ByteString -> Int64
cnt !bs	= B.length (B.filter (== ' ') bs)

main = do s <- B.getContents
	  print (cnt s)
------------------------------
hs/space-bsl---foldlx.hs:

{-# LANGUAGE BangPatterns #-}
 -- this version by sjannsen

import Data.ByteString.Lazy as B

cnt :: B.ByteString -> Int
cnt = B.foldl' f 0
 where
    f !n 32   = n+1
    f !n  _   = n

main = do
    s <- B.getContents
    print $ cnt s

------------------------------
hs/space-xxxxx-acc-1.hs:

{-# LANGUAGE BangPatterns #-}

cnt	:: Int -> String -> Int
cnt !acc bs = if null bs
		then acc
	        else cnt (if head bs == ' ' then acc+1 else acc) (tail bs)

main = do s <- getContents
	  print (cnt 0 s)
------------------------------
hs/space-xxxxx-acc-2.hs:

{-# LANGUAGE BangPatterns #-}

cnt	:: Int -> String -> Int
cnt !acc !bs = if null bs
		then acc
	        else cnt (if head bs == ' ' then acc+1 else acc) (tail bs)

main = do s <- getContents
	  print (cnt 0 s)
------------------------------
hs/space-xxxxx-foldl.hs:

{-# LANGUAGE BangPatterns #-}

cnt	:: String -> Int
cnt bs	= foldl (\sum c -> if c == ' ' then sum+1 else sum) 0 bs

main = do s <- getContents
	  print (cnt s)
------------------------------
hs/space-xxxxx-foldr-1.hs:

{-# LANGUAGE BangPatterns #-}

cnt	:: String -> Int
cnt bs	= foldr (\c sum -> if c == ' ' then sum+1 else sum) 0 bs

main = do s <- getContents
	  print (cnt s)
------------------------------
hs/space-xxxxx-foldr-2.hs:

{-# LANGUAGE BangPatterns #-}

cnt	:: String -> Int
cnt !bs	= foldr (\c sum -> if c == ' ' then sum+1 else sum) 0 bs

main = do s <- getContents
	  print (cnt s)
------------------------------
hs/space-xxxxx-lenfil.hs:

{-# LANGUAGE BangPatterns #-}

cnt	:: String -> Int
cnt bs	= length (filter (== ' ') bs)

main = do s <- getContents
	  print (cnt s)
------------------------------
c/byte-4k.c:

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>

int Main_cnt()
{
	int	cnt = 0;
	ssize_t	sze;
	char	buf[4*1024];

	do {
	again:
		sze = read(fileno(stdin), buf, sizeof(buf));
		if (sze < 0) {
			switch (errno) {
			case EAGAIN: goto again;
			default:
				perror("read() failed\n");
				exit(1);
			}
		}

		cnt += sze;
	} while (sze != 0);

	return cnt;
}


int main()
{
	printf("%d\n", Main_cnt());
	return EXIT_SUCCESS;
}

------------------------------
c/byte-getchar.c:

#include <stdio.h>
#include <stdlib.h>

int Main_cnt()
{
	int	cnt = 0;
	int	c;

	while ((c = getchar()) != EOF)
		cnt++;

	return cnt;
}


int main()
{
	printf("%d\n", Main_cnt());
	return EXIT_SUCCESS;
}

------------------------------
c/byte-getchar-u.c:

#include <stdio.h>
#include <stdlib.h>

int Main_cnt()
{
	int	cnt = 0;
	int	c;

	while ((c = getchar_unlocked()) != EOF)
		cnt++;

	return cnt;
}


int main()
{
	printf("%d\n", Main_cnt());
	return EXIT_SUCCESS;
}

------------------------------
c/space-32k-8.c:

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>

int Main_cnt()
{
	int	 cnt = 0;
	ssize_t	 sze, left;
	char	 buf[32760];
	char	*p;

	printf("using a buffer of %g KB\n", sizeof(buf) / 1024.0);

	do {
	again:
		sze = read(fileno(stdin), buf, sizeof(buf));
		if (sze < 0) {
			switch (errno) {
			case EAGAIN: goto again;
			default:
				perror("read() failed\n");
				exit(1);
			}
		}

		for (p = buf, left=sze; left > 0; left--)
			if (*p++ == ' ')
				cnt++;
	} while (sze != 0);

	return cnt;
}


int main()
{
	printf("%d\n", Main_cnt());
	return EXIT_SUCCESS;
}

------------------------------
c/space-32k.c:

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>

int Main_cnt()
{
	int	 cnt = 0;
	ssize_t	 sze, left;
	char	 buf[32*1024];
	char	*p;

	printf("using a buffer of %g KB\n", sizeof(buf) / 1024.0);

	do {
	again:
		sze = read(fileno(stdin), buf, sizeof(buf));
		if (sze < 0) {
			switch (errno) {
			case EAGAIN: goto again;
			default:
				perror("read() failed\n");
				exit(1);
			}
		}

		for (p = buf, left=sze; left > 0; left--)
			if (*p++ == ' ')
				cnt++;
	} while (sze != 0);

	return cnt;
}


int main()
{
	printf("%d\n", Main_cnt());
	return EXIT_SUCCESS;
}

------------------------------
c/space-4k.c:

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>

int Main_cnt()
{
	int	 cnt = 0;
	ssize_t	 sze, left;
	char	 buf[4*1024];
	char	*p;

	printf("using a buffer of %g KB\n", sizeof(buf) / 1024.0);

	do {
	again:
		sze = read(fileno(stdin), buf, sizeof(buf));
		if (sze < 0) {
			switch (errno) {
			case EAGAIN: goto again;
			default:
				perror("read() failed\n");
				exit(1);
			}
		}

		for (p = buf, left=sze; left > 0; left--)
			if (*p++ == ' ')
				cnt++;
	} while (sze != 0);

	return cnt;
}


int main()
{
	printf("%d\n", Main_cnt());
	return EXIT_SUCCESS;
}

------------------------------
c/space-getchar.c:

#include <stdio.h>
#include <stdlib.h>

int Main_cnt()
{
	int	cnt = 0;
	int	c;

	while ((c = getchar()) != EOF)
		if (c == ' ')
			cnt++;
	return cnt;
}


int main()
{
	printf("%d\n", Main_cnt());
	return EXIT_SUCCESS;
}

------------------------------
c/space-getchar-u.c:

#include <stdio.h>
#include <stdlib.h>

int Main_cnt()
{
	int	cnt = 0;
	int	c;

	while ((c = getchar_unlocked()) != EOF)
		if (c == ' ')
			cnt++;
	return cnt;
}


int main()
{
	printf("%d\n", Main_cnt());
	return EXIT_SUCCESS;
}

------------------------------
c/space-getwchar.c:

#include <stdio.h>
#include <wchar.h>
#include <stdlib.h>

int Main_cnt()
{
	int	cnt = 0;
	wint_t	c;

	while ((c = getwchar()) != WEOF)
		if (c == ' ')
			cnt++;
	return cnt;
}


int main()
{
	printf("%d\n", Main_cnt());
	return EXIT_SUCCESS;
}

------------------------------
c/space-getwchar-u.c:

#define _GNU_SOURCE
#include <stdio.h>
#include <wchar.h>
#include <stdlib.h>

int Main_cnt()
{
	int	cnt = 0;
	wint_t	c;

	while ((c = getwchar_unlocked()) != WEOF)
		if (c == ' ')
			cnt++;
	return cnt;
}


int main()
{
	printf("%d\n", Main_cnt());
	return EXIT_SUCCESS;
}

------------------------------
c/space-megabuf.c:

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/stat.h>
#include <unistd.h>

int isfile(int handle)
{
	struct stat	buf;

	if (fstat(handle, &buf) == -1) {
		perror("fstat(stdin)\n");
		exit(1);
	}

	return S_ISREG(buf.st_mode);
}


ssize_t getbufsize()
{
	if (isfile(fileno(stdin))) {
		off_t	x;

		x = lseek(fileno(stdin), 0, SEEK_END);
		if (x == -1) {
			perror("lseek(... SEEK_END)\n");
			exit(1);
		}
		if (lseek(fileno(stdin), 0, SEEK_SET) == -1) {
			perror("lseek(... SEEK_SET)\n");
			exit(1);
		}
		if (x > 1*1024*1024*1024LL) {
			x = 1024*1024*1024LL;
		}
		return x; /* file size for files */
	} else {
		return 10*1024*1024; /* 10M for non-files */
	}
}


int Main_cnt()
{
	int	 cnt = 0, reads=0, retries=0;
	ssize_t	 sze, left, bufsize;
	char	*buf;
	char	*p;

	bufsize = getbufsize();
	printf("using a buffer of %g MB\n", bufsize / (1024*1024.0));

	buf = malloc(bufsize);
	if (!buf) {
		fprintf(stderr, "couldn't allocate %lld bytes\n",
			(long long) bufsize);
	}

	do {
	again:
		sze = read(fileno(stdin), buf, bufsize);
		if (sze < 0) {
			switch (errno) {
			case EAGAIN: retries++; goto again;
			default:
				perror("read() failed\n");
				exit(1);
			}
		}
		reads++;

		for (p = buf, left=sze; left > 0; left--)
			if (*p++ == ' ')
				cnt++;
	} while (sze != 0);

	printf("%d reads, %d retries\n", reads, retries);

	return cnt;
}


int main()
{
	printf("%d\n", Main_cnt());
	return EXIT_SUCCESS;
}

==============================


More information about the Haskell-Cafe mailing list