packages feed

streamly-0.7.2: 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 benchmarks once if we do not have a library.  Cabal
  does no 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 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 has-llvm
  description: Use llvm backend for better performance
  manual: True
  default: False

flag no-charts
  description: Disable benchmark charts in development build
  manual: True
  default: False

-------------------------------------------------------------------------------
-- Common stanzas
-------------------------------------------------------------------------------

common compile-options
    default-language: Haskell2010

    if flag(dev)
      cpp-options:    -DDEVBUILD

    if flag(inspection)
      cpp-options:    -DINSPECTION

    ghc-options:      -Wall

    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

    if impl(ghc >= 8.0)
      ghc-options:    -Wcompat
                      -Wunrecognised-warning-flags
                      -Widentities
                      -Wincomplete-record-updates
                      -Wincomplete-uni-patterns
                      -Wredundant-constraints
                      -Wnoncanonical-monad-instances

common optimization-options
  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

-- We need optimization options here to optimize internal (non-inlined)
-- versions of functions. Also, we have some benchmarking inspection tests
-- part of the library when built with --benchmarks flag. Thos tests fail
-- if we do not use optimization options here. It was observed that due to
-- -O2 here some concurrent/nested benchmarks improved and others regressed.
-- We can investigate a bit more here why the regression occurred.
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.8   && < 5
    , deepseq             >= 1.4.1 && < 1.5
    , mtl                 >= 2.2   && < 3

    -- other libraries
    , streamly            >= 0.7.0
    , random              >= 1.0   && < 2.0
    , gauge               >= 0.2.4 && < 0.3
  if flag(fusion-plugin) && !impl(ghcjs) && !impl(ghc < 8.6)
    build-depends:
        fusion-plugin     >= 0.2   && < 0.3
  if impl(ghc < 8.0)
    build-depends:
        transformers  >= 0.4 && < 0.6
  if flag(inspection)
    build-depends:     template-haskell   >= 2.14  && < 2.17
                     , 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

library lib-prelude
    import: lib-options, bench-depends
    hs-source-dirs:    lib, .
    exposed-modules:
                       Streamly.Benchmark.Prelude
    other-modules:     Streamly.Benchmark.Common
                     , Streamly.Benchmark.Prelude.NestedOps
    -- XXX GHCJS build fails for this library.
    if impl(ghcjs)
      buildable: False
    else
      build-depends: ghc-prim
      buildable: True

-------------------------------------------------------------------------------
-- Benchmarks
-------------------------------------------------------------------------------

-- Whatever stack size below 32K we use GHC seems to report the stack size as
-- 32K at crash. Even K0K works. Therefore it probably does not make sense to
-- set it to lower than 32K.

common bench-options
  import: compile-options, optimization-options, bench-depends
  ghc-options: -with-rtsopts "-T -K32K -M16M"
  build-depends: streamly-benchmarks

-- 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 -with-rtsopts "-T -N2 -K32K -M16M"
  build-depends: streamly-benchmarks

-- XXX the individual modules can just export a bunch of gauge Benchmark
-- grouped by space usage and then we can combine the groups in just four
-- different top level drivers.

-------------------------------------------------------------------------------
-- Serial Streams
-------------------------------------------------------------------------------

benchmark linear
-- benchmark serial-o-1-space
  import: bench-options
  type: exitcode-stdio-1.0
  ghc-options: -with-rtsopts "-T -K36K -M16M"
  hs-source-dirs: Streamly/Benchmark/Prelude/Serial
  main-is: O_1_Space.hs
  if impl(ghcjs)
    buildable: False
  else
    build-depends: lib-prelude
    buildable: True

benchmark serial-o-n-heap
  import: bench-options
  type: exitcode-stdio-1.0
  ghc-options: -with-rtsopts "-T -K36K -M128M"
  hs-source-dirs: Streamly/Benchmark/Prelude/Serial
  main-is: O_n_Heap.hs
  if impl(ghcjs)
    buildable: False
  else
    build-depends: lib-prelude
    buildable: True

benchmark serial-o-n-stack
  import: bench-options
  type: exitcode-stdio-1.0
  ghc-options: -with-rtsopts "-T -K1M -M16M"
  hs-source-dirs: Streamly/Benchmark/Prelude/Serial
  main-is: O_n_Stack.hs
  if impl(ghcjs)
    buildable: False
  else
    build-depends: lib-prelude
    buildable: True

benchmark serial-o-n-space
  import: bench-options
  type: exitcode-stdio-1.0
  ghc-options: -with-rtsopts "-T -K16M -M64M"
  hs-source-dirs: Streamly/Benchmark/Prelude/Serial
  main-is: O_n_Space.hs
  if impl(ghcjs)
    buildable: False
  else
    build-depends: lib-prelude
    buildable: True

benchmark fold
  import: bench-options
  type: exitcode-stdio-1.0
  ghc-options: -rtsopts
  hs-source-dirs: Streamly/Benchmark/Data
  main-is: Fold.hs
  if impl(ghcjs)
    buildable: False
  else
    buildable: True

benchmark unfold
  import: bench-options
  type: exitcode-stdio-1.0
  ghc-options: -rtsopts
  hs-source-dirs: ., Streamly/Benchmark/Data
  main-is: Unfold.hs
  other-modules: Streamly.Benchmark.Data.NestedUnfoldOps
  if impl(ghcjs)
    buildable: False
  else
    buildable: True

benchmark parser
  import: bench-options
  type: exitcode-stdio-1.0
  ghc-options: -with-rtsopts "-T -K36K -M16M"
  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

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

library lib-base
    import: lib-options, bench-depends
    hs-source-dirs: .
    exposed-modules:
                       Streamly.Benchmark.Data.Stream.StreamD
                     , Streamly.Benchmark.Data.Stream.StreamK
                     , Streamly.Benchmark.Data.Stream.StreamDK
    if impl(ghcjs)
      buildable: False
    else
      build-depends: streamly-benchmarks
      buildable: True

benchmark base
-- benchmark base-o-1-space
  import: bench-options
  type: exitcode-stdio-1.0
  cpp-options: -DO_1_SPACE
  ghc-options: -with-rtsopts "-T -K36K -M16M"
  hs-source-dirs: Streamly/Benchmark/Data/Stream
  main-is: BaseStreams.hs
  if impl(ghcjs)
    buildable: False
  else
    build-depends: lib-base
    buildable: True

benchmark base-o-n-heap
  import: bench-options
  type: exitcode-stdio-1.0
  cpp-options: -DO_N_HEAP
  ghc-options: -with-rtsopts "-T -K36K -M64M"
  hs-source-dirs: Streamly/Benchmark/Data/Stream
  main-is: BaseStreams.hs
  if impl(ghcjs)
    buildable: False
  else
    build-depends: lib-base
    buildable: True

benchmark base-o-n-stack
  import: bench-options
  type: exitcode-stdio-1.0
  cpp-options: -DO_N_STACK
  ghc-options: -with-rtsopts "-T -K1M -M16M"
  hs-source-dirs: Streamly/Benchmark/Data/Stream
  main-is: BaseStreams.hs
  if impl(ghcjs)
    buildable: False
  else
    build-depends: lib-base
    buildable: True

benchmark base-o-n-space
  import: bench-options
  type: exitcode-stdio-1.0
  cpp-options: -DO_N_SPACE
  ghc-options: -with-rtsopts "-T -K32M -M32M"
  hs-source-dirs: Streamly/Benchmark/Data/Stream
  main-is: BaseStreams.hs
  if impl(ghcjs)
    buildable: False
  else
    build-depends: lib-base
    buildable: True

executable nano-bench
  import: bench-options
  hs-source-dirs: .
  main-is: NanoBenchmarks.hs
  if flag(dev)
    buildable: True
  else
    buildable: False

-------------------------------------------------------------------------------
-- Concurrent Streams
-------------------------------------------------------------------------------

benchmark linear-async
  import: bench-options-threaded
  type: exitcode-stdio-1.0
  ghc-options: -with-rtsopts "-T -N2 -K64K -M16M"
  hs-source-dirs: Streamly/Benchmark/Prelude
  main-is: LinearAsync.hs
  if impl(ghcjs)
    buildable: False
  else
    build-depends: lib-prelude
    buildable: True

benchmark nested-concurrent
  import: bench-options-threaded
  type: exitcode-stdio-1.0
  -- XXX this can be lowered once we split out the finite benchmarks
  ghc-options: -with-rtsopts "-T -N2 -K256K -M128M"
  hs-source-dirs: ., Streamly/Benchmark/Prelude
  main-is: NestedConcurrent.hs
  other-modules: Streamly.Benchmark.Prelude.NestedOps

benchmark parallel
  import: bench-options-threaded
  type: exitcode-stdio-1.0
  ghc-options: -with-rtsopts "-T -N2 -K128K -M256M"
  hs-source-dirs: Streamly/Benchmark/Prelude
  main-is: Parallel.hs
  if impl(ghcjs)
    buildable: False
  else
    build-depends: lib-prelude
    buildable: True

benchmark concurrent
  import: bench-options-threaded
  type: exitcode-stdio-1.0
  hs-source-dirs: Streamly/Benchmark/Prelude
  main-is: Concurrent.hs
  ghc-options: -with-rtsopts "-T -N2 -K256K -M384M"

benchmark adaptive
  import: bench-options-threaded
  type: exitcode-stdio-1.0
  hs-source-dirs: Streamly/Benchmark/Prelude
  main-is: Adaptive.hs
  if impl(ghcjs)
    buildable: False
  else
    buildable: True

benchmark linear-rate
  import: bench-options-threaded
  type: exitcode-stdio-1.0
  hs-source-dirs: Streamly/Benchmark/Prelude
  main-is: LinearRate.hs
  if impl(ghcjs)
    buildable: False
  else
    build-depends: lib-prelude
    buildable: True

-------------------------------------------------------------------------------
-- Array Benchmarks
-------------------------------------------------------------------------------

benchmark unpinned-array
  import: bench-options
  type: exitcode-stdio-1.0
  ghc-options: -with-rtsopts "-T -K1K -M128M"
  hs-source-dirs: .
  main-is: Streamly/Benchmark/Data/Array.hs
  other-modules: Streamly.Benchmark.Data.ArrayOps

benchmark prim-array
  import: bench-options
  type: exitcode-stdio-1.0
  ghc-options: -with-rtsopts "-T -K64K -M32M"
  hs-source-dirs: .
  main-is: Streamly/Benchmark/Data/Prim/Array.hs
  other-modules: Streamly.Benchmark.Data.Prim.ArrayOps

benchmark small-array
  import: bench-options
  type: exitcode-stdio-1.0
  ghc-options: -with-rtsopts "-T -K128K -M16M"
  hs-source-dirs: .
  main-is: Streamly/Benchmark/Data/SmallArray.hs
  other-modules: Streamly.Benchmark.Data.SmallArrayOps

benchmark array
  import: bench-options
  type: exitcode-stdio-1.0
  ghc-options: -with-rtsopts "-T -K64K -M128M"
  hs-source-dirs: .
  main-is: Streamly/Benchmark/Memory/Array.hs
  other-modules: Streamly.Benchmark.Memory.ArrayOps

-------------------------------------------------------------------------------
-- FileIO Benchmarks
-------------------------------------------------------------------------------

benchmark fileio
  import: bench-options
  type: exitcode-stdio-1.0
  hs-source-dirs: .
  main-is: FileIO.hs
  other-modules: Streamly.Benchmark.FileIO.Array
               , Streamly.Benchmark.FileIO.Stream
  build-depends:
                 typed-process       >= 0.2.3 && < 0.3

-------------------------------------------------------------------------------
-- benchmark comparison and presentation
-------------------------------------------------------------------------------

executable chart
  default-language: Haskell2010
  ghc-options: -Wall
  hs-source-dirs: .
  main-is: Chart.hs
  if flag(dev) && !flag(no-charts) && !impl(ghcjs)
    buildable: True
    build-Depends:
        base >= 4.8 && < 5
      , bench-show >= 0.3 && < 0.4
      , split
      , transformers >= 0.4   && < 0.6
  else
    buildable: False