on master help sign in
Add isolated benchmarks to investigate special cases
commit3d79168e4b2ade60f5e690820718be9c537d2bda authorHarendra Kumar <harendra.kumar@gmail.com> dateTue 6 Nov 2018, 04:36 (8 years ago) parentbf4e5d8
2 files changed+156−24
benchmark/NanoBenchmarks.hs+82 streamly.cabal+74−24
benchmark/NanoBenchmarks.hsnew file+82
@@ -0,0 +1,82 @@
1+-------------------------------------------------------------------------------
2+-- Investigate specific benchmarks more closely in isolation, possibly looking
3+-- at GHC generated code for optimizing specific problematic cases.
4+-------------------------------------------------------------------------------
5+
6+{-# LANGUAGE ScopedTypeVariables #-}
7+import qualified Streamly.Streams.StreamD as S
8+import Gauge
9+
10+maxValue :: Int
11+maxValue = 100000
12+
13+{-# INLINE sourceUnfoldrM #-}
14+sourceUnfoldrM :: Monad m => S.Stream m Int
15+sourceUnfoldrM = S.unfoldrM step 0
16+ where
17+ step cnt =
18+ if cnt > maxValue
19+ then return Nothing
20+ else return (Just (cnt, cnt + 1))
21+
22+{-# INLINE sourceUnfoldrMN #-}
23+sourceUnfoldrMN :: Monad m => Int -> S.Stream m Int
24+sourceUnfoldrMN n = S.unfoldrM step n
25+ where
26+ step cnt =
27+ if cnt > n
28+ then return Nothing
29+ else return (Just (cnt, cnt + 1))
30+
31+-------------------------------------------------------------------------------
32+-- take-drop composition
33+-------------------------------------------------------------------------------
34+
35+takeAllDropOne :: Monad m => S.Stream m Int -> S.Stream m Int
36+takeAllDropOne = S.drop 1 . S.take maxValue
37+
38+-- Requires -fspec-constr-recursive=5 for better fused code
39+-- The number depends on how many times we compose it
40+
41+{-# INLINE takeDrop #-}
42+takeDrop :: Monad m => S.Stream m Int -> m ()
43+takeDrop = S.runStream .
44+ takeAllDropOne . takeAllDropOne . takeAllDropOne . takeAllDropOne
45+
46+-------------------------------------------------------------------------------
47+-- dropWhileFalse composition
48+-------------------------------------------------------------------------------
49+
50+dropWhileFalse :: Monad m => S.Stream m Int -> S.Stream m Int
51+dropWhileFalse = S.dropWhile (> maxValue)
52+
53+-- Requires -fspec-constr-recursive=5 for better fused code
54+-- The number depends on how many times we compose it
55+
56+{-# INLINE dropWhileFalseX4 #-}
57+dropWhileFalseX4 :: Monad m => S.Stream m Int -> m ()
58+dropWhileFalseX4 = S.runStream
59+ . dropWhileFalse . dropWhileFalse . dropWhileFalse . dropWhileFalse
60+
61+-------------------------------------------------------------------------------
62+-- iteration
63+-------------------------------------------------------------------------------
64+
65+{-# INLINE iterateSource #-}
66+iterateSource
67+ :: Monad m
68+ => (S.Stream m Int -> S.Stream m Int) -> Int -> Int -> S.Stream m Int
69+iterateSource g i n = f i (sourceUnfoldrMN n)
70+ where
71+ f (0 :: Int) m = g m
72+ f x m = g (f (x - 1) m)
73+
74+-- Keep only the benchmark that is to be investiagted and comment out the rest.
75+-- We keep all of them enabled by default for testing the build.
76+main :: IO ()
77+main = do
78+ defaultMain [bench "take-drop" $ nfIO $ takeDrop sourceUnfoldrM]
79+ defaultMain [bench "dropWhileFalseX4" $
80+ nfIO $ dropWhileFalseX4 sourceUnfoldrM]
81+ defaultMain [bench "iterate-mapM" $
82+ nfIO $ S.runStream $ iterateSource (S.mapM return) 100000 10]
streamly.cabal+74−24
@@ -266,7 +266,7 @@ test-suite maxrate
266266 , base >= 4.8 && < 5
267267 , clock >= 0.7.1 && < 0.8
268268 , hspec >= 2.0 && < 3
269− , random >= 1.0.0 && < 1.2
269+ , random >= 1.0.0 && < 2
270270 else
271271 buildable: False
272272
@@ -289,7 +289,7 @@ test-suite nested-loops
289289 build-Depends:
290290 streamly
291291 , base >= 4.8 && < 5
292− , random >= 1.0.0 && < 1.2
292+ , random >= 1.0.0 && < 2
293293
294294test-suite parallel-loops
295295 type: exitcode-stdio-1.0
@@ -300,7 +300,7 @@ test-suite parallel-loops
300300 build-Depends:
301301 streamly
302302 , base >= 4.8 && < 5
303− , random >= 1.0.0 && < 1.2
303+ , random >= 1.0.0 && < 2
304304
305305-------------------------------------------------------------------------------
306306-- Benchmarks
@@ -450,30 +450,80 @@ benchmark base
450450 -Wnoncanonical-monad-instances
451451 -Wnoncanonical-monadfail-instances
452452
453− build-depends:
454− base >= 4.8 && < 5
455− , deepseq >= 1.4.0 && < 1.5
456− , random >= 1.0 && < 2.0
457− , gauge >= 0.2.4 && < 0.3
453+ if flag(dev)
454+ buildable: True
455+ build-depends:
456+ base >= 4.8 && < 5
457+ , deepseq >= 1.4.0 && < 1.5
458+ , random >= 1.0 && < 2.0
459+ , gauge >= 0.2.4 && < 0.3
458460
459− , ghc-prim >= 0.2 && < 0.6
460− , containers >= 0.5 && < 0.7
461− , heaps >= 0.3 && < 0.4
461+ , ghc-prim >= 0.2 && < 0.6
462+ , containers >= 0.5 && < 0.7
463+ , heaps >= 0.3 && < 0.4
462464
463− -- concurrency
464− , atomic-primops >= 0.8 && < 0.9
465− , lockfree-queue >= 0.2.3 && < 0.3
466− , clock >= 0.7.1 && < 0.8
465+ -- concurrency
466+ , atomic-primops >= 0.8 && < 0.9
467+ , lockfree-queue >= 0.2.3 && < 0.3
468+ , clock >= 0.7.1 && < 0.8
467469
468− , exceptions >= 0.8 && < 0.11
469− , monad-control >= 1.0 && < 2
470− , mtl >= 2.2 && < 3
471− , transformers >= 0.4 && < 0.6
472− , transformers-base >= 0.4 && < 0.5
470+ , exceptions >= 0.8 && < 0.11
471+ , monad-control >= 1.0 && < 2
472+ , mtl >= 2.2 && < 3
473+ , transformers >= 0.4 && < 0.6
474+ , transformers-base >= 0.4 && < 0.5
473475
474− if impl(ghc < 8.0)
475− build-depends:
476− semigroups >= 0.18 && < 0.19
476+ if impl(ghc < 8.0)
477+ build-depends:
478+ semigroups >= 0.18 && < 0.19
479+ else
480+ buildable: False
481+
482+executable nano-bench
483+ hs-source-dirs: benchmark, src
484+ main-is: NanoBenchmarks.hs
485+ other-modules: Streamly.SVar
486+ , Streamly.Streams.StreamK
487+ , Streamly.Streams.StreamD
488+ default-language: Haskell2010
489+ ghc-options: -O2 -Wall
490+
491+ if flag(dev)
492+ buildable: True
493+ build-depends:
494+ base >= 4.8 && < 5
495+ , gauge >= 0.2.4 && < 0.3
496+ , ghc-prim >= 0.2 && < 0.6
497+ , containers >= 0.5 && < 0.7
498+ , heaps >= 0.3 && < 0.4
499+
500+ -- concurrency
501+ , atomic-primops >= 0.8 && < 0.9
502+ , lockfree-queue >= 0.2.3 && < 0.3
503+ , clock >= 0.7.1 && < 0.8
504+
505+ , exceptions >= 0.8 && < 0.11
506+ , monad-control >= 1.0 && < 2
507+ , mtl >= 2.2 && < 3
508+ , transformers >= 0.4 && < 0.6
509+ else
510+ buildable: False
511+
512+executable adaptive
513+ hs-source-dirs: benchmark
514+ main-is: Adaptive.hs
515+ default-language: Haskell2010
516+ ghc-options: -O2 -Wall
517+
518+ if flag(dev)
519+ buildable: True
520+ build-depends:
521+ streamly
522+ , base >= 4.8 && < 5
523+ , gauge >= 0.2.4 && < 0.3
524+ , random >= 1.0 && < 2.0
525+ else
526+ buildable: False
477527
478528executable chart
479529 default-language: Haskell2010
@@ -531,7 +581,7 @@ executable MergeSort
531581 build-Depends:
532582 streamly
533583 , base >= 4.8 && < 5
534− , random >= 1.0.0 && < 1.2
584+ , random >= 1.0.0 && < 2
535585 else
536586 buildable: False
537587