packages feed

streamly-0.8.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 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

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

common compile-options
    default-language: Haskell2010

    if flag(dev)
      cpp-options:    -DDEVBUILD

    if flag(include-strict-utf8)
      cpp-options:    -DINCLUDE_STRICT_UTF8

    if flag(inspection)
      cpp-options:    -DINSPECTION

    ghc-options:      -Wall
                      -Wcompat
                      -Wunrecognised-warning-flags
                      -Widentities
                      -Wincomplete-record-updates
                      -Wincomplete-uni-patterns
                      -Wredundant-constraints
                      -Wnoncanonical-monad-instances
                      -Rghc-timing
                      -Wmissing-export-lists

    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.17
    , deepseq             >= 1.4.1 && < 1.5
    , mtl                 >= 2.2   && < 2.3

    -- other libraries
    , streamly
    , random              >= 1.0   && < 2.0
    , transformers        >= 0.4   && < 0.7
    , containers          >= 0.5   && < 0.7
    , process             >= 1.4 && < 1.7
    , directory         >= 1.2.2 && < 1.4
    , filepath          >= 1.4.1 && < 1.5
    , ghc-prim          >= 0.4   && < 0.9

  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.17
                     , inspection-testing >= 0.4   && < 0.5
                     , ghc-prim           >= 0.2   && < 0.9
  -- 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
                   , 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 Prelude.Serial
  import: bench-options
  type: exitcode-stdio-1.0
  hs-source-dirs: Streamly/Benchmark/Prelude
  main-is: Serial.hs
  other-modules:
        Serial.Generation
      , Serial.Elimination
      , Serial.Transformation
      , Serial.NestedStream
      , Serial.NestedFold
      , Serial.Split
      , Serial.Exceptions
      , Serial.Lift
  if impl(ghcjs)
    buildable: False
  else
    buildable: True
  if flag(limit-build-mem)
    if flag(dev)
      ghc-options: +RTS -M3500M -RTS
    else
      ghc-options: +RTS -M2000M -RTS


benchmark Prelude.WSerial
  import: bench-options
  type: exitcode-stdio-1.0
  hs-source-dirs: Streamly/Benchmark/Prelude
  main-is: WSerial.hs
  if impl(ghcjs)
    buildable: False
  else
    buildable: True
  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
  if impl(ghcjs)
    buildable: False
  else
    buildable: True

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

benchmark Prelude.ZipAsync
  import: bench-options
  type: exitcode-stdio-1.0
  hs-source-dirs: Streamly/Benchmark/Prelude
  main-is: ZipAsync.hs
  if impl(ghcjs)
    buildable: False
  else
    buildable: True
  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
  if impl(ghcjs)
    buildable: False
  else
    buildable: True

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

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

benchmark Prelude.Parallel
  import: bench-options-threaded
  type: exitcode-stdio-1.0
  hs-source-dirs: Streamly/Benchmark/Prelude
  main-is: Parallel.hs
  if impl(ghcjs)
    buildable: False
  else
    buildable: True
  if flag(limit-build-mem)
    ghc-options: +RTS -M2000M -RTS


benchmark Data.Unfold
  import: bench-options
  type: exitcode-stdio-1.0
  hs-source-dirs: .
  main-is: Streamly/Benchmark/Data/Unfold.hs
  if 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 impl(ghcjs)
    buildable: False
  else
    buildable: True

benchmark Data.Parser.ParserD
  import: bench-options
  type: exitcode-stdio-1.0
  hs-source-dirs: Streamly/Benchmark/Data/Parser
  main-is: ParserD.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 -M750M -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 impl(ghcjs)
    buildable: False
  else
    buildable: True
    build-depends: exceptions >= 0.8   && < 0.11

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

-------------------------------------------------------------------------------
-- 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
  else
    buildable: True

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
  else
    buildable: True

benchmark Data.Stream.StreamDK
  import: bench-options
  type: exitcode-stdio-1.0
  hs-source-dirs: Streamly/Benchmark/Data/Stream
  main-is: StreamDK.hs
  if impl(ghcjs)
    buildable: False
  else
    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 Prelude.Concurrent
  import: bench-options-threaded
  type: exitcode-stdio-1.0
  hs-source-dirs: Streamly/Benchmark/Prelude
  main-is: Concurrent.hs

benchmark Prelude.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 Prelude.Rate
  import: bench-options-threaded
  type: exitcode-stdio-1.0
  hs-source-dirs: Streamly/Benchmark/Prelude
  main-is: Rate.hs
  if impl(ghcjs)
    buildable: False
  else
    buildable: True

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

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

benchmark Data.Array.Prim
  import: bench-options
  type: exitcode-stdio-1.0
  main-is: Streamly/Benchmark/Data/Array/Prim.hs
  build-depends: primitive

benchmark Data.SmallArray
  import: bench-options
  type: exitcode-stdio-1.0
  main-is: Streamly/Benchmark/Data/Array/SmallArray.hs

benchmark Data.Array.Prim.Pinned
  import: bench-options
  type: exitcode-stdio-1.0
  main-is: Streamly/Benchmark/Data/Array/Prim/Pinned.hs

benchmark Data.Array.Foreign
  import: bench-options
  type: exitcode-stdio-1.0
  main-is: Streamly/Benchmark/Data/Array/Foreign.hs
  if flag(limit-build-mem)
    ghc-options: +RTS -M1000M -RTS

benchmark Data.Array.Foreign.Mut
  import: bench-options
  type: exitcode-stdio-1.0
  main-is: Streamly/Benchmark/Data/Array/Foreign/Mut.hs

-------------------------------------------------------------------------------
-- Array Stream Benchmarks
-------------------------------------------------------------------------------

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

-------------------------------------------------------------------------------
-- Unicode Benchmarks
-------------------------------------------------------------------------------

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

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