on master help sign in
Add prime sieves to benchmarks

Prime sieves are good benchmarks for scan and monad composition.

commita3c3db465f500f8dc6f8b8d2f002e64a544bf73c authorHarendra Kumar <harendra@composewell.com> dateSun 20 Sep 2020, 01:15 (6 years ago) parenta78e05b
1 file changed+33
benchmark/Streamly/Benchmark/Prelude/Serial.hs+33
benchmark/Streamly/Benchmark/Prelude/Serial.hs+33
@@ -855,6 +855,25 @@ o_1_space_mappingX4 value =
855855 ]
856856 ]
857857
858+{-# INLINE sieveScan #-}
859+sieveScan :: Monad m => SerialT m Int -> SerialT m Int
860+sieveScan =
861+ S.mapMaybe snd
862+ . S.scanlM' (\(primes, _) n -> do
863+ return $
864+ let ps = takeWhile (\p -> p * p <= n) primes
865+ in if P.all (\p -> n `mod` p /= 0) ps
866+ then (primes ++ [n], Just n)
867+ else (primes, Nothing)) ([2], Just 2)
868+
869+o_n_space_mapping :: Int -> [Benchmark]
870+o_n_space_mapping value =
871+ [ bgroup "mapping"
872+ [ benchIO "naive prime sieve"
873+ (\n -> S.sum $ sieveScan $ S.enumerateFromTo 2 (value + n))
874+ ]
875+ ]
876+
858877-------------------------------------------------------------------------------
859878-- Iteration/looping utilities
860879-------------------------------------------------------------------------------
@@ -1657,6 +1676,17 @@ o_1_space_monad value =
16571676 ]
16581677 ]
16591678
1679+-- This is a good benchmark but inefficient way to compute primes. As we see a
1680+-- new prime we keep appending a division filter for all the future numbers.
1681+{-# INLINE sieve #-}
1682+sieve :: Monad m => SerialT m Int -> SerialT m Int
1683+sieve s = do
1684+ r <- lift $ S.uncons s
1685+ case r of
1686+ Just (prime, rest) ->
1687+ prime `S.cons` sieve (S.filter (\n -> n `mod` prime /= 0) rest)
1688+ Nothing -> S.nil
1689+
16601690o_n_space_monad :: Int -> [Benchmark]
16611691o_n_space_monad value =
16621692 [ bgroup "Monad"
@@ -1668,6 +1698,8 @@ o_n_space_monad value =
16681698 toListM value serially
16691699 , benchIO "(>>=) (sqrt n x sqrt n) (toListSome)" $
16701700 toListSome value serially
1701+ , benchIO "naive prime sieve (n/4)"
1702+ (\n -> S.sum $ sieve $ S.enumerateFromTo 2 (value `div` 4 + n))
16711703 ]
16721704 ]
16731705
@@ -1823,6 +1855,7 @@ main = do
18231855
18241856 -- transformation
18251857 , o_n_space_traversable size
1858+ , o_n_space_mapping size
18261859 , o_n_space_grouping size
18271860
18281861 -- multi-stream