Instantly share code, notes, and snippets.

@snoyberg /boxed.hs
Last active May 22, 2018

Embed
What would you like to do?
import qualified Data.ByteString.Lazy as L
import Data.Word (Word8)
data Stats = Stats
{ total :: Int
, count :: Int
}
initStats :: Stats
initStats = Stats 0 0
addStat :: Int -> Stats -> Stats
addStat x (Stats t c) = Stats (t + x) (c + 1)
average :: Stats -> Double
average (Stats t c) = fromIntegral t / fromIntegral c
fileName :: FilePath
fileName = "sample-data.bin"
population :: Int
population = 9
addStats :: [Stats] -> [Word8] -> [Stats]
addStats stats0 bytes0 =
loop [] stats0 bytes0
where
loop front stats [] = reverse front ++ stats
loop front [] bytes = loop [] (reverse front) bytes
loop front (x:stats) (y:bytes) = loop
(addStat (fromIntegral y) x:front)
stats
bytes
main :: IO ()
main = do
lbs <- L.readFile "sample-data.bin"
let initial = replicate population initStats
final = addStats initial (L.unpack lbs)
print $ map average final
{-
[127.436561,127.449141,127.64308,127.551385,127.479474,127.457795,127.577525,127.697076,127.463543]
2,948,968,072 bytes allocated in the heap
4,447,810,144 bytes copied during GC
397,149,080 bytes maximum residency (24 sample(s))
48,124,104 bytes maximum slop
1065 MB total memory in use (0 MB lost due to fragmentation)
Tot time (elapsed) Avg pause Max pause
Gen 0 5574 colls, 0 par 0.340s 2.030s 0.0004s 0.0014s
Gen 1 24 colls, 0 par 1.440s 1.706s 0.0711s 0.2660s
INIT time 0.000s ( 0.000s elapsed)
MUT time 0.252s ( 1.178s elapsed)
GC time 1.780s ( 3.737s elapsed)
EXIT time 0.000s ( 0.004s elapsed)
Total time 2.032s ( 4.919s elapsed)
%GC time 87.6% (76.0% elapsed)
Alloc rate 11,702,254,253 bytes per MUT second
Productivity 12.4% of total user, 5.1% of total elapsed
real 0m4.923s
user 0m2.032s
sys 0m2.884s
-}
#!/usr/bin/env bash
set -exuo pipefail
dd if=/dev/urandom of=sample-data.bin bs=9000 count=1000
import qualified Data.ByteString.Lazy as L
import Data.Word (Word8)
data Stats = Stats
{ total :: !Int
, count :: !Int
}
initStats :: Stats
initStats = Stats 0 0
addStat :: Int -> Stats -> Stats
addStat x (Stats t c) = Stats (t + x) (c + 1)
average :: Stats -> Double
average (Stats t c) = fromIntegral t / fromIntegral c
fileName :: FilePath
fileName = "sample-data.bin"
population :: Int
population = 9
addStats :: [Stats] -> [Word8] -> [Stats]
addStats stats0 bytes0 =
loop [] stats0 bytes0
where
loop front stats [] = reverse front ++ stats
loop front [] bytes = loop [] (reverse front) bytes
loop front (x:stats) (y:bytes) = y' `seq` loop
(y':front)
stats
bytes
where
y' = addStat (fromIntegral y) x
main :: IO ()
main = do
lbs <- L.readFile "sample-data.bin"
let initial = replicate population initStats
final = addStats initial (L.unpack lbs)
print $ map average final
{-
[127.436561,127.449141,127.64308,127.551385,127.479474,127.457795,127.577525,127.697076,127.463543]
1,046,425,584 bytes allocated in the heap
247,482,784 bytes copied during GC
83,160 bytes maximum residency (275 sample(s))
193,920 bytes maximum slop
2 MB total memory in use (0 MB lost due to fragmentation)
Tot time (elapsed) Avg pause Max pause
Gen 0 1713 colls, 0 par 0.008s 0.120s 0.0001s 0.0009s
Gen 1 275 colls, 0 par 0.004s 0.013s 0.0000s 0.0002s
INIT time 0.000s ( 0.000s elapsed)
MUT time 0.008s ( 0.139s elapsed)
GC time 0.012s ( 0.133s elapsed)
EXIT time 0.000s ( 0.000s elapsed)
Total time 0.020s ( 0.272s elapsed)
%GC time 60.0% (48.7% elapsed)
Alloc rate 130,803,198,000 bytes per MUT second
Productivity 40.0% of total user, 2.9% of total elapsed
real 0m0.274s
user 0m0.020s
sys 0m0.252s
-}
{-# LANGUAGE TemplateHaskell, TypeFamilies, MultiParamTypeClasses #-}
import qualified Data.ByteString.Lazy as L
import Data.Word (Word8)
import Data.Vector.Unboxed.Deriving
import qualified Data.Vector.Unboxed as V
import qualified Data.Vector.Unboxed.Mutable as M
import Control.Monad.Primitive (PrimState)
data Stats = Stats
{ total :: !Int
, count :: !Int
}
-- auto-generate the marshaling code
derivingUnbox "Stats"
[t|Stats -> (Int, Int)|]
[|\(Stats t c) -> (t, c)|]
[|\(t, c) -> Stats t c|]
initStats :: Stats
initStats = Stats 0 0
addStat :: Int -> Stats -> Stats
addStat x (Stats t c) = Stats (t + x) (c + 1)
average :: Stats -> Double
average (Stats t c) = fromIntegral t / fromIntegral c
fileName :: FilePath
fileName = "sample-data.bin"
population :: Int
population = 9
addStats :: M.MVector (PrimState IO) Stats -> [Word8] -> IO ()
addStats m =
loop 0
where
loop _ [] = return ()
loop index bytes | index >= M.length m = loop 0 bytes
loop index (x:bytes) = do
stats <- M.unsafeRead m index
M.unsafeWrite m index $ addStat (fromIntegral x) stats
loop (index + 1) bytes
main :: IO ()
main = do
lbs <- L.readFile "sample-data.bin"
m <- M.replicate population initStats
addStats m (L.unpack lbs)
final <- V.unsafeFreeze m
print $ V.map average final
{-
fromList [127.436561,127.449141,127.64308,127.551385,127.479474,127.457795,127.577525,127.697076,127.463543]
374,426,560 bytes allocated in the heap
148,927,200 bytes copied during GC
57,208 bytes maximum residency (138 sample(s))
244,032 bytes maximum slop
3 MB total memory in use (0 MB lost due to fragmentation)
Tot time (elapsed) Avg pause Max pause
Gen 0 565 colls, 0 par 0.004s 0.075s 0.0001s 0.0010s
Gen 1 138 colls, 0 par 0.000s 0.006s 0.0000s 0.0002s
INIT time 0.000s ( 0.000s elapsed)
MUT time 0.004s ( 0.069s elapsed)
GC time 0.004s ( 0.081s elapsed)
EXIT time 0.000s ( 0.000s elapsed)
Total time 0.008s ( 0.150s elapsed)
%GC time 50.0% (54.0% elapsed)
Alloc rate 93,606,640,000 bytes per MUT second
Productivity 50.0% of total user, 2.7% of total elapsed
real 0m0.152s
user 0m0.008s
sys 0m0.140s
-}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment