Skip to content
This repository was archived by the owner on Sep 20, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 30 additions & 8 deletions Foundation/Array/Unboxed.hs
Original file line number Diff line number Diff line change
Expand Up @@ -531,25 +531,25 @@ null (UVecAddr _ l _) = l == Size 0
take :: PrimType ty => Int -> UArray ty -> UArray ty
take nbElems v
| nbElems <= 0 = empty
| n == vlen = v
| n >= vlen = v
| otherwise =
case v of
UVecBA start _ pinst ba -> UVecBA start n pinst ba
UVecAddr start _ fptr -> UVecAddr start n fptr
where
n = min (Size nbElems) vlen
n = Size nbElems
vlen = lengthSize v

drop :: PrimType ty => Int -> UArray ty -> UArray ty
drop nbElems v
| nbElems <= 0 = v
| n == vlen = empty
| n >= vlen = empty
| otherwise =
case v of
UVecBA start len pinst ba -> UVecBA (start `offsetPlusE` n) (len - n) pinst ba
UVecAddr start len fptr -> UVecAddr (start `offsetPlusE` n) (len - n) fptr
where
n = min (Size nbElems) vlen
n = Size nbElems
vlen = lengthSize v

splitAt :: PrimType ty => Int -> UArray ty -> (UArray ty, UArray ty)
Expand Down Expand Up @@ -580,7 +580,7 @@ splitElem !ty r@(UVecBA start len pinst ba)
loop !i | i < end && t /= ty = loop (i+Offset 1)
| otherwise = i
where !t = primBaIndex ba i
splitElem ty r@(UVecAddr start len fptr)
splitElem !ty r@(UVecAddr start len fptr)
| k == end = (# r, empty #)
| otherwise =
(# UVecAddr start (offsetAsSize k) fptr
Expand Down Expand Up @@ -809,10 +809,32 @@ filter :: PrimType ty => (ty -> Bool) -> UArray ty -> UArray ty
filter predicate vec = vFromList $ Data.List.filter predicate $ vToList vec

reverse :: PrimType ty => UArray ty -> UArray ty
reverse a = create len toEnd
reverse a
| len == Size 0 = empty
| otherwise = runST $ do
ma <- newNative len $ \mba ->
case a of
(UVecBA start _ _ ba) -> goNative endOfs mba ba start
(UVecAddr start _ fptr) -> withFinalPtr fptr $ \ptr -> goAddr endOfs mba ptr start
unsafeFreeze ma
where
len = length a
toEnd i = unsafeIndex a (len - i - 1)
!len = lengthSize a
!endOfs = Offset 0 `offsetPlusE` len

goNative :: PrimType ty => Offset ty -> MutableByteArray# s -> ByteArray# -> Offset ty -> ST s ()
goNative !end !ma !ba !srcStart = loop (Offset 0)
where
!endI = sizeAsOffset ((srcStart + end) - Offset 1)
loop !i
| i == end = return ()
| otherwise = primMbaWrite ma i (primBaIndex ba (sizeAsOffset (endI - i))) >> loop (i+Offset 1)
goAddr !end !ma !(Ptr ba) !srcStart = loop (Offset 0)
where
!endI = sizeAsOffset ((srcStart + end) - Offset 1)
loop !i
| i == end = return ()
| otherwise = primMbaWrite ma i (primAddrIndex ba (sizeAsOffset (endI - i))) >> loop (i+Offset 1)
{-# SPECIALIZE [3] reverse :: UArray Word8 -> UArray Word8 #-}

foldl :: PrimType ty => (a -> ty -> a) -> a -> UArray ty -> a
foldl f initialAcc vec = loop 0 initialAcc
Expand Down
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,10 @@ To run a specific or set of benchmarks :
stack bench --flag foundation:bench-all --benchmark-arguments '-m prefix types/String/SplitAt'
stack bench --flag foundation:bench-all --benchmark-arguments '-m glob types/String/SplitAt'

To register a set of benchmarks:

stack bench --flag foundation:bench-all --benchmark-arguments "--csv $(git describe).csv"


Design
======
Expand Down
22 changes: 19 additions & 3 deletions benchs/BenchUtil/RefData.hs
Original file line number Diff line number Diff line change
@@ -1,19 +1,26 @@
module BenchUtil.RefData
( rdLoremIpsum1
(
-- string
rdLoremIpsum1
, rdLoremIpsum5
, rdFoundationEn
, rdFoundationZh
, rdFoundationJap
, rdFoundationHun
-- byte array
, rdBytes20
, rdBytes200
, rdBytes2000
) where

import Prelude (Char)
import Prelude (Char, cycle, take, ($))
import Data.Word (Word8)

rdLoremIpsum1 :: [Char]
rdLoremIpsum1 = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam ornare dui vitae porta varius. In quis diam sed felis elementum ultricies non sit amet lorem. Nullam ut erat varius lectus scelerisque iaculis sed eu leo. Vivamus gravida interdum elit suscipit tempus. Quisque at mauris ac sapien consequat feugiat. In varius interdum rhoncus. Etiam hendrerit pharetra consectetur. Pellentesque laoreet, nisi quis feugiat rhoncus, nisi ipsum tincidunt nulla, vel fermentum mauris nisl sed felis. Sed ac convallis nibh. Donec rutrum finibus odio et rhoncus. Suspendisse pulvinar ex ac fermentum fermentum. Nam dui dui, lobortis sit amet sapien sed, gravida sagittis magna. Vestibulum nec egestas dui, non efficitur lectus. Fusce vitae mattis sem, nec dignissim nibh. Sed ac tincidunt metus."

rdLoremIpsum5 :: [Char]
rdLoremIpsum5 = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam ornare dui vitae porta varius. In quis diam sed felis elementum ultricies non sit amet lorem. Nullam ut erat varius lectus scelerisque iaculis sed eu leo. Vivamus gravida interdum elit suscipit tempus. Quisque at mauris ac sapien consequat feugiat. In varius interdum rhoncus. Etiam hendrerit pharetra consectetur. Pellentesque laoreet, nisi quis feugiat rhoncus, nisi ipsum tincidunt nulla, vel fermentum mauris nisl sed felis. Sed ac convallis nibh. Donec rutrum finibus odio et rhoncus. Suspendisse pulvinar ex ac fermentum fermentum. Nam dui dui, lobortis sit amet sapien sed, gravida sagittis magna. Vestibulum nec egestas dui, non efficitur lectus. Fusce vitae mattis sem, nec dignissim nibh. Sed ac tincidunt metus. Vestibulum ac bibendum ex. In vulputate pellentesque elementum. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Maecenas elit libero, vehicula eget hendrerit non, convallis vel metus. Maecenas faucibus nulla id quam vestibulum, eget commodo tellus interdum. Mauris eu odio id lacus gravida sollicitudin. Aenean vel velit enim. Phasellus vitae urna nisl. Interdum et malesuada fames ac ante ipsum primis in faucibus. Nunc volutpat convallis elementum. Curabitur suscipit congue ligula non maximus. Fusce tristique lacinia sem sed condimentum. Sed non eleifend mi, fringilla congue tortor. Nunc rhoncus sit amet nisl ac tempor. Fusce sed consectetur purus, et aliquam sem. Vestibulum finibus lectus et vehicula euismod. Aliquam sed neque mattis, sollicitudin enim sed, vestibulum est. Quisque varius pharetra risus id tempor. In hac habitasse platea dictumst. Donec cursus nisi sed magna bibendum aliquet. Mauris a elit id erat imperdiet consequat. Phasellus at condimentum ipsum. Pellentesque vehicula pulvinar ipsum et porta. Nullam quis quam mauris. Sed scelerisque porta nibh eu tempor. Morbi sollicitudin fringilla sollicitudin. Cras nec velit quis velit sollicitudin pellentesque. Phasellus quis ullamcorper nisi. Curabitur fringilla sed turpis sit amet pharetra. Cras euismod eget massa eu posuere. Suspendisse id aliquam enim. Nullam sollicitudin aliquet elementum. Nulla sit amet ligula vitae lorem finibus laoreet sed ac velit. Nulla facilisi. Aenean vel pretium lectus. Nunc augue lorem, viverra et felis vel, vestibulum feugiat nisl. Vestibulum imperdiet laoreet posuere. Maecenas vestibulum consequat felis eu aliquam. Nullam ac efficitur ante, eget egestas mauris. Cras id tincidunt nisi. Cras tincidunt molestie lorem et bibendum. Donec commodo porttitor faucibus. Aenean aliquam suscipit iaculis. Cras eu purus sit amet elit rhoncus laoreet. Vestibulum fringilla nulla ut neque vestibulum porttitor. Pellentesque vitae risus elit. Quisque et sapien eu diam tincidunt luctus ac quis nunc. Proin nec nisl eget diam faucibus tempus id sed quam. Ut scelerisque enim lacus, at mollis diam sagittis et. Nam lobortis convallis maximus. Donec maximus tortor id consequat venenatis."
rdLoremIpsum5 = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam ornare dui vitae porta varius. In quis diam sed felis elementum ultricies non sit amet lorem. Nullam ut erat varius lectus scelerisque iaculis sed eu leo. Vivamus gravida interdum elit suscipit tempus. Quisque at mauris ac sapien consequat feugiat. In varius interdum rhoncus. Etiam hendrerit pharetra consectetur. Pellentesque laoreet, nisi quis feugiat rhoncus, nisi ipsum tincidunt nulla, vel fermentum mauris nisl sed felis. Sed ac convallis nibh. Donec rutrum finibus odio et rhoncus. Suspendisse pulvinar ex ac fermentum fermentum. Nam dui dui, lobortis sit amet sapien sed, gravida sagittis magna. Vestibulum nec egestas dui, non efficitur lectus. Fusce vitae mattis sem, nec dignissim nibh. Sed ac tincidunt metus. Vestibulum ac bibendum ex. In vulputate pellentesque elementum. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Maecenas elit libero, vehicula eget hendrerit non, convallis vel metus. Maecenas faucibus nulla id quam vestibulum, eget commodo tellus interdum. Mauris eu odio id lacus gravida sollicitudin. Aenean vel velit enim. Phasellus vitae urna nisl. Interdum et malesuada fames ac ante ipsum primis in faucibus. Nunc volutpat convallis elementum. Curabitur suscipit congue ligula non maximus. Fusce tristique lacinia sem sed condimentum. Sed non eleifend mi, fringilla congue tortor. Nunc rhoncus sit amet nisl ac tempor. Fusce sed consectetur purus, et aliquam sem. Vestibulum finibus lectus et vehicula euismod. Aliquam sed neque mattis, sollicitudin enim sed, vestibulum est. Quisque varius pharetra risus id tempor. In hac habitasse platea dictumst. Donec cursus nisi sed magna bibendum aliquet. Mauris a elit id erat imperdiet consequat. Phasellus at condimentum ipsum. Pellentesque vehicula pulvinar ipsum et porta. Nullam quis quam mauris. Sed scelerisque porta nibh eu tempor. Morbi sollicitudin fringilla sollicitudin. Cras nec velit quis velit sollicitudin pellentesque. Phasellus quis ullamcorper nisi. Curabitur fringilla sed turpis sit amet pharetra. Cras euismod eget massa eu posuere. Suspendisse id aliquam enim. Nullam sollicitudin aliquet elementum. Nulla sit amet ligula vitae lorem finibus laoreet sed ac velit. Nulla facilisi. Aenean vel pretium lectus. Nunc augue lorem, viverra et felis vel, vestibulum feugiat nisl. Vestibulum imperdiet laoreet posuere. Maecenas vestibulum consequat felis eu aliquam. Nullam ac efficitur ante, eget egestas mauris. Cras id tincidunt nisi. Cras tincidunt molestie lorem et bibendum. Donec commodo porttitor faucibus. Aenean aliquam suscipit iaculis. Cras eu purus sit amet elit rhoncus laoreet. Vestibulum fringilla nulla ut neque vestibulum porttitor. Pellentesque vitae risus elit. Quisque et sapien eu diam tincidunt luctus ac quis nunc. Proin nec nisl eget diam faucibus tempus id sed quam. Ut scelerisque enim lacus, at mollis diam sagittis et. Nam lobortis convallis maximus. Donec maximus tortor id consequat venenatis."

rdFoundationEn :: [Char]
rdFoundationEn = "Set in the year 0 F.E. (\"Foundation Era\"), The Psychohistorians opens on Trantor, the capital of the 12,000-year-old Galactic Empire. Though the empire appears stable and powerful, it is slowly decaying in ways that parallel the decline of the Western Roman Empire. Hari Seldon, a mathematician and psychologist, has developed psychohistory, a new field of science and psychology that equates all possibilities in large societies to mathematics, allowing for the prediction of future events."
Expand All @@ -26,3 +33,12 @@ rdFoundationHun = "A történet G.K. 12 067-ben (A.K. 1) játszódik. A fiatal

rdFoundationJap :: [Char]
rdFoundationJap = "数学者ハリ・セルダンは、膨大な集団の行動を予測する心理歴史学を作りあげ発展させることで、銀河帝国が近いうちに崩壊することを予言する[1]。セルダンは、帝国崩壊後に3万年続くはずの暗黒時代を、あらゆる知識を保存することで千年に縮めようとし、知識の集大成となる銀河百科事典 (Encyclopedia Galactica) を編纂するグループ「ファウンデーション」をつくったが、帝国崩壊を公言し平和を乱したという罪で裁判にかけられ、グループは銀河系辺縁部にある資源の乏しい無人惑星ターミナスへ追放されることになった。しかし、この追放劇すらもセルダンの計画に予定されていた事柄であった。病で死期をさとっていたセルダンは、己の仕事が終わったことを確信する。"

rdBytes20 ::[Word8]
rdBytes20 = take 20 $ cycle [1..255]

rdBytes200 :: [Word8]
rdBytes200 = take 200 $ cycle [1..255]

rdBytes2000 :: [Word8]
rdBytes2000 = take 2000 $ cycle [1..255]
22 changes: 22 additions & 0 deletions benchs/Fake/ByteString.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
module Fake.ByteString
( ByteString
, pack
, length
, splitAt
, take
, break
, reverse
, filter
) where

import Prelude (undefined)

data ByteString = ByteString

pack _ = ByteString
length = undefined
splitAt _ _ = (undefined, undefined)
take = undefined
break _ _ = (undefined, undefined)
reverse = undefined
filter _ = undefined
22 changes: 22 additions & 0 deletions benchs/Fake/Text.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
module Fake.Text
( Text
, pack
, length
, splitAt
, take
, any
, filter
, reverse
) where

import Prelude (undefined)

data Text = Text

pack _ = Text
length = undefined
splitAt _ _ = (undefined, undefined)
take = undefined
filter _ = undefined
reverse = undefined
any = undefined
134 changes: 85 additions & 49 deletions benchs/Main.hs
Original file line number Diff line number Diff line change
Expand Up @@ -11,22 +11,11 @@ import BenchUtil.Common
import BenchUtil.RefData

#ifdef BENCH_ALL
import qualified Data.ByteString as ByteString
import qualified Data.Text as Text
type TextText = Text.Text

textPack = Text.pack
textLength = Text.length
textSplitAt = Text.splitAt
textTake = Text.take
textAny = Text.any
#else
data TextText = Text

textPack _ = Text
textLength = undefined
textSplitAt _ _ = (undefined, undefined)
textTake = undefined
textAny = undefined
import qualified Fake.ByteString as ByteString
import qualified Fake.Text as Text
#endif

--------------------------------------------------------------------------
Expand All @@ -37,10 +26,12 @@ benchsString = bgroup "String"
, benchTake
, benchSplitAt
, benchBuildable
, benchReverse
, benchFilter
]
where
diffTextString :: (String -> a)
-> (TextText -> b)
-> (Text.Text -> b)
-> [Char]
-> [Benchmark]
diffTextString foundationBench textBench dat =
Expand All @@ -51,54 +42,99 @@ benchsString = bgroup "String"
]
where
s = fromList dat
t = textPack dat
t = Text.pack dat

allDat = [ ("ascii", rdFoundationEn)
, ("mascii", rdFoundationHun)
, ("uni1" ,rdFoundationJap)
, ("uni2" ,rdFoundationZh)
]
allDatSuffix s = fmap (first (\x -> x <> "-" <> s)) allDat

benchLength = bgroup "Length" $
fmap (\(n, dat) -> bgroup n $ diffTextString length textLength dat)
[ ("ascii", rdFoundationEn)
, ("mascii", rdFoundationHun)
, ("uni1" ,rdFoundationJap)
, ("uni2" ,rdFoundationZh)
]
fmap (\(n, dat) -> bgroup n $ diffTextString length Text.length dat)
allDat
benchElem = bgroup "Elem" $
fmap (\(n, dat) -> bgroup n $ diffTextString (elem '.') (textAny (== '.')) dat)
[ ("ascii" , rdFoundationEn)
, ("mascii", rdFoundationHun)
, ("uni1" , rdFoundationJap)
, ("uni2" , rdFoundationZh)
]
benchTake = bgroup "Take" $
mconcat $ fmap (\p ->
fmap (\(n, dat) -> bgroup n $ diffTextString (take p) (textTake p) dat)
[ ("ascii-" <> show p, rdFoundationEn)
, ("mascii-" <> show p, rdFoundationHun)
, ("uni1-" <> show p,rdFoundationJap)
, ("uni2-" <> show p,rdFoundationZh)
]) [ 10, 100, 800 ]
benchSplitAt = bgroup "SplitAt" $
mconcat $ fmap (\p ->
fmap (\(n, dat) -> bgroup n $ diffTextString (fst . splitAt p) (fst . textSplitAt p) dat)
[ ("ascii-" <> show p, rdFoundationEn)
, ("mascii-" <> show p, rdFoundationHun)
, ("uni1-" <> show p,rdFoundationJap)
, ("uni2-" <> show p,rdFoundationZh)
]) [ 10, 100, 800 ]
fmap (\(n, dat) -> bgroup n $ diffTextString (elem '.') (Text.any (== '.')) dat)
allDat
benchTake = bgroup "Take" $ mconcat $ fmap (\p ->
fmap (\(n, dat) -> bgroup n $ diffTextString (take p) (Text.take p) dat)
$ allDatSuffix (show p)
) [ 10, 100, 800 ]
benchSplitAt = bgroup "SplitAt" $ mconcat $ fmap (\p ->
fmap (\(n, dat) -> bgroup n $ diffTextString (fst . splitAt p) (fst . Text.splitAt p) dat)
$ allDatSuffix (show p)
) [ 10, 100, 800 ]

benchBuildable = bgroup "Buildable" $
fmap (\(n, dat) -> bench n $ toString (\es -> runST $ build 128 $ Prelude.mapM_ append es) dat)
[ ("ascii" , rdFoundationEn)
, ("mascii", rdFoundationHun)
, ("uni1" , rdFoundationJap)
, ("uni2" , rdFoundationZh)
]
allDat

benchReverse = bgroup "Reverse" $
fmap (\(n, dat) -> bgroup n $ diffTextString reverse Text.reverse dat)
allDat

benchFilter = bgroup "Filter" $
fmap (\(n, dat) -> bgroup n $ diffTextString (filter (> 'b')) (Text.filter (> 'b')) dat)
allDat

toString :: ([Char] -> String) -> [Char] -> Benchmarkable
toString = whnf

--------------------------------------------------------------------------
benchsByteArray = bgroup "ByteArray"
[ benchLength
, benchTake
, benchBreakElem
, benchReverse
, benchFilter
--, benchSplitAt
]
where
diffByteString :: (UArray Word8 -> a)
-> (ByteString.ByteString -> b)
-> [Word8]
-> [Benchmark]
diffByteString foundationBench textBench dat =
[ bench "UArray_W8" $ whnf foundationBench s
#ifdef BENCH_ALL
, bench "ByteString" $ whnf textBench t
#endif
]
where
s = fromList dat
t = ByteString.pack dat

allDat =
[ ("bs20", rdBytes20)
, ("bs200", rdBytes200)
, ("bs2000", rdBytes2000)
]
allDatSuffix s = fmap (first (\x -> x <> "-" <> s)) allDat

benchLength = bgroup "Length" $
fmap (\(n, dat) -> bgroup n $ diffByteString length ByteString.length dat) allDat

benchTake = bgroup "Take" $ mconcat $ fmap (\p ->
fmap (\(n, dat) -> bgroup n $ diffByteString (take p) (ByteString.take p) dat)
$ allDatSuffix (show p)
) [ 0, 10, 100 ]

benchBreakElem = bgroup "BreakElem" $ mconcat $ fmap (\p ->
fmap (\(n, dat) -> bgroup n $ diffByteString (fst . breakElem p) (fst . ByteString.break (== p)) dat)
$ allDatSuffix (show p)
) [ 19, 199, 0 ]

benchReverse = bgroup "Reverse" $
fmap (\(n, dat) -> bgroup n $ diffByteString reverse ByteString.reverse dat) allDat

benchFilter = bgroup "Filter" $
fmap (\(n, dat) -> bgroup n $ diffByteString (filter (> 100)) (ByteString.filter (> 100)) dat) allDat
--------------------------------------------------------------------------

benchsTypes = bgroup "types"
[ benchsString
, benchsByteArray
]

main = defaultMain
Expand Down