Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Usable benchmarks -- many of them.

  • Loading branch information...
commit 9cc06664fe39ce9d69315698fad31dd3b3266f5a 1 parent 4913174
@solidsnack authored
View
11 Data/ByteString/Nums/Careless/Float.hs
@@ -7,8 +7,9 @@
module Data.ByteString.Nums.Careless.Float where
-import Prelude hiding (length, splitAt)
-import Data.ByteString.Char8 hiding (inits, elem, last)
+import Data.Char
+import Prelude hiding (splitAt)
+import Data.ByteString.Char8 hiding (length, inits, elem, last)
import qualified Data.ByteString.Lazy.Char8 as Lazy
@@ -42,18 +43,20 @@ instance Floatable Lazy.ByteString Rational where
strict_float bytes = case findIndices (`elem` ".,") bytes of
[ ] -> int bytes
- idx -> hi' + (int lo * (0.1 ^ length lo) * s)
+ idx -> hi' + (int lo * (0.1 ^ length digits) * s)
where
(hi, lo) = splitAt (last idx) bytes
hi' = int hi
s = signum hi'
+ digits = findIndices isDigit lo
lazy_float bytes = case Lazy.findIndices (`elem` ".,") bytes of
[ ] -> int bytes
- idx -> hi' + (int lo * (0.1 ^ Lazy.length lo) * s)
+ idx -> hi' + (int lo * (0.1 ^ length digits) * s)
where
(hi, lo) = Lazy.splitAt (last idx) bytes
hi' = int hi
s = signum hi'
+ digits = Lazy.findIndices isDigit lo
View
12 Data/ByteString/Nums/Careless/Hex.hs
@@ -113,16 +113,8 @@ hexalize acc byte
between b a z = b >= c2w a && byte <= c2w z
place_up b = (0x10 * acc) + fromIntegral b
-strict_hex bytes = foldl' hexalize 0 piece
- where
- piece = if pack "0x" `isPrefixOf` bytes
- then drop 2 bytes
- else bytes
+strict_hex bytes = foldl' hexalize 0 bytes
-lazy_hex bytes = Lazy.foldlChunks (foldl' hexalize) 0 piece
- where
- piece = if Lazy.pack "0x" `Lazy.isPrefixOf` bytes
- then Lazy.drop 2 bytes
- else bytes
+lazy_hex bytes = Lazy.foldlChunks (foldl' hexalize) 0 bytes
View
4 Data/ByteString/Nums/Careless/Int.hs
@@ -11,9 +11,9 @@ import Prelude hiding (head, tail, null)
import Data.Word
import Data.Int
import Data.Ratio
-import Data.ByteString hiding (head)
+import Data.ByteString hiding (head, pack)
import Data.ByteString.Internal
-import Data.ByteString.Char8 (head)
+import Data.ByteString.Char8 hiding (foldl')
import qualified Data.ByteString.Lazy.Char8 as Lazy
import qualified Data.ByteString.Lazy.Internal as Lazy
View
69 SPOJDons.hs
@@ -0,0 +1,69 @@
+
+{-# LANGUAGE BangPatterns
+ #-}
+
+import Data.Char
+import Data.Maybe
+import Data.ByteString hiding (last, uncons)
+import Data.ByteString.Internal
+import Data.ByteString.Unsafe
+import qualified Data.ByteString.Char8 as S
+import qualified Data.ByteString.Lazy.Char8 as L
+
+main = do
+ ss <- L.getContents -- done with IO now.
+ let (l,ls) = L.break (=='\n') ss
+ -- don't need count, we're allocating lazily
+ k = fst . fromJust . L.readInt . last . L.split ' ' $ l
+ file = L.toChunks (L.tail ls) -- a lazy list of strict cache chunks
+ print $ process k 0 file
+
+divisibleBy :: Int -> Int -> Bool
+a `divisibleBy` n = a `rem` n == 0
+
+-- ---------------------------------------------------------------------
+--
+-- Optimised parsing of strict bytestrings representing \n separated numbers
+--
+
+--
+-- we have the file as a list of cache chunks
+-- align them on \n boundaries, and process each chunk separately
+-- when the next chunk is demanded, it will be read in.
+--
+process :: Int -> Int -> [S.ByteString] -> Int
+process k i [] = i
+process k !i (s:t:ts) | S.last s /= '\n' = process k (add k i s') ts'
+ where
+ (s',r) = S.breakEnd (=='\n') s
+ ts' = (S.append r t) : ts -- join chunks on line boundaries
+
+process k i (s: ss) = process k (add k i s) ss
+
+--
+-- process a single cache-sized chunk of numbers, \n aligned
+--
+add :: Int -> Int -> S.ByteString -> Int
+add k i s | S.null s = i
+ | otherwise = test k i (parse x) xs
+ where (x,xs) = uncons s
+
+--
+-- process a single line, until \n
+--
+test :: Int -> Int -> Int -> ByteString -> Int
+test k i !n t
+ | y == '\n' = -- done reading the line, process it:
+ if n `divisibleBy` k then add k (i+1) ys
+ else add k i ys
+ | otherwise = test k i n' ys
+ where (y,ys) = uncons t
+ n' = parse y + 10 * n
+
+parse c = ord c - ord '0'
+
+-- fastest way to take the head of a strict bytestring
+uncons s = (w2c (unsafeHead s), unsafeTail s)
+
+
+
View
45 SPOJEugeneKirpichov.hs
@@ -0,0 +1,45 @@
+
+
+module Main where
+
+import qualified Data.ByteString.Lazy as B
+import Data.ByteString.Nums.Careless -- from bytestring-nums package
+
+bint :: B.ByteString -> Int
+bint = int
+
+main = do
+ line : rest <- B.split 10 `fmap` B.getContents
+ let [n, k] = map int . B.split 32 $ line
+ putStrLn . show . length . tail . filter ((==0).(`mod`k).bint) $ rest
+
+
+
+{- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+---------- Forwarded message ----------
+From: Eugene Kirpichov <ekirpichov@gmail.com>
+Date: 2009/08/30
+Subject: Re: [Haskell-cafe] Slow IO?
+To: Steve <stevech1097@yahoo.com.au>
+Cc: haskell-cafe@haskell.org
+
+
+module Main where
+
+import qualified Data.ByteString.Lazy as B
+import Data.ByteString.Nums.Careless -- from bytestring-nums package
+
+bint :: B.ByteString -> Int
+bint = int
+
+main = do
+ line : rest <- B.split 10 `fmap` B.getContents
+ let [n, k] = map int . B.split 32 $ line
+ putStrLn . show . length . tail . filter ((==0).(`mod`k).bint) $ rest
+
+This does a 100MB file in 2.7s (probably because the file is cached by
+the filesystem).
+
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -}
+
View
46 SPOJMem.hs
@@ -0,0 +1,46 @@
+#!/usr/bin/env runhaskell
+
+{-# LANGUAGE BangPatterns
+ , ScopedTypeVariables
+ #-}
+
+{-| The Sphere Online Judge is a collection of problems. One problem, problem
+ 450, came up on the mailing list as a sensible benchmark for fast integer
+ parsing.
+ -}
+
+
+{- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+ https://www.spoj.pl/problems/INTEST/
+
+ Slow IO?
+ http://www.nabble.com/Slow-IO--td25210251.html
+
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -}
+
+
+import Data.List
+import Prelude hiding (drop, take)
+import System.IO (stdin, stdout, stderr, Handle, putStrLn)
+import Control.Monad
+
+import Data.ByteString hiding (putStrLn, foldl', length, filter, take)
+import Data.ByteString.Nums.Careless
+
+
+
+
+main = do
+ (n, k) <- breakByte 0x20 `fmap` hGetLine stdin
+ strings <- split 0x0a `fmap` hGetContents stdin
+ putStrLn . show . process (int k) . ints . take (int n) $ strings
+ where
+ ints :: [ByteString] -> [Int]
+ ints = fmap int
+ process :: Int -> [Int] -> Int
+ process k = length . filter (condition k)
+ where
+ condition k num = num `mod` k == 0
+
+
View
53 SPOJObvious.hs
@@ -0,0 +1,53 @@
+#!/usr/bin/env runhaskell
+
+{-# LANGUAGE BangPatterns
+ #-}
+
+{-| The Sphere Online Judge is a collection of problems. One problem, problem
+ 450, came up on the mailing list as a sensible benchmark for fast integer
+ parsing.
+ -}
+
+
+{- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+ https://www.spoj.pl/problems/INTEST/
+
+ Slow IO?
+ http://www.nabble.com/Slow-IO--td25210251.html
+
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -}
+
+
+import Data.List
+import Prelude hiding (drop, take)
+import System.IO (stdin, stdout, stderr, Handle, putStrLn)
+import Control.Monad
+
+import Data.ByteString hiding (putStrLn, foldl')
+import Data.ByteString.Nums.Careless
+
+
+
+
+main = do
+ (n, k) <- breakByte 0x20 `fmap` hGetLine stdin
+ count <- show `fmap` obvious (int n) (int k)
+ putStrLn count
+
+
+obvious n k = sum `fmap` sequence (numbers n stdin)
+ where
+ sum = foldl' (check k) 0
+
+
+numbers :: Int -> Handle -> [IO Int]
+numbers n h = const (int `fmap` hGetLine h) `fmap` [1..n]
+
+
+check :: Int -> Int -> Int -> Int
+check k acc n
+ | n `mod` k == 0 = acc + 1
+ | otherwise = acc
+
+
View
53 SPOJStrict.hs
@@ -0,0 +1,53 @@
+#!/usr/bin/env runhaskell
+
+{-# LANGUAGE BangPatterns
+ #-}
+
+{-| The Sphere Online Judge is a collection of problems. One problem, problem
+ 450, came up on the mailing list as a sensible benchmark for fast integer
+ parsing.
+ -}
+
+
+{- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+ https://www.spoj.pl/problems/INTEST/
+
+ Slow IO?
+ http://www.nabble.com/Slow-IO--td25210251.html
+
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -}
+
+
+import Data.List
+import Prelude hiding (drop, take)
+import System.IO (stdin, stdout, stderr, Handle, putStrLn)
+import Control.Monad
+
+import Data.ByteString hiding (putStrLn, foldl')
+import Data.ByteString.Nums.Careless
+
+
+
+
+main = do
+ (n, k) <- breakByte 0x20 `fmap` hGetLine stdin
+ count <- show `fmap` strict (int n) (int k)
+ putStrLn count
+
+
+strict !n !k = sum `fmap` sequence (numbers n stdin)
+ where
+ sum = foldl' (check k) 0
+
+
+numbers :: Int -> Handle -> [IO Int]
+numbers !n !h = const (int `fmap` hGetLine h) `fmap` [1..n]
+
+
+check :: Int -> Int -> Int -> Int
+check !k !acc !n
+ | n `mod` k == 0 = acc + 1
+ | otherwise = acc
+
+
View
48 bytestring-nums.cabal
@@ -1,5 +1,5 @@
name : bytestring-nums
-version : 0.1.0
+version : 0.2.1
category : Text
license : BSD3
license-file : LICENSE
@@ -18,7 +18,7 @@ extra-source-files : README
library
- build-depends : base
+ build-depends : base >= 3 && <= 4
, containers
, bytestring >= 0.9
exposed-modules : Data.ByteString.Nums.Careless
@@ -27,4 +27,48 @@ library
Data.ByteString.Nums.Careless.Float
extensions : MultiParamTypeClasses
TypeSynonymInstances
+ ghc-options : -O2 -Wall -funbox-strict-fields
+
+
+executable spoj-strict
+ main-is : SPOJStrict.hs
+ extensions : MultiParamTypeClasses
+ TypeSynonymInstances
+ BangPatterns
+ ghc-options : -O2 -Wall -funbox-strict-fields
+
+
+executable spoj-eugene
+ main-is : SPOJEugeneKirpichov.hs
+ extensions : MultiParamTypeClasses
+ TypeSynonymInstances
+ BangPatterns
+ ghc-options : -O2 -Wall -funbox-strict-fields
+
+
+executable spoj-obvious
+ main-is : SPOJObvious.hs
+ extensions : MultiParamTypeClasses
+ TypeSynonymInstances
+ ghc-options : -O2 -Wall -funbox-strict-fields
+
+
+executable spoj-mem
+ main-is : SPOJMem.hs
+ extensions : MultiParamTypeClasses
+ TypeSynonymInstances
+ BangPatterns
+ ScopedTypeVariables
+ ghc-options : -O2 -Wall -funbox-strict-fields
+
+
+executable spoj-dons
+ main-is : SPOJDons.hs
+ extensions : MultiParamTypeClasses
+ TypeSynonymInstances
+ BangPatterns
+ ghc-options : -O2 -Wall -funbox-strict-fields
+
+
+
Please sign in to comment.
Something went wrong with that request. Please try again.