cabal-version: 2.2 name: streamly-benchmarks version: 0.0.0 synopsis: Benchmarks for streamly description: Benchmarks are separated from the main package because we want to have a library for benchmarks to reuse the code across different benchmark executables. For example, we have common benchmarking code for different types of streams. We need different benchmarking executables for serial, async, ahead style streams, therefore, we need to use the common code in several benchmarks, just changing the type of the stream. It takes a long time to compile this file and it gets compiled for each benchmark once if we do not have a library. Cabal does not support internal libraries without per-component builds and per-component builds are not supported with Configure, so we are not left with any other choice. flag fusion-plugin description: Use fusion plugin for benchmarks and executables manual: True default: False flag limit-build-mem description: Limits memory when building the executables manual: True default: False flag inspection description: Enable inspection testing manual: True default: False flag debug description: Debug build with asserts enabled manual: True default: False flag dev description: Development build manual: True default: False flag include-strict-utf8 description: Include strict utf8 input benchmarks manual: True default: False flag has-llvm description: Use llvm backend for better performance manual: True default: False flag opt description: off=-O0 (faster builds), on=-O2 manual: True default: True flag use-gauge description: Use gauge instead of tasty-bench for benchmarking manual: True default: False flag use-streamly-core description: Benchmark only core package manual: True default: False flag use-prelude description: Use Prelude instead of Data.Stream for serial benchmarks manual: True default: False ------------------------------------------------------------------------------- -- Common stanzas ------------------------------------------------------------------------------- common default-extensions default-extensions: BangPatterns CApiFFI CPP ConstraintKinds DeriveDataTypeable DeriveGeneric DeriveTraversable ExistentialQuantification FlexibleContexts FlexibleInstances GeneralizedNewtypeDeriving InstanceSigs KindSignatures LambdaCase MagicHash MultiParamTypeClasses PatternSynonyms RankNTypes RecordWildCards ScopedTypeVariables TupleSections TypeApplications TypeFamilies TypeOperators ViewPatterns -- MonoLocalBinds, enabled by TypeFamilies, causes performance -- regressions. Disable it. This must come after TypeFamilies, -- otherwise TypeFamilies will enable it again. NoMonoLocalBinds -- UndecidableInstances -- Does not show any perf impact -- UnboxedTuples -- interferes with (#.) common compile-options import: default-extensions default-language: Haskell2010 if flag(use-streamly-core) cpp-options: -DUSE_STREAMLY_CORE if flag(dev) cpp-options: -DDEVBUILD if flag(include-strict-utf8) cpp-options: -DINCLUDE_STRICT_UTF8 if flag(inspection) cpp-options: -DINSPECTION ghc-options: -Weverything -Wno-implicit-prelude -Wno-missing-deriving-strategies -Wno-missing-exported-signatures -Wno-missing-import-lists -Wno-missing-local-signatures -Wno-missing-safe-haskell-mode -Wno-missed-specialisations -Wno-all-missed-specialisations -Wno-monomorphism-restriction -Wno-prepositive-qualified-module -Wno-unsafe -Wno-unused-packages -Rghc-timing if impl(ghc >= 9.2) ghc-options: -Wno-missing-kind-signatures -Wno-operator-whitespace if flag(has-llvm) ghc-options: -fllvm if flag(dev) ghc-options: -Wmissed-specialisations -Wall-missed-specialisations if flag(dev) || flag(debug) ghc-options: -fno-ignore-asserts common optimization-options if flag(opt) ghc-options: -O2 -fdicts-strict -fspec-constr-recursive=16 -fmax-worker-args=16 if flag(fusion-plugin) && !impl(ghcjs) && !impl(ghc < 8.6) ghc-options: -fplugin Fusion.Plugin else ghc-options: -O0 common lib-options import: compile-options, optimization-options common bench-depends build-depends: -- Core libraries shipped with ghc, the min and max -- constraints of these libraries should match with -- the GHC versions we support base >= 4.9 && < 4.18 , deepseq >= 1.4.1 && < 1.5 , mtl >= 2.2 && < 2.3 -- other libraries , random >= 1.0 && < 2.0 , transformers >= 0.4 && < 0.7 , containers >= 0.5 && < 0.7 , hashable >= 1.3 && < 1.5 , unordered-containers >= 0.2 && < 0.3 , process >= 1.4 && < 1.7 , directory >= 1.2.2 && < 1.4 , filepath >= 1.4.1 && < 1.5 , ghc-prim >= 0.4 && < 0.10 if flag(use-streamly-core) build-depends: streamly-core else build-depends: streamly , streamly-core if flag(use-gauge) build-depends: gauge >= 0.2.4 && < 0.3 else build-depends: tasty-bench >= 0.3 && < 0.4 , tasty >= 1.4.1 && < 1.5 mixins: tasty-bench (Test.Tasty.Bench as Gauge , Test.Tasty.Bench as Gauge.Main ) if flag(fusion-plugin) && !impl(ghcjs) && !impl(ghc < 8.6) build-depends: fusion-plugin >= 0.2 && < 0.3 if flag(inspection) build-depends: template-haskell >= 2.14 && < 2.20 , inspection-testing >= 0.4 && < 0.5 -- Array uses a Storable constraint in dev build making several inspection -- tests fail if flag(dev) && flag(inspection) build-depends: inspection-and-dev-flags-cannot-be-used-together ------------------------------------------------------------------------------- -- Library ------------------------------------------------------------------------------- library import: lib-options, bench-depends hs-source-dirs: lib exposed-modules: Streamly.Benchmark.Common , Streamly.Benchmark.Common.Handle if flag(use-prelude) exposed-modules: Streamly.Benchmark.Prelude ------------------------------------------------------------------------------- -- Benchmarks ------------------------------------------------------------------------------- common bench-options import: compile-options, optimization-options, bench-depends include-dirs: . ghc-options: -rtsopts if flag(limit-build-mem) ghc-options: +RTS -M512M -RTS build-depends: streamly-benchmarks == 0.0.0 -- Some benchmarks are threaded some are not common bench-options-threaded import: compile-options, optimization-options, bench-depends -- -threaded and -N2 is important because some GC and space leak issues -- trigger only with these options. ghc-options: -threaded -rtsopts -with-rtsopts "-N2" if flag(limit-build-mem) ghc-options: +RTS -M512M -RTS build-depends: streamly-benchmarks == 0.0.0 ------------------------------------------------------------------------------- -- Serial Streams ------------------------------------------------------------------------------- benchmark Data.Stream import: bench-options type: exitcode-stdio-1.0 hs-source-dirs: Streamly/Benchmark/Data main-is: Stream.hs other-modules: Stream.Generate Stream.Eliminate Stream.Transform Stream.Reduce Stream.Expand Stream.Lift Stream.Common if !flag(use-streamly-core) other-modules: Stream.Exceptions if flag(limit-build-mem) if flag(dev) ghc-options: +RTS -M3500M -RTS else ghc-options: +RTS -M2500M -RTS -- Use StreamK functions where possible, converting to StreaK to StreamD benchmark Data.Stream.StreamDK import: bench-options type: exitcode-stdio-1.0 hs-source-dirs: Streamly/Benchmark/Data main-is: Stream.hs other-modules: Stream.Generate Stream.Eliminate Stream.Transform Stream.Reduce Stream.Expand Stream.Lift Stream.Common if !flag(use-streamly-core) other-modules: Stream.Exceptions -- Cannot use USE_STREAMK and USE_PRELUDE together if flag(use-prelude) buildable: False cpp-options: -DUSE_STREAMK if flag(limit-build-mem) if flag(dev) ghc-options: +RTS -M3500M -RTS else ghc-options: +RTS -M2500M -RTS benchmark Data.Stream.Concurrent import: bench-options-threaded type: exitcode-stdio-1.0 hs-source-dirs: Streamly/Benchmark/Data/Stream/, Streamly/Benchmark/Data/ main-is: Concurrent.hs other-modules: Stream.ConcurrentCommon Stream.Common if flag(use-streamly-core) || impl(ghcjs) buildable: False else buildable: True benchmark Data.Stream.ConcurrentInterleaved import: bench-options-threaded type: exitcode-stdio-1.0 hs-source-dirs: Streamly/Benchmark/Data/Stream/, Streamly/Benchmark/Data/ main-is: ConcurrentInterleaved.hs other-modules: Stream.ConcurrentCommon Stream.Common if flag(use-streamly-core) || impl(ghcjs) buildable: False else buildable: True benchmark Data.Stream.ConcurrentEager import: bench-options-threaded type: exitcode-stdio-1.0 hs-source-dirs: Streamly/Benchmark/Data/Stream/, Streamly/Benchmark/Data/ main-is: ConcurrentEager.hs other-modules: Stream.ConcurrentCommon Stream.Common if flag(use-streamly-core) || impl(ghcjs) buildable: False else buildable: True benchmark Data.Stream.ConcurrentOrdered import: bench-options-threaded type: exitcode-stdio-1.0 hs-source-dirs: Streamly/Benchmark/Data/Stream/, Streamly/Benchmark/Data/ main-is: ConcurrentOrdered.hs other-modules: Stream.ConcurrentCommon Stream.Common if flag(use-streamly-core) || impl(ghcjs) buildable: False else buildable: True benchmark Data.Unfold import: bench-options type: exitcode-stdio-1.0 hs-source-dirs: . main-is: Streamly/Benchmark/Data/Unfold.hs if flag(use-streamly-core) || impl(ghcjs) buildable: False else buildable: True benchmark Data.Fold import: bench-options type: exitcode-stdio-1.0 hs-source-dirs: Streamly/Benchmark/Data main-is: Fold.hs if flag(use-streamly-core) || impl(ghcjs) buildable: False else buildable: True benchmark Data.Fold.Window import: bench-options type: exitcode-stdio-1.0 hs-source-dirs: Streamly/Benchmark/Data/Fold main-is: Window.hs if flag(use-streamly-core) buildable: False else buildable: True benchmark Data.Parser import: bench-options type: exitcode-stdio-1.0 hs-source-dirs: Streamly/Benchmark/Data main-is: Parser.hs if impl(ghcjs) buildable: False else buildable: True build-depends: exceptions >= 0.8 && < 0.11 if flag(limit-build-mem) if flag(dev) ghc-options: +RTS -M3000M -RTS else ghc-options: +RTS -M1000M -RTS benchmark Data.Parser.ParserK import: bench-options type: exitcode-stdio-1.0 hs-source-dirs: Streamly/Benchmark/Data/Parser main-is: ParserK.hs if impl(ghcjs) buildable: False else buildable: True build-depends: exceptions >= 0.8 && < 0.11 -- Note: to use this we have to set DISABLE_FUSION in ParserD.hs so that -- the rewrite rules are disabled. We can also use the "no-fusion" build -- flag but we need to keep in mind that it disables fusion for streams -- as well. benchmark Data.Parser.FromParserK import: bench-options type: exitcode-stdio-1.0 hs-source-dirs: Streamly/Benchmark/Data/Parser cpp-options: -DFROM_PARSERK main-is: ParserK.hs if flag(use-streamly-core) || impl(ghcjs) buildable: False else buildable: True build-depends: exceptions >= 0.8 && < 0.11 ------------------------------------------------------------------------------- -- Raw Streams ------------------------------------------------------------------------------- benchmark Data.Stream.StreamD import: bench-options type: exitcode-stdio-1.0 hs-source-dirs: Streamly/Benchmark/Data/Stream main-is: StreamD.hs if impl(ghcjs) buildable: False benchmark Data.Stream.StreamK import: bench-options type: exitcode-stdio-1.0 hs-source-dirs: Streamly/Benchmark/Data/Stream main-is: StreamK.hs if impl(ghcjs) buildable: False benchmark Data.Stream.ToStreamK import: bench-options type: exitcode-stdio-1.0 hs-source-dirs: Streamly/Benchmark/Data/Stream main-is: ToStreamK.hs if !flag(dev) || impl(ghcjs) buildable: False benchmark Data.Stream.StreamK.Alt import: bench-options type: exitcode-stdio-1.0 hs-source-dirs: Streamly/Benchmark/Data/Stream main-is: StreamDK.hs if !flag(dev) || impl(ghcjs) buildable: False executable nano-bench import: bench-options hs-source-dirs: . main-is: NanoBenchmarks.hs if !flag(dev) buildable: False ------------------------------------------------------------------------------- -- Streamly.Prelude ------------------------------------------------------------------------------- benchmark Prelude import: bench-options type: exitcode-stdio-1.0 hs-source-dirs: Streamly/Benchmark/Data main-is: Stream.hs other-modules: Stream.Generate Stream.Eliminate Stream.Transform Stream.Reduce Stream.Expand Stream.Lift Stream.Common Stream.Split Stream.Exceptions cpp-options: -DUSE_PRELUDE if !flag(use-prelude) buildable: False if flag(limit-build-mem) if flag(dev) ghc-options: +RTS -M3500M -RTS else ghc-options: +RTS -M2500M -RTS benchmark Prelude.WSerial import: bench-options type: exitcode-stdio-1.0 hs-source-dirs: Streamly/Benchmark/Prelude main-is: WSerial.hs cpp-options: -DUSE_PRELUDE if !flag(use-prelude) buildable: False if flag(limit-build-mem) ghc-options: +RTS -M750M -RTS benchmark Prelude.Merge import: bench-options type: exitcode-stdio-1.0 hs-source-dirs: Streamly/Benchmark/Prelude main-is: Merge.hs cpp-options: -DUSE_PRELUDE if !flag(use-prelude) buildable: False benchmark Prelude.ZipSerial import: bench-options type: exitcode-stdio-1.0 hs-source-dirs: Streamly/Benchmark/Prelude main-is: ZipSerial.hs cpp-options: -DUSE_PRELUDE if !flag(use-prelude) buildable: False benchmark Prelude.ZipAsync import: bench-options type: exitcode-stdio-1.0 hs-source-dirs: Streamly/Benchmark/Prelude main-is: ZipAsync.hs cpp-options: -DUSE_PRELUDE if !flag(use-prelude) buildable: False if flag(limit-build-mem) ghc-options: +RTS -M1000M -RTS benchmark Prelude.Ahead import: bench-options-threaded type: exitcode-stdio-1.0 hs-source-dirs: Streamly/Benchmark/Prelude main-is: Ahead.hs cpp-options: -DUSE_PRELUDE if !flag(use-prelude) buildable: False benchmark Prelude.Async import: bench-options-threaded type: exitcode-stdio-1.0 hs-source-dirs: Streamly/Benchmark/Prelude main-is: Async.hs cpp-options: -DUSE_PRELUDE if !flag(use-prelude) buildable: False benchmark Prelude.WAsync import: bench-options-threaded type: exitcode-stdio-1.0 hs-source-dirs: Streamly/Benchmark/Prelude main-is: WAsync.hs cpp-options: -DUSE_PRELUDE if !flag(use-prelude) buildable: False benchmark Prelude.Parallel import: bench-options-threaded type: exitcode-stdio-1.0 hs-source-dirs: Streamly/Benchmark/Prelude main-is: Parallel.hs cpp-options: -DUSE_PRELUDE if !flag(use-prelude) buildable: False if flag(limit-build-mem) ghc-options: +RTS -M2000M -RTS ------------------------------------------------------------------------------- -- Concurrent Streams ------------------------------------------------------------------------------- benchmark Prelude.Concurrent import: bench-options-threaded type: exitcode-stdio-1.0 hs-source-dirs: Streamly/Benchmark/Prelude main-is: Concurrent.hs cpp-options: -DUSE_PRELUDE if !flag(use-prelude) buildable: False benchmark Prelude.Adaptive import: bench-options-threaded type: exitcode-stdio-1.0 hs-source-dirs: Streamly/Benchmark/Prelude main-is: Adaptive.hs cpp-options: -DUSE_PRELUDE if !flag(use-prelude) buildable: False benchmark Prelude.Rate import: bench-options-threaded type: exitcode-stdio-1.0 hs-source-dirs: Streamly/Benchmark/Prelude main-is: Rate.hs cpp-options: -DUSE_PRELUDE if !flag(use-prelude) buildable: False ------------------------------------------------------------------------------- -- Array Benchmarks ------------------------------------------------------------------------------- benchmark Data.Array.Generic import: bench-options type: exitcode-stdio-1.0 hs-source-dirs: ., Streamly/Benchmark/Data main-is: Streamly/Benchmark/Data/Array/Generic.hs other-modules: Stream.Common if flag(use-streamly-core) buildable: False else buildable: True if flag(limit-build-mem) ghc-options: +RTS -M1000M -RTS benchmark Data.SmallArray import: bench-options type: exitcode-stdio-1.0 main-is: Streamly/Benchmark/Data/Array/SmallArray.hs if flag(dev) && !flag(use-streamly-core) buildable: True else buildable: False benchmark Data.Array import: bench-options type: exitcode-stdio-1.0 hs-source-dirs: ., Streamly/Benchmark/Data main-is: Streamly/Benchmark/Data/Array.hs other-modules: Stream.Common if flag(use-streamly-core) buildable: False else buildable: True if flag(limit-build-mem) ghc-options: +RTS -M1500M -RTS benchmark Data.Array.Mut import: bench-options type: exitcode-stdio-1.0 main-is: Streamly/Benchmark/Data/Array/Mut.hs if flag(limit-build-mem) ghc-options: +RTS -M1500M -RTS if flag(use-streamly-core) buildable: False else buildable: True ------------------------------------------------------------------------------- -- Ring Benchmarks ------------------------------------------------------------------------------- benchmark Data.Ring.Unboxed import: bench-options type: exitcode-stdio-1.0 main-is: Streamly/Benchmark/Data/Ring/Unboxed.hs if flag(limit-build-mem) ghc-options: +RTS -M1500M -RTS ------------------------------------------------------------------------------- -- Array Stream Benchmarks ------------------------------------------------------------------------------- benchmark Data.Array.Stream import: bench-options type: exitcode-stdio-1.0 hs-source-dirs: Streamly/Benchmark/Data/Array main-is: Stream.hs if flag(use-streamly-core) || impl(ghcjs) buildable: False else buildable: True build-depends: exceptions >= 0.8 && < 0.11 ------------------------------------------------------------------------------- -- FileIO Benchmarks ------------------------------------------------------------------------------- benchmark FileSystem.Handle import: bench-options type: exitcode-stdio-1.0 hs-source-dirs: Streamly/Benchmark/FileSystem main-is: Handle.hs other-modules: Handle.Read , Handle.ReadWrite if flag(limit-build-mem) ghc-options: +RTS -M1000M -RTS if flag(use-streamly-core) buildable: False else buildable: True ------------------------------------------------------------------------------- -- Unicode Benchmarks ------------------------------------------------------------------------------- benchmark Unicode.Stream import: bench-options type: exitcode-stdio-1.0 hs-source-dirs: Streamly/Benchmark/Unicode main-is: Stream.hs if flag(limit-build-mem) ghc-options: +RTS -M1000M -RTS if flag(use-streamly-core) buildable: False else buildable: True benchmark Unicode.Char import: bench-options type: exitcode-stdio-1.0 hs-source-dirs: Streamly/Benchmark/Unicode main-is: Char.hs -- Takes too much memory for ghcjs if flag(use-streamly-core) || impl(ghcjs) buildable: False benchmark Unicode.Utf8 import: bench-options type: exitcode-stdio-1.0 hs-source-dirs: Streamly/Benchmark/Unicode main-is: Utf8.hs if flag(use-streamly-core) buildable: False else buildable: True