packages feed

streamly-0.10.1: benchmark/streamly-benchmarks.cabal

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-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 impl(ghc >= 9.8)
      ghc-options:
        -Wno-missing-role-annotations

    if flag(has-llvm)
      ghc-options: -fllvm

    if flag(dev)
      ghc-options:    -Wmissed-specialisations
                      -Wall-missed-specialisations

common optimization-options
  if flag(opt)
    ghc-options: -O2
                 -fdicts-strict
                 -fspec-constr-recursive=16
                 -fmax-worker-args=16

    -- For this to be effective it must come after the -O2 option
    if flag(dev) || flag(debug)
      ghc-options: -fno-ignore-asserts

    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.20
    , deepseq             >= 1.4.1 && < 1.6
    , mtl                 >= 2.2   && < 2.3.2

    -- other libraries
    , exceptions >= 0.8   && < 0.11
    , random              >= 1.0   && < 2.0
    , transformers        >= 0.4   && < 0.7
    , containers          >= 0.5   && < 0.8
    , 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.6
    , ghc-prim          >= 0.4   && < 0.12
    , tasty-bench       >= 0.3 && < 0.4
    , tasty             >= 1.4.1 && < 1.6
    , streamly-core

  if !flag(use-streamly-core)
    build-depends: streamly

  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.22
                     , inspection-testing >= 0.4   && < 0.6
  -- 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.Unbox
  import: bench-options
  type: exitcode-stdio-1.0
  hs-source-dirs: .
  cpp-options: -DUSE_UNBOX
  main-is: Streamly/Benchmark/Data/Serialize.hs

benchmark Data.Unbox.Derive.TH
  import: bench-options
  type: exitcode-stdio-1.0
  hs-source-dirs: .
  cpp-options: -DUSE_UNBOX
  cpp-options: -DUSE_TH
  main-is: Streamly/Benchmark/Data/Serialize.hs

benchmark Data.Serialize
  import: bench-options
  type: exitcode-stdio-1.0
  hs-source-dirs: .
  cpp-options: -DUSE_TH
  main-is: Streamly/Benchmark/Data/Serialize.hs
  build-depends: QuickCheck, template-haskell
  other-modules:
      Streamly.Benchmark.Data.Serialize.TH
      Streamly.Benchmark.Data.Serialize.RecCompatible
      Streamly.Benchmark.Data.Serialize.RecNonCompatible
  if flag(limit-build-mem)
    ghc-options: +RTS -M1000M -RTS

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 -M2000M -RTS

benchmark Data.ParserK
  import: bench-options
  type: exitcode-stdio-1.0
  hs-source-dirs: Streamly/Benchmark/Data
  cpp-options: -DBENCH_SINGULAR
  main-is: ParserK.hs
  if impl(ghcjs)
    buildable: False
  else
    buildable: True
    build-depends: exceptions >= 0.8   && < 0.11

benchmark Data.ParserK.Chunked
  import: bench-options
  type: exitcode-stdio-1.0
  hs-source-dirs: Streamly/Benchmark/Data
  cpp-options: -DBENCH_CHUNKED
  main-is: ParserK.hs
  if impl(ghcjs)
    buildable: False
  else
    buildable: True
    build-depends: exceptions >= 0.8   && < 0.11

benchmark Data.ParserK.Chunked.Generic
  import: bench-options
  type: exitcode-stdio-1.0
  hs-source-dirs: Streamly/Benchmark/Data
  cpp-options: -DBENCH_CHUNKED_GENERIC
  main-is: ParserK.hs
  if impl(ghcjs)
    buildable: False
  else
    buildable: True
    build-depends: exceptions >= 0.8   && < 0.11

-------------------------------------------------------------------------------
-- Raw Streams
-------------------------------------------------------------------------------

benchmark Data.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.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.StreamK.Alt
  import: bench-options
  type: exitcode-stdio-1.0
  hs-source-dirs: Streamly/Benchmark/Data/Stream
  main-is: StreamKAlt.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.MutArray
  import: bench-options
  type: exitcode-stdio-1.0
  main-is: Streamly/Benchmark/Data/MutArray.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

benchmark Unicode.Parser
  import: bench-options
  type: exitcode-stdio-1.0
  hs-source-dirs: Streamly/Benchmark/Unicode
  main-is: Parser.hs