1
Fork 0
solar-conflux/purescript/slice/src/Benchmarks.purs
2023-10-29 01:21:05 +02:00

111 lines
3.5 KiB
Plaintext

module Benchmarks where
import Prelude
import Benchotron.Core (Benchmark, benchFn, benchFn', mkBenchmark)
import Control.Monad.ST.Internal as ST
import Control.Monad.ST.Internal as STRef
import Data.Array (foldMap, foldr, foldl, (..))
import Data.Array.NonEmpty as NonEmptyArray
import Data.Array.ST as STArray
import Data.List (List(..), (:))
import Data.List as List
import Data.Maybe (Maybe(..))
import Data.Monoid.Additive (Additive(..))
import Data.ZipperArray (ZipperArray)
import Data.ZipperArray as ZipperArray
import Slice (Slice)
import Slice as Slice
import Test.QuickCheck (arbitrary)
import Test.QuickCheck.Gen (vectorOf)
listSum :: List Int -> Int
listSum (head:tail) = head + listSum tail
listSum _ = 0
listSumTCO :: List Int -> Int
listSumTCO = go 0
where
go s Nil = s
go s (head:tail) = go (s + head) tail
zipperSum :: ZipperArray Int -> Int
zipperSum arr = ZipperArray.current arr + case ZipperArray.goNext arr of
Nothing -> 0
Just next -> zipperSum next
sliceSum :: Slice Int -> Int
sliceSum arr = case Slice.uncons arr of
Nothing -> 0
Just { head, tail } -> head + sliceSum tail
sliceSumTCO :: Slice Int -> Int
sliceSumTCO = go 0
where
go s arr = case Slice.uncons arr of
Nothing -> s
Just { head, tail } -> go (s + head) tail
listFib :: Int -> List Int
listFib = go 1 1
where
go a b 0 = Nil
go a b n = c:go c a (n - 1)
where
c = a + b
stArrayFib :: Int -> Array Int
stArrayFib to = STArray.run do
a <- STRef.new 1
b <- STRef.new 1
result <- STArray.empty
ST.for 1 to \_ -> do
a' <- STRef.read a
b' <- STRef.read b
let c = a' + b'
void
$ STArray.push c result
<* STRef.write a' b
<* STRef.write c a
pure result
foreign import arraySum :: Array Int -> Int
foreign import arrayFib :: Int -> Array Int
benchSum :: Benchmark
benchSum = mkBenchmark
{ slug: "sum"
, title: "Finding the sum of a sequence of integers"
, sizes: (1..10) <#> (_ * 1000)
, sizeInterpretation: "Number of elements in the array"
, inputsPerSize: 1
, gen: \n -> NonEmptyArray.cons' <$> arbitrary <*> vectorOf n arbitrary
, functions: [
-- benchFn' "array" arraySum NonEmptyArray.toArray
benchFn' "list" listSum List.fromFoldable
, benchFn' "list (tail call optimization" listSumTCO List.fromFoldable
, benchFn' "zipper" zipperSum ZipperArray.fromNonEmptyArray
, benchFn' "array slice" sliceSum (NonEmptyArray.toArray >>> Slice.fromArray)
, benchFn' "array slice (tail call optimization)" sliceSumTCO (NonEmptyArray.toArray >>> Slice.fromArray)
, benchFn' "array foldr" (foldr (+) 0) NonEmptyArray.toArray
, benchFn' "array foldl" (foldl (+) 0) NonEmptyArray.toArray
, benchFn' "array foldMap" (foldMap Additive) NonEmptyArray.toArray
, benchFn' "list foldr" (foldr (+) 0) List.fromFoldable
, benchFn' "list foldl" (foldl (+) 0) List.fromFoldable
, benchFn' "list foldMap" (foldMap Additive) List.fromFoldable
]
}
benchFib :: Benchmark
benchFib = mkBenchmark
{ slug: "fibonacci"
, title: "Generating the first n fibonacci numbers as a sequence"
, sizes: (1..10) <#> (_ * 100)
, sizeInterpretation: "Number of elements"
, inputsPerSize: 1
, gen: pure
, functions: [ benchFn "array" arrayFib
, benchFn "list" listFib
, benchFn "stArray" stArrayFib
]
}