项目作者: frankhjung

项目描述 :
Benchmark Greatest Common Denominator algorithms
高级语言: HTML
项目地址: git://github.com/frankhjung/haskell-gcd.git
创建时间: 2018-07-23T02:05:39Z
项目社区:https://github.com/frankhjung/haskell-gcd

开源协议:GNU General Public License v3.0

下载


Haskell Greatest Common Denominator

This is one of my early Haskell projects. I was using it to work out how to
structure a project and on what tools to use. Later, when Git pipelines became
available, I explored how to use these to build the project.

The code was not as important as the project structure. Professionally as an
Developer + SCM + DevOps + Consultant I deal with enterprise projects with the
following features:

  • code is version controlled
  • code is styled and formatted by tools
  • building code is controlled by a build system (e.g. Maven, Gradle, Make, Stack, etc)
  • there are unit tests
  • there are performance benchmarks
  • API documentation is included
  • documentation (this README, more often a wiki)

Originally I was using Cabal, but found that
Stack managed dependencies and project phases
better. If you look at earlier commits you will see those attempts. Perhaps, you
can show me where I went wrong and should have stuck with Cabal?

In this project, I will show how to:

It uses a couple of Greatest Common Denominator (GCD) algorithms as examples for
testing and benchmarking. The GCD algorithms are described
here.

Documentation

API documentation is available from:

Documentation is produced using Haddock.

Setup

To prime environment with compiler, packages and dependencies, run the
environment setup (see Makefile setup goal for full details):

  1. make setup

Stack uses Cabal under the covers but does more package management.

Build

Use the make goal build:

  1. make build

For a rebuild of all targets run the clean goal first:

  1. make clean build

Tests

Run the test goal:

  1. make test

Example - test

  1. $ make test
  2. gcd> test (suite: test)
  3. euclid1
  4. euclid1 1 1
  5. returns 1
  6. euclid1 371 379904
  7. returns 371
  8. euclid2
  9. euclid2 1 1
  10. returns 1
  11. euclid2 371 379904
  12. returns 371
  13. gcd
  14. gcd 1 1
  15. returns 1
  16. gcd 371 379904
  17. returns 371
  18. Finished in 0.0009 seconds
  19. 6 examples, 0 failures

Benchmark

Benchmark the two Euclid Greatest Common Denominator algorithms:

  1. make bench

Example - performance benchmark

  1. $ make bench
  2. gcd> benchmarks
  3. Running 1 benchmarks...
  4. Benchmark benchmark: RUNNING...
  5. benchmarking euclid1: /379904
  6. time 18.62 ns (17.59 ns .. 19.73 ns)
  7. 0.983 R² (0.973 R² .. 0.996 R²)
  8. mean 18.60 ns (17.92 ns .. 19.83 ns)
  9. std dev 3.045 ns (1.540 ns .. 5.638 ns)
  10. variance introduced by outliers: 97% (severely inflated)
  11. benchmarking euclid2: /379904
  12. time 19.09 ns (18.64 ns .. 19.60 ns)
  13. 0.995 R² (0.992 R² .. 0.997 R²)
  14. mean 19.45 ns (18.99 ns .. 20.04 ns)
  15. std dev 1.810 ns (1.376 ns .. 2.618 ns)
  16. variance introduced by outliers: 91% (severely inflated)
  17. benchmarking gcd: /379904
  18. time 18.51 ns (17.86 ns .. 19.19 ns)
  19. 0.990 R² (0.983 R² .. 0.995 R²)
  20. mean 18.88 ns (18.28 ns .. 19.52 ns)
  21. std dev 2.038 ns (1.595 ns .. 2.628 ns)
  22. variance introduced by outliers: 93% (severely inflated)
  23. Benchmark benchmark: FINISH
  24. Completed 2 action(s).

Report

Profiling

Using GHC

The following shows how to profile this application using GHC:

  • compile with profiling

    1. ghc -prof -fprof-auto -rtsopts app/Main.hs src/GCD.hs
  • to profile run program with arguments:

  1. app/Main 371 379904 +RTS -p
  • results are reported in Main.prof:
  1. Fri Jul 27 23:05 2018 Time and Allocation Profiling Report (Final)
  2. Main +RTS -p -RTS 371 379904
  3. total time = 0.00 secs (1 ticks @ 1000 us, 1 processor)
  4. total alloc = 112,632 bytes (excludes profiling overheads)
  5. COST CENTRE MODULE SRC %time %alloc
  6. euclid1 GCD src/GCD.hs:(21,1)-(25,44) 100.0 43.6
  7. CAF GHC.IO.Handle.FD <entire-module> 0.0 30.8
  8. CAF GHC.IO.Encoding <entire-module> 0.0 2.9
  9. main Main app/Main.hs:(19,1)-(24,25) 0.0 12.0
  10. main.(...) Main app/Main.hs:23:19-40 0.0 8.5
  11. COST CENTRE MODULE SRC no. entries %time %alloc %time %alloc
  12. MAIN MAIN <built-in> 118 0 0.0 0.6 100.0 100.0
  13. CAF Main <entire-module> 234 0 0.0 0.1 0.0 0.2
  14. main Main app/Main.hs:(19,1)-(24,25) 236 1 0.0 0.0 0.0 0.0
  15. CAF GHC.Conc.Signal <entire-module> 226 0 0.0 0.6 0.0 0.6
  16. CAF GHC.IO.Encoding <entire-module> 214 0 0.0 2.9 0.0 2.9
  17. CAF GHC.IO.Encoding.Iconv <entire-module> 212 0 0.0 0.2 0.0 0.2
  18. CAF GHC.IO.Handle.FD <entire-module> 204 0 0.0 30.8 0.0 30.8
  19. CAF GHC.IO.Handle.Text <entire-module> 202 0 0.0 0.1 0.0 0.1
  20. CAF Text.Read.Lex <entire-module> 170 0 0.0 0.6 0.0 0.6
  21. main Main app/Main.hs:(19,1)-(24,25) 237 0 0.0 11.9 100.0 64.1
  22. euclid1 GCD src/GCD.hs:(21,1)-(25,44) 238 1024 100.0 43.6 100.0 43.6
  23. euclid2 GCD src/GCD.hs:(29,1)-(32,41) 242 2 0.0 0.1 0.0 0.1
  24. euclid2.remainder GCD src/GCD.hs:32:21-41 243 2 0.0 0.0 0.0 0.0
  25. eain.(...) Main app/Main.hs:23:19-40 240 1 0.0 8.5 0.0 8.5
  26. main.u Main app/Main.hs:23:19-40 239 1 0.0 0.0 0.0 0.0
  27. main.v Main app/Main.hs:23:19-40 241 1 0.0 0.0 0.0 0.0

Using ThreadScope

Another useful tool for performance profiling is
ThreadScope.

  • compile with multi-threaded runtime:
  1. ghc -threaded -eventlog -rtsopts --make app/Main.hs src/GCD.hs
  • execute program and generate a profile use the -ls flag after +RTS
  1. app/Main 371 379904 +RTS -ls -N2
  • pass the profile into ThreadScope:
  1. threadscope Main.eventlog

Here is an example of the report:

threadscope-main.png

Project Information

  1. $ cabal info .
  2. Warning: Unknown/unsupported 'ghc' version detected (Cabal 3.6.2.0 supports
  3. 'ghc' version < 9.4): /home/frank/.ghcup/bin/ghc is version 9.4.7
  4. Warning: The package list for 'hackage.haskell.org' does not exist. Run 'cabal
  5. update' to download it.
  6. * gcd-0.12.0 (program and library)
  7. Synopsis: Greatest Common Denominator
  8. Versions available: [ Not available from server ]
  9. Versions installed: [ Not installed ]
  10. Homepage: https://github.com/frankhjung/gcd#readme
  11. Bug reports: [ Not specified ]
  12. Description: Test versions of Euclid's greatest common denominator
  13. algorithm
  14. Category: education
  15. License: GPL-3.0-only
  16. Author: Frank H Jung
  17. Maintainer: frankhjung@linux.com
  18. Source repo: git@github.com:frankhjung/haskell-gcd.git
  19. Executables: gcd
  20. Dependencies: base, base >=4.13 && <5.0, gcd, base, gcd, hspec, base,
  21. criterion, gcd
  22. Cached: Yes
  23. Modules:
  24. Gcd