├── .github └── workflows │ └── haskell-ci.yml ├── .gitignore ├── CHANGELOG.md ├── GhcEvents.hs ├── LICENSE ├── README.md ├── Setup.lhs ├── cabal.haskell-ci ├── cabal.project ├── ghc-events.cabal ├── include └── EventLogFormat.h ├── src └── GHC │ └── RTS │ ├── EventParserUtils.hs │ ├── EventTypes.hs │ ├── Events.hs │ └── Events │ ├── Analysis.hs │ ├── Analysis │ ├── Capability.hs │ ├── SparkThread.hs │ └── Thread.hs │ ├── Binary.hs │ ├── Incremental.hs │ └── Merge.hs └── test ├── Roundtrip.hs ├── TestVersions.hs ├── Utils.hs ├── WriteMerge.hs ├── biographical-samples.eventlog ├── biographical-samples.eventlog.reference ├── ghc-9.2-events.eventlog ├── ghc-9.2-events.eventlog.reference ├── hello-ghc-8.2.2.eventlog ├── hello-ghc-8.2.2.eventlog.reference ├── hello-ghc-8.6.5.eventlog ├── hello-ghc-8.6.5.eventlog.reference ├── nonmoving-gc-census-T23340.eventlog ├── nonmoving-gc-census-T23340.eventlog.reference ├── nonmoving-gc-census.eventlog ├── nonmoving-gc-census.eventlog.reference ├── nonmoving-gc-pruned-segments.eventlog ├── nonmoving-gc-pruned-segments.eventlog.reference ├── nonmoving-gc.eventlog ├── nonmoving-gc.eventlog.reference ├── parallelTest.eventlog ├── parallelTest.eventlog.reference ├── sleep.h.eventlog ├── sleep.h.eventlog.reference ├── sleep.hC.eventlog ├── sleep.hC.eventlog.reference ├── sleep.hd.eventlog ├── sleep.hd.eventlog.reference ├── sleep.hm.eventlog ├── sleep.hm.eventlog.reference ├── sleep.hy.eventlog ├── sleep.hy.eventlog.reference ├── stop.hT.eventlog ├── stop.hT.eventlog.reference ├── stop.hs ├── testlog-part.eventlog ├── testlog.eventlog ├── ticky-begin-sample.eventlog ├── ticky-begin-sample.eventlog.reference ├── ticky-json.eventlog ├── ticky-json.eventlog.reference ├── ticky-new.eventlog ├── ticky-new.eventlog.reference ├── ticky-ticky.eventlog ├── ticky-ticky.eventlog.reference ├── time-prof.eventlog ├── time-prof.eventlog.reference ├── trace-binary-event.eventlog ├── trace-binary-event.eventlog.reference ├── trace-binary-nonutf.eventlog ├── trace-binary-nonutf.eventlog.reference ├── unicode.eventlog └── unicode.eventlog.reference /.github/workflows/haskell-ci.yml: -------------------------------------------------------------------------------- 1 | # This GitHub workflow config has been generated by a script via 2 | # 3 | # haskell-ci 'github' 'ghc-events.cabal' 4 | # 5 | # To regenerate the script (for example after adjusting tested-with) run 6 | # 7 | # haskell-ci regenerate 8 | # 9 | # For more information, see https://github.com/haskell-CI/haskell-ci 10 | # 11 | # version: 0.19.20241219 12 | # 13 | # REGENDATA ("0.19.20241219",["github","ghc-events.cabal"]) 14 | # 15 | name: Haskell-CI 16 | on: 17 | - push 18 | - pull_request 19 | jobs: 20 | linux: 21 | name: Haskell-CI - Linux - ${{ matrix.compiler }} 22 | runs-on: ubuntu-20.04 23 | timeout-minutes: 24 | 60 25 | container: 26 | image: buildpack-deps:jammy 27 | continue-on-error: ${{ matrix.allow-failure }} 28 | strategy: 29 | matrix: 30 | include: 31 | - compiler: ghc-9.12.1 32 | compilerKind: ghc 33 | compilerVersion: 9.12.1 34 | setup-method: ghcup 35 | allow-failure: false 36 | - compiler: ghc-9.10.1 37 | compilerKind: ghc 38 | compilerVersion: 9.10.1 39 | setup-method: ghcup 40 | allow-failure: false 41 | - compiler: ghc-9.8.1 42 | compilerKind: ghc 43 | compilerVersion: 9.8.1 44 | setup-method: ghcup 45 | allow-failure: false 46 | - compiler: ghc-9.6.1 47 | compilerKind: ghc 48 | compilerVersion: 9.6.1 49 | setup-method: ghcup 50 | allow-failure: false 51 | - compiler: ghc-9.4.2 52 | compilerKind: ghc 53 | compilerVersion: 9.4.2 54 | setup-method: ghcup 55 | allow-failure: false 56 | - compiler: ghc-9.2.4 57 | compilerKind: ghc 58 | compilerVersion: 9.2.4 59 | setup-method: ghcup 60 | allow-failure: false 61 | - compiler: ghc-9.0.2 62 | compilerKind: ghc 63 | compilerVersion: 9.0.2 64 | setup-method: ghcup 65 | allow-failure: false 66 | - compiler: ghc-8.10.7 67 | compilerKind: ghc 68 | compilerVersion: 8.10.7 69 | setup-method: ghcup 70 | allow-failure: false 71 | - compiler: ghc-8.8.4 72 | compilerKind: ghc 73 | compilerVersion: 8.8.4 74 | setup-method: ghcup 75 | allow-failure: false 76 | - compiler: ghc-8.6.5 77 | compilerKind: ghc 78 | compilerVersion: 8.6.5 79 | setup-method: ghcup 80 | allow-failure: false 81 | - compiler: ghc-8.4.4 82 | compilerKind: ghc 83 | compilerVersion: 8.4.4 84 | setup-method: ghcup 85 | allow-failure: false 86 | - compiler: ghc-8.2.2 87 | compilerKind: ghc 88 | compilerVersion: 8.2.2 89 | setup-method: ghcup 90 | allow-failure: false 91 | - compiler: ghc-8.0.2 92 | compilerKind: ghc 93 | compilerVersion: 8.0.2 94 | setup-method: ghcup 95 | allow-failure: false 96 | fail-fast: false 97 | steps: 98 | - name: apt-get install 99 | run: | 100 | apt-get update 101 | apt-get install -y --no-install-recommends gnupg ca-certificates dirmngr curl git software-properties-common libtinfo5 libnuma-dev 102 | - name: Install GHCup 103 | run: | 104 | mkdir -p "$HOME/.ghcup/bin" 105 | curl -sL https://downloads.haskell.org/ghcup/0.1.30.0/x86_64-linux-ghcup-0.1.30.0 > "$HOME/.ghcup/bin/ghcup" 106 | chmod a+x "$HOME/.ghcup/bin/ghcup" 107 | - name: Install cabal-install 108 | run: | 109 | "$HOME/.ghcup/bin/ghcup" install cabal 3.12.1.0 || (cat "$HOME"/.ghcup/logs/*.* && false) 110 | echo "CABAL=$HOME/.ghcup/bin/cabal-3.12.1.0 -vnormal+nowrap" >> "$GITHUB_ENV" 111 | - name: Install GHC (GHCup) 112 | if: matrix.setup-method == 'ghcup' 113 | run: | 114 | "$HOME/.ghcup/bin/ghcup" install ghc "$HCVER" || (cat "$HOME"/.ghcup/logs/*.* && false) 115 | HC=$("$HOME/.ghcup/bin/ghcup" whereis ghc "$HCVER") 116 | HCPKG=$(echo "$HC" | sed 's#ghc$#ghc-pkg#') 117 | HADDOCK=$(echo "$HC" | sed 's#ghc$#haddock#') 118 | echo "HC=$HC" >> "$GITHUB_ENV" 119 | echo "HCPKG=$HCPKG" >> "$GITHUB_ENV" 120 | echo "HADDOCK=$HADDOCK" >> "$GITHUB_ENV" 121 | env: 122 | HCKIND: ${{ matrix.compilerKind }} 123 | HCNAME: ${{ matrix.compiler }} 124 | HCVER: ${{ matrix.compilerVersion }} 125 | - name: Set PATH and environment variables 126 | run: | 127 | echo "$HOME/.cabal/bin" >> $GITHUB_PATH 128 | echo "LANG=C.UTF-8" >> "$GITHUB_ENV" 129 | echo "CABAL_DIR=$HOME/.cabal" >> "$GITHUB_ENV" 130 | echo "CABAL_CONFIG=$HOME/.cabal/config" >> "$GITHUB_ENV" 131 | HCNUMVER=$(${HC} --numeric-version|perl -ne '/^(\d+)\.(\d+)\.(\d+)(\.(\d+))?$/; print(10000 * $1 + 100 * $2 + ($3 == 0 ? $5 != 1 : $3))') 132 | echo "HCNUMVER=$HCNUMVER" >> "$GITHUB_ENV" 133 | echo "ARG_TESTS=--enable-tests" >> "$GITHUB_ENV" 134 | echo "ARG_BENCH=--enable-benchmarks" >> "$GITHUB_ENV" 135 | if [ $((HCNUMVER >= 91200)) -ne 0 ] ; then echo "HEADHACKAGE=true" >> "$GITHUB_ENV" ; else echo "HEADHACKAGE=false" >> "$GITHUB_ENV" ; fi 136 | echo "ARG_COMPILER=--$HCKIND --with-compiler=$HC" >> "$GITHUB_ENV" 137 | env: 138 | HCKIND: ${{ matrix.compilerKind }} 139 | HCNAME: ${{ matrix.compiler }} 140 | HCVER: ${{ matrix.compilerVersion }} 141 | - name: env 142 | run: | 143 | env 144 | - name: write cabal config 145 | run: | 146 | mkdir -p $CABAL_DIR 147 | cat >> $CABAL_CONFIG <> $CABAL_CONFIG <> $CABAL_CONFIG < cabal-plan.xz 192 | echo 'f62ccb2971567a5f638f2005ad3173dba14693a45154c1508645c52289714cb2 cabal-plan.xz' | sha256sum -c - 193 | xz -d < cabal-plan.xz > $HOME/.cabal/bin/cabal-plan 194 | rm -f cabal-plan.xz 195 | chmod a+x $HOME/.cabal/bin/cabal-plan 196 | cabal-plan --version 197 | - name: checkout 198 | uses: actions/checkout@v4 199 | with: 200 | path: source 201 | - name: initial cabal.project for sdist 202 | run: | 203 | touch cabal.project 204 | echo "packages: $GITHUB_WORKSPACE/source/." >> cabal.project 205 | cat cabal.project 206 | - name: sdist 207 | run: | 208 | mkdir -p sdist 209 | $CABAL sdist all --output-dir $GITHUB_WORKSPACE/sdist 210 | - name: unpack 211 | run: | 212 | mkdir -p unpacked 213 | find sdist -maxdepth 1 -type f -name '*.tar.gz' -exec tar -C $GITHUB_WORKSPACE/unpacked -xzvf {} \; 214 | - name: generate cabal.project 215 | run: | 216 | PKGDIR_ghc_events="$(find "$GITHUB_WORKSPACE/unpacked" -maxdepth 1 -type d -regex '.*/ghc-events-[0-9.]*')" 217 | echo "PKGDIR_ghc_events=${PKGDIR_ghc_events}" >> "$GITHUB_ENV" 218 | rm -f cabal.project cabal.project.local 219 | touch cabal.project 220 | touch cabal.project.local 221 | echo "packages: ${PKGDIR_ghc_events}" >> cabal.project 222 | if [ $((HCNUMVER >= 80200)) -ne 0 ] ; then echo "package ghc-events" >> cabal.project ; fi 223 | if [ $((HCNUMVER >= 80200)) -ne 0 ] ; then echo " ghc-options: -Werror=missing-methods" >> cabal.project ; fi 224 | cat >> cabal.project <> cabal.project 228 | fi 229 | $HCPKG list --simple-output --names-only | perl -ne 'for (split /\s+/) { print "constraints: any.$_ installed\n" unless /^(ghc-events)$/; }' >> cabal.project.local 230 | cat cabal.project 231 | cat cabal.project.local 232 | - name: dump install plan 233 | run: | 234 | $CABAL v2-build $ARG_COMPILER $ARG_TESTS $ARG_BENCH --dry-run all 235 | cabal-plan 236 | - name: restore cache 237 | uses: actions/cache/restore@v4 238 | with: 239 | key: ${{ runner.os }}-${{ matrix.compiler }}-${{ github.sha }} 240 | path: ~/.cabal/store 241 | restore-keys: ${{ runner.os }}-${{ matrix.compiler }}- 242 | - name: install dependencies 243 | run: | 244 | $CABAL v2-build $ARG_COMPILER --disable-tests --disable-benchmarks --dependencies-only -j2 all 245 | $CABAL v2-build $ARG_COMPILER $ARG_TESTS $ARG_BENCH --dependencies-only -j2 all 246 | - name: build w/o tests 247 | run: | 248 | $CABAL v2-build $ARG_COMPILER --disable-tests --disable-benchmarks all 249 | - name: build 250 | run: | 251 | $CABAL v2-build $ARG_COMPILER $ARG_TESTS $ARG_BENCH all --write-ghc-environment-files=always 252 | - name: tests 253 | run: | 254 | $CABAL v2-test $ARG_COMPILER $ARG_TESTS $ARG_BENCH all --test-show-details=direct 255 | - name: cabal check 256 | run: | 257 | cd ${PKGDIR_ghc_events} || false 258 | ${CABAL} -vnormal check 259 | - name: haddock 260 | run: | 261 | $CABAL v2-haddock --disable-documentation --haddock-all $ARG_COMPILER --with-haddock $HADDOCK $ARG_TESTS $ARG_BENCH all 262 | - name: unconstrained build 263 | run: | 264 | rm -f cabal.project.local 265 | $CABAL v2-build $ARG_COMPILER --disable-tests --disable-benchmarks all 266 | - name: save cache 267 | if: always() 268 | uses: actions/cache/save@v4 269 | with: 270 | key: ${{ runner.os }}-${{ matrix.compiler }}-${{ github.sha }} 271 | path: ~/.cabal/store 272 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *# 2 | *swp 3 | *~ 4 | .cabal-sandbox/ 5 | .ghc.environment.* 6 | cabal.project.local 7 | cabal.sandbox.config 8 | dist-newstyle/ 9 | dist/ 10 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | 3 | ## Unreleased 4 | * Drop dependency on `array` ([#114](https://github.com/haskell/ghc-events/pull/114)) 5 | * Make definition of `Monoid MaxVars` cannonical ([#115](https://github.com/haskell/ghc-events/pull/115)) 6 | 7 | 8 | ## 0.20.0.0 - 2024-11-25 9 | 10 | * Add pretty printing for timestamps ([#92](https://github.com/haskell/ghc-events/pull/92)) 11 | * Added `--version` option to CLI interface ([#95](https://github.com/haskell/ghc-events/pull/95)) 12 | * Support GHC 9.8 ([#102](https://github.com/haskell/ghc-events/pull/102)) 13 | * Add support for era profiling events ([#103](https://github.com/haskell/ghc-events/pull/103)) 14 | * Support GHC 9.10 ([#105](https://github.com/haskell/ghc-events/pull/105)) 15 | * Add support for the NonmovingPrunedSegment event ([#107](https://github.com/haskell/ghc-events/pull/107)) 16 | * Fix the type of the `profCap` field of `ProfSampleCostCentre` ([#108](https://github.com/haskell/ghc-events/pull/108)) 17 | 18 | 19 | ## 0.19.0.1 - 2023-04-13 20 | 21 | * Update for GHC 9.6 ([#93](https://github.com/haskell/ghc-events/pull/93)) 22 | 23 | ## 0.19.0 - 2022-12-15 24 | 25 | * Add support for extension to Ticky counter definition field ([#83](https://github.com/haskell/ghc-events/pull/83)) 26 | * Add support for ticky definition json fields ([#87](https://github.com/haskell/ghc-events/pull/87)) 27 | 28 | ## 0.18.0 - 2022-10-28 29 | 30 | * Ensure that ghc-events show fails with an error on malformed events ([#86](https://github.com/haskell/ghc-events/pull/86)) 31 | * Drop support for GHC < 8 ([#89](https://github.com/haskell/ghc-events/issues/89)) 32 | * Allow parsing UserBinaryMessage events that have non-utf payloads ([#91](https://github.com/haskell/ghc-events/pull/91)) 33 | * Update dependencies to support GHC 9.4 34 | 35 | ## 0.17.0.3 - 2022-04-18 36 | 37 | * Fix typos and terminology ([#81](https://github.com/haskell/ghc-events/pull/81), [#82](https://github.com/haskell/ghc-events/pull/82)) 38 | 39 | ## 0.17.0.2 - 2022-02-14 40 | 41 | * Clarify usage of IntMap EventType in ppEvent ([#80](https://github.com/haskell/ghc-events/pull/80)) 42 | * Relax upper version bound for text 43 | 44 | ## 0.17.0.1 - 2021-11-22 45 | 46 | * Relax base bound to support GHC-9.2.1 ([#78](https://github.com/haskell/ghc-events/pull/78)) 47 | 48 | ## 0.17.0 - 2021-05-06 49 | 50 | * Introduce EVENT_TICKY_BEGIN_SAMPLE ([#76](https://github.com/haskell/ghc-events/pull/76)) 51 | 52 | ## 0.16.0 - 2021-03-12 53 | 54 | * Add support for new 9.2 events ([#74](https://github.com/haskell/ghc-events/pull/74)) 55 | 56 | ## 0.15.1 - 2020-12-30 57 | 58 | * Add missing extra-source-files ([#71](https://github.com/haskell/ghc-events/pull/71)) 59 | 60 | ## 0.15.0 - 2020-12-16 61 | 62 | * Add support for ticky-ticky counts ([#67](https://github.com/haskell/ghc-events/pull/67)) 63 | 64 | ## 0.14.0 - 2020-11-17 65 | 66 | * Add support for non-moving GC events ([#60](https://github.com/haskell/ghc-events/pull/60)) 67 | * Fix the parser error under GHC 9.0 ([#64](https://github.com/haskell/ghc-events/pull/64)) 68 | * Fix string encodings ([#62](https://github.com/haskell/ghc-events/pull/62)) 69 | * Switch to GitHub Actions ([#65](https://github.com/haskell/ghc-events/pull/65)), dropping GHC 7.8.4 from the support range 70 | 71 | ## 0.13.0 - 2020-04-04 72 | 73 | * Fix broken UTF-8 decoding ([#55](https://github.com/haskell/ghc-events/pull/55)) 74 | * This is a breaking change. Most of the String fields in EventInfo have been replaced with Texts. 75 | * Support GHC 8.10.1 76 | 77 | ## 0.12.0 - 2019-12-02 78 | 79 | * Add support for EVENT_USER_BINARY_MSG ([#54](https://github.com/haskell/ghc-events/pull/54)) 80 | 81 | ## 0.11.0 - 2019-10-29 82 | 83 | * Add support for time profiling events (ProfSampleCostCentre and ProfBegin) ([#53](https://github.com/haskell/ghc-events/pull/53)) 84 | 85 | ## 0.10.0 - 2019-10-01 86 | 87 | * Add support for HeapProfSampleEnd and HeapBioProfSampleBegin ([#52](https://github.com/haskell/ghc-events/pull/52)) 88 | 89 | ## 0.9.1 - 2019-09-03 90 | 91 | * Relax upper version bounds to support GHC 8.8.1 ([#49](https://github.com/haskell/ghc-events/pull/49) and [#51](https://github.com/haskell/ghc-events/pull/51)) 92 | 93 | ## 0.9.0 - 2019-05-15 94 | 95 | * Support the newly added par_balanced_copied field ([#47](https://github.com/haskell/ghc-events/pull/47)) 96 | 97 | ## 0.8.0.2 - 2019-04-02 98 | 99 | * Tighten lower version bound for base ([#46](https://github.com/haskell/ghc-events/pull/46)) 100 | 101 | ## 0.8.0.1 - 2018-10-22 102 | 103 | * Relax upper version bound for base to support GHC 8.6 104 | * Relax upper version bound for binary 105 | 106 | ## 0.8.0 - 2018-07-11 107 | 108 | * Add HeapProfBreakdownClosureType ([#33](https://github.com/haskell/ghc-events/pull/33), [#39](https://github.com/haskell/ghc-events/pull/39)) 109 | * This is a breaking change 110 | * Test with newer GHCs ([#40](https://github.com/haskell/ghc-events/pull/40)) 111 | 112 | ## 0.7.3 - 2018-07-10 113 | 114 | * Fixed memory-leak in incremental readEvents ([#37](https://github.com/haskell/ghc-events/pull/37)) 115 | * Relax upper version bound for containers ([#38](https://github.com/haskell/ghc-events/pull/38)) 116 | 117 | ## 0.7.2 - 2018-03-13 118 | 119 | * Add Semigroup instance for MaxVars to build with ghc-8.4 120 | 121 | ## 0.7.1 - 2018-02-17 122 | 123 | * Export HeapProfBreakdown, HeapProfFlags, and PID types ([#35](https://github.com/haskell/ghc-events/pull/35)) 124 | 125 | ## 0.7.0 - 2017-10-04 126 | 127 | * Add support for heap profiling events ([#29](https://github.com/haskell/ghc-events/pull/29)) 128 | 129 | ## 0.6.0 - 2017-05-31 130 | 131 | This contains breaking changes. 132 | 133 | * The deprecation notice on `readEventLogFromFile` has been retracted 134 | * The incremental API has been refactored 135 | 136 | The details are as follows: 137 | 138 | * Update bug tracker URL ([#10](https://github.com/haskell/ghc-events/pull/10)) 139 | * New test for Eden events ([#11](https://github.com/haskell/ghc-events/pull/11)) 140 | * Relax version bound for binary ([#15](https://github.com/haskell/ghc-events/pull/15)) 141 | * Enable Travis CI ([#19](https://github.com/haskell/ghc-events/pull/19)) 142 | * Refactor the incremental API which was introduced in 0.5.0.0 ([#22](https://github.com/haskell/ghc-events/pull/22)) 143 | * Some speed/memory usage improvements ([#18](https://github.com/haskell/ghc-events/pull/18), [#22](https://github.com/haskell/ghc-events/pull/22)) 144 | 145 | ## 0.5.0.0 - unreleased 146 | 147 | * Readme added :) 148 | * Old parser replaced with an incremental implementation 149 | * General overhaul of the codebase 150 | * Partial Haddock coverage 151 | 152 | The 0.5.* releases should be able to handle large event logs and logs that have been cut off abruptly, e.g. from executable runs that resulted in crashes. 153 | 154 | This release should be *mostly* backwards compatible, however the "old" way of reading event logs, namely the `readEventLogFromFile` function is now **deprecated**. 155 | 156 | **NOTE:** Users parsing large logs may notice that this version of the library is noticeably slower than the older versions. The incremental parser is at fault here - previous versions of the library used a "trick" that would let them essentially skip the first step of the mergesort algorithm since `EventBlock`s were already sorted in time order. The new parser reads the file incrementally and cannot take the advantage of this. Apologies for any inconvenience this may have caused. 157 | -------------------------------------------------------------------------------- /GhcEvents.hs: -------------------------------------------------------------------------------- 1 | module Main where 2 | 3 | import GHC.RTS.Events 4 | import GHC.RTS.Events.Incremental 5 | import GHC.RTS.Events.Merge 6 | import GHC.RTS.Events.Analysis 7 | import GHC.RTS.Events.Analysis.SparkThread 8 | import GHC.RTS.Events.Analysis.Thread 9 | import GHC.RTS.Events.Analysis.Capability 10 | 11 | import qualified Data.ByteString.Lazy as BL 12 | 13 | import System.Environment (getArgs) 14 | import Data.Either (rights) 15 | import qualified Data.Map as M 16 | import Data.Version (showVersion) 17 | import qualified Paths_ghc_events as P 18 | import System.IO 19 | import System.Exit 20 | 21 | 22 | main :: IO () 23 | main = getArgs >>= command 24 | 25 | command :: [String] -> IO () 26 | command ["--version"] = putStrLn $ "ghc-events version: " ++ showVersion P.version 27 | 28 | command ["--help"] = putStr usage 29 | 30 | command ["inc", file] = printEventsIncremental False file 31 | 32 | command ["inc", "force", file] = printEventsIncremental True file 33 | 34 | command ["show", "--pretty-time", file] = do 35 | evtLog <- readLogOrDie file 36 | putStrLn $ ppEventLog PrettyTime evtLog 37 | 38 | command ["show", file] = do 39 | evtLog <- readLogOrDie file 40 | putStrLn $ ppEventLog RawTime evtLog 41 | 42 | command ["show", "threads", file] = do 43 | eventLog <- readLogOrDie file 44 | let eventTypeMap = buildEventTypeMap . eventTypes . header $ eventLog 45 | evts = sortEvents $ events $ dat eventLog 46 | mappings = rights . validates capabilityThreadRunMachine $ evts 47 | indexes = zipWith capabilityThreadIndexer mappings evts 48 | threadMap = M.fromListWith (++) . reverse $ zip indexes (map return evts) 49 | putStrLn "Event Types:" 50 | putStrLn . unlines . map ppEventType . eventTypes . header $ eventLog 51 | putStrLn "Thread Indexed Events:" 52 | putStrLn . showMap 53 | ((++ "\n") . show) 54 | (unlines . map ((" " ++) . ppEvent RawTime eventTypeMap)) $ 55 | threadMap 56 | 57 | command ["show", "caps", file] = do 58 | eventLog <- readLogOrDie file 59 | let eventTypeMap = buildEventTypeMap . eventTypes . header $ eventLog 60 | let evts = sortEvents . events . dat $ eventLog 61 | indexes = map evCap evts 62 | capMap = M.fromListWith (++) . reverse $ zip indexes (map return evts) 63 | putStrLn "Event Types:" 64 | putStrLn . unlines . map ppEventType . eventTypes . header $ eventLog 65 | putStrLn "Cap Indexed Events:" 66 | putStrLn . showMap 67 | ((++ "\n") . show) 68 | (unlines . map ((" " ++) . ppEvent RawTime eventTypeMap)) $ 69 | capMap 70 | 71 | command ["merge", out, file1, file2] = do 72 | log1 <- readLogOrDie file1 73 | log2 <- readLogOrDie file2 74 | let m = mergeEventLogs log1 log2 75 | writeEventLogToFile out m 76 | 77 | command ["validate", "threads", file] = do 78 | eventLog <- readLogOrDie file 79 | let evts = sortEvents . events . dat $ eventLog 80 | let result = validate (routeM capabilityThreadRunMachine 81 | capabilityThreadIndexer 82 | (refineM evSpec threadMachine)) 83 | evts 84 | putStrLn $ showValidate (\(m, n) -> 85 | "\nThread States:\n" ++ showIndexed show show m ++ 86 | "\nCap States:\n" ++ showIndexed show show n) 87 | show result 88 | 89 | command ["validate", "threadpool", file] = do 90 | eventLog <- readLogOrDie file 91 | let evts = sortEvents . events . dat $ eventLog 92 | let result = validate capabilityThreadPoolMachine evts 93 | putStrLn $ showValidate show show result 94 | 95 | command ["validate", "threadrun", file] = do 96 | eventLog <- readLogOrDie file 97 | let evts = sortEvents . events . dat $ eventLog 98 | let result = validate capabilityThreadRunMachine evts 99 | putStrLn $ showValidate show show result 100 | 101 | command ["validate", "taskpool", file] = do 102 | eventLog <- readLogOrDie file 103 | let evts = sortEvents . events . dat $ eventLog 104 | let result = validate capabilityTaskPoolMachine evts 105 | putStrLn $ showValidate show show result 106 | 107 | command ["validate", "tasks", file] = do 108 | eventLog <- readLogOrDie file 109 | let evts = sortEvents . events . dat $ eventLog 110 | let result = validate capabilityTaskOSMachine evts 111 | putStrLn $ showValidate show show result 112 | 113 | command ["validate", "sparks", file] = do 114 | eventLog <- readLogOrDie file 115 | let evts = sortEvents . events . dat $ eventLog 116 | let result = validate 117 | (routeM capabilitySparkThreadMachine capabilitySparkThreadIndexer 118 | (refineM evSpec sparkThreadMachine)) 119 | evts 120 | putStrLn $ showValidate show show result 121 | 122 | command ["simulate", "threads", file] = do 123 | eventLog <- readLogOrDie file 124 | let evts = sortEvents . events . dat $ eventLog 125 | let result = simulate (routeM capabilityThreadRunMachine 126 | capabilityThreadIndexer 127 | (refineM evSpec threadMachine)) 128 | evts 129 | putStrLn . showProcess $ result 130 | 131 | command ["simulate", "threadpool", file] = do 132 | eventLog <- readLogOrDie file 133 | let evts = sortEvents . events . dat $ eventLog 134 | let result = simulate capabilityThreadPoolMachine evts 135 | putStrLn . showProcess $ result 136 | 137 | command ["simulate", "threadrun", file] = do 138 | eventLog <- readLogOrDie file 139 | let evts = sortEvents . events . dat $ eventLog 140 | let result = simulate capabilityThreadRunMachine evts 141 | putStrLn . showProcess $ result 142 | 143 | command ["simulate", "taskpool", file] = do 144 | eventLog <- readLogOrDie file 145 | let evts = sortEvents . events . dat $ eventLog 146 | let result = simulate capabilityTaskPoolMachine evts 147 | putStrLn . showProcess $ result 148 | 149 | command ["simulate", "tasks", file] = do 150 | eventLog <- readLogOrDie file 151 | let evts = sortEvents . events . dat $ eventLog 152 | let result = simulate capabilityTaskOSMachine evts 153 | putStrLn . showProcess $ result 154 | 155 | command ["simulate", "sparks", file] = do 156 | eventLog <- readLogOrDie file 157 | let evts = sortEvents . events . dat $ eventLog 158 | let result = simulate 159 | (routeM capabilitySparkThreadMachine 160 | capabilitySparkThreadIndexer 161 | (refineM evSpec sparkThreadMachine)) evts 162 | putStrLn . showProcess $ result 163 | 164 | command ["profile", "threads", file] = do 165 | eventLog <- readLogOrDie file 166 | let evts = sortEvents . events . dat $ eventLog 167 | let result = profileRouted 168 | (refineM evSpec threadMachine) 169 | capabilityThreadRunMachine 170 | capabilityThreadIndexer evTime evts 171 | putStrLn . showProcess $ result 172 | 173 | command ["profile", "sparks", file] = do 174 | eventLog <- readLogOrDie file 175 | let evts = sortEvents . events . dat $ eventLog 176 | let result = profileRouted 177 | (refineM evSpec sparkThreadMachine) 178 | capabilitySparkThreadMachine 179 | capabilitySparkThreadIndexer 180 | evTime evts 181 | putStrLn . showProcess $ result 182 | 183 | command _ = putStr usage >> die "Unrecognized command" 184 | 185 | readLogOrDie :: FilePath -> IO EventLog 186 | readLogOrDie file = do 187 | res <- readEventLogOrFail <$> BL.readFile file 188 | case res of 189 | Left err -> die $ "Failed to parse " ++ file ++ ": " ++ err 190 | Right eventlog -> return eventlog 191 | 192 | usage :: String 193 | usage = unlines $ map pad strings 194 | where 195 | align = 4 + (maximum . map (length . fst) $ strings) 196 | pad (x, y) = zipWith const (x ++ repeat ' ') (replicate align ()) ++ y 197 | strings = [ ("ghc-events --help:", "Display this help.") 198 | , ("ghc-events --version", "Print the version of ghc-events.") 199 | , ("ghc-events inc :", "Pretty print an event log incrementally") 200 | , ("ghc-events inc force :", "Pretty print an event log incrementally. Retry on incomplete input (aka 'tail -f').") 201 | , ("ghc-events show :", "Pretty print an event log.") 202 | , ("ghc-events show threads :", "Pretty print an event log, ordered by threads.") 203 | , ("ghc-events show caps :", "Pretty print an event log, ordered by capabilities.") 204 | 205 | , ("ghc-events merge :", "Merge two event logs.") 206 | 207 | , ("ghc-events sparks-csv :", "Print spark information in CSV.") 208 | 209 | , ("ghc-events validate threads :", "Validate thread states.") 210 | , ("ghc-events validate threadpool :", "Validate thread pool state.") 211 | , ("ghc-events validate threadrun :", "Validate thread running state.") 212 | , ("ghc-events validate tasks :", "Validate task states.") 213 | , ("ghc-events validate sparks :", "Validate spark thread states.") 214 | 215 | , ("ghc-events simulate threads :", "Simulate thread states.") 216 | , ("ghc-events simulate threadpool :", "Simulate thread pool state.") 217 | , ("ghc-events simulate threadrun :", "Simulate thread running state.") 218 | , ("ghc-events simulate tasks :", "Simulate task states.") 219 | , ("ghc-events simulate sparks :", "Simulate spark thread states.") 220 | 221 | , ("ghc-events profile threads :", "Profile thread states.") 222 | , ("ghc-events profile sparks :", "Profile spark thread states.") 223 | ] 224 | 225 | showValidate :: (s -> String) -> (i -> String) -> Either (s, i) s -> String 226 | showValidate showState showInput (Left (state, input)) = 227 | "Invalid event log:" 228 | ++ "\nState:\n" ++ showState state 229 | ++ "\nInput:\n" ++ showInput input 230 | showValidate showState _ (Right state) = 231 | "Valid event log: " ++ showState state 232 | 233 | showProcess :: (Show e, Show a) => Process e a -> String 234 | showProcess process = 235 | "Trace:\n" 236 | ++ (unlines . map show . toList) process 237 | ++ "\n" 238 | ++ (maybe "Valid." (("Invalid:\n" ++) . show) . toMaybe) process 239 | 240 | showIndexed :: (k -> String) -> (v -> String) -> M.Map k v -> String 241 | showIndexed showKey showValue m 242 | | M.null m = "Empty map\n" 243 | | otherwise = "Indexed output:\n" ++ 244 | concatMap (\(k, v) -> "Key: " ++ showKey k ++ ", Value: " 245 | ++ showValue v ++ "\n") 246 | (M.toList m) 247 | 248 | showMap :: Ord k => (k -> String) -> (a -> String) -> M.Map k a -> String 249 | showMap showKey showValue m = 250 | concat $ zipWith (++) 251 | (map showKey . M.keys $ m :: [String]) 252 | (map (showValue . (M.!) m) . M.keys $ m :: [String]) 253 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The Glasgow Haskell Compiler License 2 | 3 | Copyright 2002-2012, The University Court of the University of Glasgow 4 | and others. All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | - Redistributions of source code must retain the above copyright notice, 10 | this list of conditions and the following disclaimer. 11 | 12 | - Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | - Neither name of the University nor the names of its contributors may be 17 | used to endorse or promote products derived from this software without 18 | specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY COURT OF THE UNIVERSITY OF 21 | GLASGOW AND THE CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 22 | INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 23 | FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 24 | UNIVERSITY COURT OF THE UNIVERSITY OF GLASGOW OR THE CONTRIBUTORS BE LIABLE 25 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 28 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 | OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 31 | DAMAGE. 32 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ghc-events 2 | 3 | ![build](https://github.com/haskell/ghc-events/workflows/build/badge.svg) 4 | [![Hackage](https://img.shields.io/hackage/v/ghc-events.svg)](https://hackage.haskell.org/package/ghc-events) 5 | [![Hackage-Deps](https://img.shields.io/hackage-deps/v/ghc-events.svg)](http://packdeps.haskellers.com/feed?needle=ghc-events) 6 | 7 | A Haskell library for parsing .eventlog files emitted by the GHC runtime system. 8 | The package also includes an executable, `ghc-events` that can be used to display the contents of .eventlog files 9 | 10 | ## TODO 11 | * Add example usage/tutorial of the new API to this readme 12 | 13 | ## Known Issues 14 | * Writing event logs back to file does not work. It is hard to say how long has this been broken or how difficult will it be to fix ([#14](https://github.com/haskell/ghc-events/issues/14)) 15 | -------------------------------------------------------------------------------- /Setup.lhs: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env runhaskell 2 | 3 | > import Distribution.Simple 4 | > main = defaultMain 5 | -------------------------------------------------------------------------------- /cabal.haskell-ci: -------------------------------------------------------------------------------- 1 | cabal-install-version: 3.12.1.0 2 | -------------------------------------------------------------------------------- /cabal.project: -------------------------------------------------------------------------------- 1 | 2 | packages: ./ghc-events.cabal 3 | -------------------------------------------------------------------------------- /ghc-events.cabal: -------------------------------------------------------------------------------- 1 | cabal-version: 2.4 2 | name: ghc-events 3 | version: 0.20.0.0 4 | synopsis: Library and tool for parsing .eventlog files from GHC 5 | description: Parses .eventlog files emitted by GHC 8.0.2 and later. 6 | Includes the ghc-events tool permitting, in particular, 7 | to dump an event log file as text. 8 | category: Development, GHC, Debug, Profiling, Trace 9 | license: BSD-3-Clause 10 | license-file: LICENSE 11 | author: Donnie Jones , 12 | Simon Marlow , 13 | Paul Bone , 14 | Mischa Dieterle , 15 | Thomas Horstmeyer , 16 | Duncan Coutts , 17 | Nicolas Wu , 18 | Jost Berthold 19 | Mikolaj Konarski 20 | Karolis Velicka 21 | maintainer: Simon Marlow 22 | bug-reports: https://github.com/haskell/ghc-events/issues 23 | build-type: Simple 24 | tested-with: GHC == 8.0.2 25 | GHC == 8.2.2 26 | GHC == 8.4.4 27 | GHC == 8.6.5 28 | GHC == 8.8.4 29 | GHC == 8.10.7 30 | GHC == 9.0.2 31 | GHC == 9.2.4 32 | GHC == 9.4.2 33 | GHC == 9.6.1 34 | GHC == 9.8.1 35 | GHC == 9.10.1 36 | GHC == 9.12.1 37 | extra-source-files: include/EventLogFormat.h 38 | test/*.eventlog 39 | test/*.reference 40 | test/Utils.hs 41 | test/stop.hs 42 | extra-doc-files: README.md 43 | CHANGELOG.md 44 | 45 | source-repository head 46 | type: git 47 | location: git@github.com:haskell/ghc-events.git 48 | 49 | common default 50 | default-extensions: 51 | BangPatterns 52 | NamedFieldPuns 53 | PatternGuards 54 | RecordWildCards 55 | default-language: Haskell2010 56 | 57 | library 58 | import: default 59 | build-depends: base >= 4.7 && < 4.22, 60 | containers >= 0.5 && < 0.9, 61 | binary >= 0.7 && < 0.11, 62 | bytestring >= 0.10.4 && < 0.13, 63 | text >= 0.11.2.3 && < 2.2, 64 | vector >= 0.7 && < 0.14 65 | exposed-modules: GHC.RTS.Events, 66 | GHC.RTS.Events.Incremental 67 | GHC.RTS.Events.Merge 68 | GHC.RTS.Events.Analysis 69 | GHC.RTS.Events.Analysis.Capability 70 | GHC.RTS.Events.Analysis.SparkThread 71 | GHC.RTS.Events.Analysis.Thread 72 | other-modules: GHC.RTS.EventParserUtils, 73 | GHC.RTS.EventTypes 74 | GHC.RTS.Events.Binary 75 | Paths_ghc_events 76 | autogen-modules: Paths_ghc_events 77 | hs-source-dirs: src 78 | include-dirs: include 79 | other-extensions: FlexibleContexts, CPP 80 | ghc-options: -Wall 81 | 82 | executable ghc-events 83 | import: default 84 | main-is: GhcEvents.hs 85 | build-depends: ghc-events, base, containers, bytestring 86 | other-modules: Paths_ghc_events 87 | autogen-modules: Paths_ghc_events 88 | 89 | test-suite test-versions 90 | import: default 91 | type: exitcode-stdio-1.0 92 | main-is: TestVersions.hs 93 | other-modules: Utils 94 | hs-source-dirs: ., test 95 | build-depends: ghc-events, base 96 | 97 | test-suite write-merge 98 | import: default 99 | type: exitcode-stdio-1.0 100 | main-is: WriteMerge.hs 101 | other-modules: Utils 102 | hs-source-dirs: ., test 103 | build-depends: ghc-events, base, bytestring 104 | -- disabled until #14 is fixed 105 | buildable: False 106 | 107 | test-suite roundtrip 108 | import: default 109 | type: exitcode-stdio-1.0 110 | main-is: Roundtrip.hs 111 | other-modules: Utils 112 | hs-source-dirs: ., test 113 | build-depends: ghc-events, base 114 | -- disabled until #14 is fixed 115 | buildable: False 116 | -------------------------------------------------------------------------------- /include/EventLogFormat.h: -------------------------------------------------------------------------------- 1 | /* ----------------------------------------------------------------------------- 2 | * 3 | * (c) The GHC Team, 2008-2012 4 | * 5 | * Event log format 6 | * 7 | * The log format is designed to be extensible: old tools should be 8 | * able to parse (but not necessarily understand all of) new versions 9 | * of the format, and new tools will be able to understand old log 10 | * files. 11 | * 12 | * Each event has a specific format. If you add new events, give them 13 | * new numbers: we never re-use old event numbers. 14 | * 15 | * - The format is endian-independent: all values are represented in 16 | * bigendian order. 17 | * 18 | * - The format is extensible: 19 | * 20 | * - The header describes each event type and its length. Tools 21 | * that don't recognise a particular event type can skip those events. 22 | * 23 | * - There is room for extra information in the event type 24 | * specification, which can be ignored by older tools. 25 | * 26 | * - Events can have extra information added, but existing fields 27 | * cannot be changed. Tools should ignore extra fields at the 28 | * end of the event record. 29 | * 30 | * - Old event type ids are never re-used; just take a new identifier. 31 | * 32 | * 33 | * The format 34 | * ---------- 35 | * 36 | * log : EVENT_HEADER_BEGIN 37 | * EventType* 38 | * EVENT_HEADER_END 39 | * EVENT_DATA_BEGIN 40 | * Event* 41 | * EVENT_DATA_END 42 | * 43 | * EventType : 44 | * EVENT_ET_BEGIN 45 | * Word16 -- unique identifier for this event 46 | * Int16 -- >=0 size of the event in bytes (minus the header) 47 | * -- -1 variable size 48 | * Word32 -- length of the next field in bytes 49 | * Word8* -- string describing the event 50 | * Word32 -- length of the next field in bytes 51 | * Word8* -- extra info (for future extensions) 52 | * EVENT_ET_END 53 | * 54 | * Event : 55 | * Word16 -- event_type 56 | * Word64 -- time (nanosecs) 57 | * [Word16] -- length of the rest (for variable-sized events only) 58 | * ... extra event-specific info ... 59 | * 60 | * 61 | * To add a new event 62 | * ------------------ 63 | * 64 | * - In this file: 65 | * - give it a new number, add a new #define EVENT_XXX below 66 | * - In EventLog.c 67 | * - add it to the EventDesc array 68 | * - emit the event type in initEventLogging() 69 | * - emit the new event in postEvent_() 70 | * - generate the event itself by calling postEvent() somewhere 71 | * - In the Haskell code to parse the event log file: 72 | * - add types and code to read the new event 73 | * 74 | * -------------------------------------------------------------------------- */ 75 | 76 | #ifndef RTS_EVENTLOGFORMAT_H 77 | #define RTS_EVENTLOGFORMAT_H 78 | 79 | /* 80 | * Markers for begin/end of the Header. 81 | */ 82 | #define EVENT_HEADER_BEGIN 0x68647262 /* 'h' 'd' 'r' 'b' */ 83 | #define EVENT_HEADER_END 0x68647265 /* 'h' 'd' 'r' 'e' */ 84 | 85 | #define EVENT_DATA_BEGIN 0x64617462 /* 'd' 'a' 't' 'b' */ 86 | #define EVENT_DATA_END 0xffff 87 | 88 | /* 89 | * Markers for begin/end of the list of Event Types in the Header. 90 | * Header, Event Type, Begin = hetb 91 | * Header, Event Type, End = hete 92 | */ 93 | #define EVENT_HET_BEGIN 0x68657462 /* 'h' 'e' 't' 'b' */ 94 | #define EVENT_HET_END 0x68657465 /* 'h' 'e' 't' 'e' */ 95 | 96 | #define EVENT_ET_BEGIN 0x65746200 /* 'e' 't' 'b' 0 */ 97 | #define EVENT_ET_END 0x65746500 /* 'e' 't' 'e' 0 */ 98 | 99 | /* 100 | * Types of event 101 | */ 102 | #define EVENT_CREATE_THREAD 0 /* (thread) */ 103 | #define EVENT_RUN_THREAD 1 /* (thread) */ 104 | #define EVENT_STOP_THREAD 2 /* (thread, status, blockinfo) */ 105 | #define EVENT_THREAD_RUNNABLE 3 /* (thread) */ 106 | #define EVENT_MIGRATE_THREAD 4 /* (thread, new_cap) */ 107 | /* 5, 6, 7 deprecated */ 108 | #define EVENT_THREAD_WAKEUP 8 /* (thread, other_cap) */ 109 | #define EVENT_GC_START 9 /* () */ 110 | #define EVENT_GC_END 10 /* () */ 111 | #define EVENT_REQUEST_SEQ_GC 11 /* () */ 112 | #define EVENT_REQUEST_PAR_GC 12 /* () */ 113 | /* 13, 14 deprecated */ 114 | #define EVENT_CREATE_SPARK_THREAD 15 /* (spark_thread) */ 115 | #define EVENT_LOG_MSG 16 /* (message ...) */ 116 | /* 17 deprecated */ 117 | #define EVENT_BLOCK_MARKER 18 /* (size, end_time, capability) */ 118 | #define EVENT_USER_MSG 19 /* (message ...) */ 119 | #define EVENT_GC_IDLE 20 /* () */ 120 | #define EVENT_GC_WORK 21 /* () */ 121 | #define EVENT_GC_DONE 22 /* () */ 122 | /* 23, 24 used by eden */ 123 | #define EVENT_CAPSET_CREATE 25 /* (capset, capset_type) */ 124 | #define EVENT_CAPSET_DELETE 26 /* (capset) */ 125 | #define EVENT_CAPSET_ASSIGN_CAP 27 /* (capset, cap) */ 126 | #define EVENT_CAPSET_REMOVE_CAP 28 /* (capset, cap) */ 127 | /* the RTS identifier is in the form of "GHC-version rts_way" */ 128 | #define EVENT_RTS_IDENTIFIER 29 /* (capset, name_version_string) */ 129 | /* the vectors in these events are null separated strings */ 130 | #define EVENT_PROGRAM_ARGS 30 /* (capset, commandline_vector) */ 131 | #define EVENT_PROGRAM_ENV 31 /* (capset, environment_vector) */ 132 | #define EVENT_OSPROCESS_PID 32 /* (capset, pid) */ 133 | #define EVENT_OSPROCESS_PPID 33 /* (capset, parent_pid) */ 134 | #define EVENT_SPARK_COUNTERS 34 /* (crt,dud,ovf,cnv,gcd,fiz,rem) */ 135 | #define EVENT_SPARK_CREATE 35 /* () */ 136 | #define EVENT_SPARK_DUD 36 /* () */ 137 | #define EVENT_SPARK_OVERFLOW 37 /* () */ 138 | #define EVENT_SPARK_RUN 38 /* () */ 139 | #define EVENT_SPARK_STEAL 39 /* (victim_cap) */ 140 | #define EVENT_SPARK_FIZZLE 40 /* () */ 141 | #define EVENT_SPARK_GC 41 /* () */ 142 | #define EVENT_INTERN_STRING 42 /* (string, id) {not used by ghc} */ 143 | #define EVENT_WALL_CLOCK_TIME 43 /* (capset, unix_epoch_seconds, nanoseconds) */ 144 | #define EVENT_THREAD_LABEL 44 /* (thread, name_string) */ 145 | #define EVENT_CAP_CREATE 45 /* (cap) */ 146 | #define EVENT_CAP_DELETE 46 /* (cap) */ 147 | #define EVENT_CAP_DISABLE 47 /* (cap) */ 148 | #define EVENT_CAP_ENABLE 48 /* (cap) */ 149 | #define EVENT_HEAP_ALLOCATED 49 /* (heap_capset, alloc_bytes) */ 150 | #define EVENT_HEAP_SIZE 50 /* (heap_capset, size_bytes) */ 151 | #define EVENT_HEAP_LIVE 51 /* (heap_capset, live_bytes) */ 152 | #define EVENT_HEAP_INFO_GHC 52 /* (heap_capset, n_generations, 153 | max_heap_size, alloc_area_size, 154 | mblock_size, block_size) */ 155 | #define EVENT_GC_STATS_GHC 53 /* (heap_capset, generation, 156 | copied_bytes, slop_bytes, frag_bytes, 157 | par_n_threads, 158 | par_max_copied, par_tot_copied) */ 159 | #define EVENT_GC_GLOBAL_SYNC 54 /* () */ 160 | #define EVENT_TASK_CREATE 55 /* (taskID, cap, tid) */ 161 | #define EVENT_TASK_MIGRATE 56 /* (taskID, cap, new_cap) */ 162 | #define EVENT_TASK_DELETE 57 /* (taskID) */ 163 | #define EVENT_USER_MARKER 58 /* (marker_name) */ 164 | #define EVENT_HACK_BUG_T9003 59 /* Hack: see trac #9003 */ 165 | 166 | /* Range 60 - 80 is used by eden for parallel tracing 167 | * see http://www.mathematik.uni-marburg.de/~eden/ 168 | */ 169 | 170 | /* these are used by eden but are replaced by new alternatives for ghc */ 171 | #define EVENT_VERSION 23 /* (version_string) */ 172 | #define EVENT_PROGRAM_INVOCATION 24 /* (commandline_string) */ 173 | 174 | /* start of parallel trace events */ 175 | #define EVENT_EDEN_START_RECEIVE 60 /* () */ 176 | #define EVENT_EDEN_END_RECEIVE 61 /* () */ 177 | #define EVENT_CREATE_PROCESS 62 /* (process) */ 178 | #define EVENT_KILL_PROCESS 63 /* (process) */ 179 | #define EVENT_ASSIGN_THREAD_TO_PROCESS 64 /* (thread, process) */ 180 | #define EVENT_CREATE_MACHINE 65 /* (machine, startupTime(in 10^-8 seconds after 19xx)) */ 181 | #define EVENT_KILL_MACHINE 66 /* (machine) */ 182 | #define EVENT_SEND_MESSAGE 67 /* (tag, sender_process, sender_thread, receiver_machine, receiver_process, receiver_inport) */ 183 | #define EVENT_RECEIVE_MESSAGE 68 /* (tag, receiver_process, receiver_inport, sender_machine, sender_process, sender_outport, message_size) */ 184 | #define EVENT_SEND_RECEIVE_LOCAL_MESSAGE 69 /* (tag, sender_process, sender_thread, receiver_process, receiver_inport) */ 185 | 186 | #define EVENT_MEM_RETURN 90 /* (cap, current_mblocks, needed_mblocks, returned_mblocks) */ 187 | #define EVENT_BLOCKS_SIZE 91 /* (heapcapset, size_bytes) */ 188 | 189 | /* Range 100 - 139 is reserved for Mercury, see below. */ 190 | 191 | /* Range 140 - 159 is reserved for Perf events, see below. */ 192 | 193 | /* Range 160 - 180 is reserved for cost-centre heap profiling events. */ 194 | 195 | #define EVENT_HEAP_PROF_BEGIN 160 196 | #define EVENT_HEAP_PROF_COST_CENTRE 161 197 | #define EVENT_HEAP_PROF_SAMPLE_BEGIN 162 198 | #define EVENT_HEAP_PROF_SAMPLE_COST_CENTRE 163 199 | #define EVENT_HEAP_PROF_SAMPLE_STRING 164 200 | #define EVENT_HEAP_PROF_SAMPLE_END 165 201 | #define EVENT_HEAP_BIO_PROF_SAMPLE_BEGIN 166 202 | #define EVENT_PROF_SAMPLE_COST_CENTRE 167 203 | #define EVENT_PROF_BEGIN 168 204 | #define EVENT_IPE 169 205 | 206 | #define EVENT_USER_BINARY_MSG 181 207 | 208 | #define EVENT_CONC_MARK_BEGIN 200 209 | #define EVENT_CONC_MARK_END 201 210 | #define EVENT_CONC_SYNC_BEGIN 202 211 | #define EVENT_CONC_SYNC_END 203 212 | #define EVENT_CONC_SWEEP_BEGIN 204 213 | #define EVENT_CONC_SWEEP_END 205 214 | #define EVENT_CONC_UPD_REM_SET_FLUSH 206 215 | #define EVENT_NONMOVING_HEAP_CENSUS 207 216 | #define EVENT_NONMOVING_PRUNED_SEGMENTS 208 217 | 218 | #define EVENT_TICKY_COUNTER_DEF 210 219 | #define EVENT_TICKY_COUNTER_SAMPLE 211 220 | #define EVENT_TICKY_BEGIN_SAMPLE 212 221 | 222 | /* 223 | * The highest event code +1 that ghc itself emits. Note that some event 224 | * ranges higher than this are reserved but not currently emitted by ghc. 225 | * This must match the size of the EventDesc[] array in EventLog.c 226 | */ 227 | #define NUM_GHC_EVENT_TAGS 213 228 | 229 | 230 | /* DEPRECATED EVENTS: */ 231 | /* shutdown replaced by EVENT_CAP_DELETE */ 232 | #define EVENT_SHUTDOWN 7 /* () */ 233 | #if 0 234 | /* ghc changed how it handles sparks so these are no longer applicable */ 235 | #define EVENT_CREATE_SPARK 13 /* (cap, thread) */ 236 | #define EVENT_SPARK_TO_THREAD 14 /* (cap, thread, spark_thread) */ 237 | #endif 238 | #define EVENT_STARTUP 17 /* (num_capabilities) */ 239 | 240 | 241 | /* 242 | * These event types are Mercury specific, Mercury may use up to event number 243 | * 139 244 | */ 245 | #define EVENT_FIRST_MER_EVENT 100 246 | #define NUM_MER_EVENTS 14 247 | 248 | #define EVENT_MER_START_PAR_CONJUNCTION 100 /* (dyn id, static id) */ 249 | #define EVENT_MER_STOP_PAR_CONJUNCTION 101 /* (dyn id) */ 250 | #define EVENT_MER_STOP_PAR_CONJUNCT 102 /* (dyn id) */ 251 | #define EVENT_MER_CREATE_SPARK 103 /* (dyn id, spark id) */ 252 | #define EVENT_MER_FUT_CREATE 104 /* (fut id, memo'd name id) */ 253 | #define EVENT_MER_FUT_WAIT_NOSUSPEND 105 /* (fut id) */ 254 | #define EVENT_MER_FUT_WAIT_SUSPENDED 106 /* (fut id) */ 255 | #define EVENT_MER_FUT_SIGNAL 107 /* (fut id) */ 256 | #define EVENT_MER_LOOKING_FOR_GLOBAL_CONTEXT \ 257 | 108 /* () */ 258 | #define EVENT_MER_WORK_STEALING 109 /* () */ 259 | #define EVENT_MER_LOOKING_FOR_LOCAL_SPARK \ 260 | 112 /* () */ 261 | #define EVENT_MER_RELEASE_CONTEXT 110 /* (context id) */ 262 | #define EVENT_MER_ENGINE_SLEEPING 111 /* () */ 263 | #define EVENT_MER_CALLING_MAIN 113 /* () */ 264 | 265 | 266 | /* 267 | * These event types are parsed from hardware performance counters logs, 268 | * such as the Linux Performance Counters data available through 269 | * the perf subsystem. 270 | */ 271 | 272 | #define EVENT_PERF_NAME 140 /* (perf_num, name) */ 273 | #define EVENT_PERF_COUNTER 141 /* (perf_num, tid, period) */ 274 | #define EVENT_PERF_TRACEPOINT 142 /* (perf_num, tid) */ 275 | 276 | 277 | /* 278 | * Status values for EVENT_STOP_THREAD 279 | * 280 | * 1-5 are the StgRun return values (from includes/rts/Constants.h): 281 | * 282 | * #define HeapOverflow 1 283 | * #define StackOverflow 2 284 | * #define ThreadYielding 3 285 | * #define ThreadBlocked 4 286 | * #define ThreadFinished 5 287 | * #define ForeignCall 6 288 | * #define BlockedOnMVar 7 289 | * #define BlockedOnMVarRead 20 290 | * NOTE: in GHC-7.8.2, this was 8, and following states shifted one up 291 | * #define BlockedOnBlackHole 8 292 | * #define BlockedOnRead 9 293 | * #define BlockedOnWrite 10 294 | * #define BlockedOnDelay 11 295 | * #define BlockedOnSTM 12 296 | * #define BlockedOnDoProc 13 297 | * NOTE: unused GUM states 8, 9 (here: 14,15) in rts/Constants.h 298 | * #define BlockedOnCCall -- not used (see ForeignCall) 299 | * #define BlockedOnCCall_NoUnblockExc -- not used (see ForeignCall) 300 | * #define BlockedOnMsgThrowTo 16 301 | * NOTE: 16 because unused GUM states ignored in ghc-events lib 302 | * Otherwise it would be 18, following would be 19, 20 303 | * TODO: verify the above is what GHC does (16/17 could be 18/19) 304 | * #define ThreadMigrating 17 305 | * #define BlockedOnMsgGlobalise 18 306 | * NOTE: not present in GHC. Mercury-Event? 307 | */ 308 | #define THREAD_SUSPENDED_FOREIGN_CALL 6 309 | 310 | /* 311 | * Capset type values for EVENT_CAPSET_CREATE 312 | */ 313 | #define CAPSET_TYPE_CUSTOM 1 /* reserved for end-user applications */ 314 | #define CAPSET_TYPE_OSPROCESS 2 /* caps belong to the same OS process */ 315 | #define CAPSET_TYPE_CLOCKDOMAIN 3 /* caps share a local clock/time */ 316 | 317 | #ifndef EVENTLOG_CONSTANTS_ONLY 318 | 319 | typedef StgWord16 EventTypeNum; 320 | typedef StgWord64 EventTimestamp; /* in nanoseconds */ 321 | typedef StgWord32 EventThreadID; 322 | typedef StgWord16 EventCapNo; 323 | typedef StgWord16 EventPayloadSize; /* variable-size events */ 324 | typedef StgWord16 EventThreadStatus; /* status for EVENT_STOP_THREAD */ 325 | typedef StgWord32 EventCapsetID; 326 | typedef StgWord16 EventCapsetType; /* types for EVENT_CAPSET_CREATE */ 327 | typedef StgWord64 EventTaskId; /* for EVENT_TASK_* */ 328 | typedef StgWord64 EventKernelThreadId; /* for EVENT_TASK_CREATE */ 329 | 330 | typedef StgWord32 EventProcessID; 331 | typedef StgWord16 EventMachineID; 332 | typedef EventThreadID EventPortID; 333 | 334 | #endif 335 | 336 | #endif /* RTS_EVENTLOGFORMAT_H */ 337 | -------------------------------------------------------------------------------- /src/GHC/RTS/EventParserUtils.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE CPP #-} 2 | {-# LANGUAGE FlexibleContexts #-} 3 | module GHC.RTS.EventParserUtils ( 4 | EventParser(..), 5 | EventParsers(..), 6 | 7 | getString, 8 | getText, 9 | getTextNul, 10 | mkEventTypeParsers, 11 | simpleEvent, 12 | skip, 13 | ) where 14 | 15 | import Data.Binary 16 | import Data.Binary.Get () 17 | import Data.Binary.Put () 18 | import Data.IntMap (IntMap) 19 | import Data.List 20 | import Data.Text (Text) 21 | import Data.Vector (Vector) 22 | import qualified Data.Binary.Get as G 23 | import qualified Data.ByteString.Char8 as B8 24 | import qualified Data.IntMap as M 25 | import qualified Data.Text.Encoding as TE 26 | import qualified Data.Text.Lazy as TL 27 | import qualified Data.Text.Lazy.Encoding as TLE 28 | import qualified Data.Vector as Vec 29 | 30 | #define EVENTLOG_CONSTANTS_ONLY 31 | #include "EventLogFormat.h" 32 | 33 | import GHC.RTS.EventTypes 34 | 35 | newtype EventParsers = EventParsers (Vector (Get EventInfo)) 36 | 37 | getString :: Integral a => a -> Get String 38 | getString len = do 39 | bytes <- G.getByteString $ fromIntegral len 40 | return $! B8.unpack bytes 41 | 42 | -- | Decode a given length of bytes as a 'Text' 43 | getText 44 | :: Integral a 45 | => a -- ^ Number of bytes to decode 46 | -> Get Text 47 | getText len = do 48 | bytes <- G.getByteString $ fromIntegral len 49 | case TE.decodeUtf8' bytes of 50 | Left err -> fail $ show err 51 | Right text -> return text 52 | 53 | -- | Decode a null-terminated string as a 'Text' 54 | getTextNul :: Get Text 55 | getTextNul = do 56 | chunks <- G.getLazyByteStringNul 57 | case TLE.decodeUtf8' chunks of 58 | Left err -> fail $ show err 59 | Right text -> return $ TL.toStrict text 60 | 61 | -- | Skip over n bytes of input 62 | skip :: Integral a => a -> Get () 63 | skip n = G.skip (fromIntegral n) 64 | 65 | -- 66 | -- Code to build the event parser table. 67 | -- 68 | 69 | -- 70 | -- | Event parser data. Parsers are either fixed or variable size. 71 | -- 72 | data EventParser a 73 | = FixedSizeParser { 74 | fsp_type :: Int, 75 | fsp_size :: EventTypeSize, 76 | fsp_parser :: Get a 77 | } 78 | | VariableSizeParser { 79 | vsp_type :: Int, 80 | vsp_parser :: Get a 81 | } 82 | 83 | getParser :: EventParser a -> Get a 84 | getParser (FixedSizeParser _ _ p) = p 85 | getParser (VariableSizeParser _ p) = p 86 | 87 | getType :: EventParser a -> Int 88 | getType (FixedSizeParser t _ _) = t 89 | getType (VariableSizeParser t _) = t 90 | 91 | isFixedSize :: EventParser a -> Bool 92 | isFixedSize (FixedSizeParser {}) = True 93 | isFixedSize (VariableSizeParser {}) = False 94 | 95 | simpleEvent :: Int -> a -> EventParser a 96 | simpleEvent t p = FixedSizeParser t 0 (return p) 97 | 98 | -- Our event log format allows new fields to be added to events over 99 | -- time. This means that our parser must be able to handle: 100 | -- 101 | -- * old versions of an event, with fewer fields than expected, 102 | -- * new versions of an event, with more fields than expected 103 | -- 104 | -- The event log file declares the size for each event type, so we can 105 | -- select the correct parser for the event type based on its size. We 106 | -- do this once after parsing the header: given the EventTypes, we build 107 | -- an array of event parsers indexed by event type. 108 | -- 109 | -- For each event type, we may have multiple parsers for different 110 | -- versions of the event, indexed by size. These are listed in the 111 | -- eventTypeParsers list below. For the given log file we select the 112 | -- parser for the most recent version (largest size doesn't exceed the size 113 | -- declared in the header). If this is a newer version of the event 114 | -- than we understand, there may be extra bytes that we have to read 115 | -- and discard in the parser for this event type. 116 | -- 117 | -- Summary: 118 | -- if size is smaller that we expect: 119 | -- parse the earlier version, or ignore the event 120 | -- if size is just right: 121 | -- parse it 122 | -- if size is too big: 123 | -- parse the bits we understand and discard the rest 124 | 125 | mkEventTypeParsers :: IntMap EventType 126 | -> [EventParser EventInfo] 127 | -> Vector (Get EventInfo) 128 | mkEventTypeParsers etypes event_parsers 129 | = Vec.fromList 130 | [ parser num | num <- [0..max_event_num] ] 131 | where 132 | max_event_num = maximum (M.keys etypes) 133 | undeclared_etype num = fail ("undeclared event type: " ++ show num) 134 | parser_map = makeParserMap event_parsers 135 | parser num = 136 | -- Get the event's size from the header, 137 | -- the first Maybe describes whether the event was declared in the header. 138 | -- the second Maybe selects between variable and fixed size events. 139 | let mb_mb_et_size = do et <- M.lookup num etypes 140 | return $ size et 141 | -- Find a parser for the event with the given size. 142 | maybe_parser mb_et_size = do possible <- M.lookup num parser_map 143 | best_parser <- case mb_et_size of 144 | Nothing -> getVariableParser possible 145 | Just et_size -> getFixedParser et_size possible 146 | return $ getParser best_parser 147 | in case mb_mb_et_size of 148 | -- This event is declared in the log file's header 149 | Just mb_et_size -> case maybe_parser mb_et_size of 150 | -- And we have a valid parser for it. 151 | Just p -> p 152 | -- But we don't have a valid parser for it. 153 | Nothing -> noEventTypeParser num mb_et_size 154 | -- This event is not declared in the log file's header 155 | Nothing -> undeclared_etype num 156 | 157 | -- Find the first variable length parser. 158 | getVariableParser :: [EventParser a] -> Maybe (EventParser a) 159 | getVariableParser [] = Nothing 160 | getVariableParser (x:xs) = case x of 161 | FixedSizeParser _ _ _ -> getVariableParser xs 162 | VariableSizeParser _ _ -> Just x 163 | 164 | -- Find the best fixed size parser, that is to say, the parser for the largest 165 | -- event that does not exceed the size of the event as declared in the log 166 | -- file's header. 167 | getFixedParser :: EventTypeSize -> [EventParser a] -> Maybe (EventParser a) 168 | getFixedParser size parsers = 169 | do parser <- ((filter isFixedSize) `pipe` 170 | (filter (\x -> (fsp_size x) <= size)) `pipe` 171 | (sortBy descending_size) `pipe` 172 | maybe_head) parsers 173 | return $ padParser size parser 174 | where pipe f g = g . f 175 | descending_size (FixedSizeParser _ s1 _) (FixedSizeParser _ s2 _) = 176 | compare s2 s1 177 | descending_size _ _ = undefined 178 | maybe_head [] = Nothing 179 | maybe_head (x:_) = Just x 180 | 181 | padParser :: EventTypeSize -> (EventParser a) -> (EventParser a) 182 | padParser _ (VariableSizeParser t p) = VariableSizeParser t p 183 | padParser size (FixedSizeParser t orig_size orig_p) = FixedSizeParser t size p 184 | where p = if (size == orig_size) 185 | then orig_p 186 | else do d <- orig_p 187 | skip (size - orig_size) 188 | return d 189 | 190 | makeParserMap :: [EventParser a] -> IntMap [EventParser a] 191 | makeParserMap = foldl buildParserMap M.empty 192 | where buildParserMap map' parser = 193 | M.alter (addParser parser) (getType parser) map' 194 | addParser p Nothing = Just [p] 195 | addParser p (Just ps) = Just (p:ps) 196 | 197 | noEventTypeParser :: Int -> Maybe EventTypeSize 198 | -> Get EventInfo 199 | noEventTypeParser num mb_size = do 200 | bytes <- case mb_size of 201 | Just n -> return n 202 | Nothing -> get :: Get Word16 203 | skip bytes 204 | return UnknownEvent{ ref = fromIntegral num } 205 | -------------------------------------------------------------------------------- /src/GHC/RTS/Events/Analysis.hs: -------------------------------------------------------------------------------- 1 | module GHC.RTS.Events.Analysis 2 | ( Machine (..) 3 | , validate 4 | , validates 5 | , simulate 6 | , Profile (..) 7 | , profile 8 | , profileIndexed 9 | , profileRouted 10 | , extractIndexed 11 | , refineM 12 | , profileM 13 | , indexM 14 | , toList 15 | , toMaybe 16 | , Process (..) 17 | , routeM 18 | ) 19 | where 20 | 21 | import GHC.RTS.Events 22 | 23 | import Data.Map (Map) 24 | import qualified Data.Map as M 25 | import Data.Maybe (fromMaybe) 26 | 27 | -------------------------------------------------------------------------------- 28 | -- | This is based on a simple finite state machine hence the names `delta` 29 | -- for the state transition function. 30 | -- Since states might be more than simple pattern matched constructors, we 31 | -- use `finals :: state -> Bool`, rather than `Set state`, to indicate that 32 | -- the machine is in some final state. Similarly for `alpha`, which 33 | -- indicates the alphabet of inputs to a machine. 34 | -- The function `delta` returns `Maybe` values, where `Nothing` 35 | -- indicates that no valid transition is possible: ie, there has been an 36 | -- error. 37 | data Machine s i = Machine 38 | { initial :: s -- ^ Initial state 39 | , final :: s -> Bool -- ^ Valid final states 40 | , alpha :: i -> Bool -- ^ Valid input alphabet 41 | , delta :: s -> i -> Maybe s -- ^ State transition function 42 | } 43 | 44 | -- | The `step` function runs a machine in a state against a single input. 45 | -- The state remains fixed once a final state is encountered. The 46 | -- result is `Left state input` if some `state` failed for an `ìnput`, and 47 | -- `Right state` for a successful state. 48 | step :: Machine s i -> s -> i -> Either (s, i) s 49 | step m s i 50 | | final m s = Right s 51 | | alpha m i = case delta m s i of 52 | Just s' -> Right s' 53 | Nothing -> Left (s, i) 54 | | otherwise = Right s 55 | 56 | -- | The `validate` function takes a machine and a list of inputs. The machine 57 | -- is started from its initial state and run against the inputs in turn. 58 | -- It returns the state and input on failure, and just the state on success. 59 | validate :: Machine s i -> [i] -> Either (s, i) s 60 | validate m = foldl (>>=) (Right (initial m)) . map (flip (step m)) 61 | 62 | -- | This function is similar to `validate`, but outputs each intermediary 63 | -- state as well. For an incremental version, use `simulate`. 64 | validates :: Machine s i -> [i] -> [Either (s, i) s] 65 | validates m = scanl (>>=) (Right (initial m)) . map (flip (step m)) 66 | 67 | -------------------------------------------------------------------------------- 68 | -- A Process is a list of successful values, followed by an error if one 69 | -- occurred. This captures the idea that a computation may produce a list of 70 | -- elements before possibly failing. This gives us an incremental interface 71 | -- to data processed from machine transitions. 72 | data Process e a 73 | = Done 74 | | Fail e 75 | | Prod a (Process e a) 76 | deriving Show 77 | 78 | toList :: Process e a -> [a] 79 | toList (Fail _) = [] 80 | toList Done = [] 81 | toList (Prod a as) = a : toList as 82 | 83 | toMaybe :: Process e a -> Maybe e 84 | toMaybe (Fail e) = Just e 85 | toMaybe Done = Nothing 86 | toMaybe (Prod _ as) = toMaybe as 87 | 88 | -- | A machine can be analysed while it is accepting input in order to extract 89 | -- some information. This function takes a machine and a function that extracts 90 | -- data and produces output. On failure, the machine state and input are 91 | -- produced. Note that when an input is not in the machine's alphabet, 92 | -- then there is no transition, and so no output is produced in response 93 | -- to that input. 94 | analyse :: Machine s i -- ^ The machine used 95 | -> (s -> i -> Maybe o) -- ^ An extraction function that may produce output 96 | -> [i] -- ^ A list of input 97 | -> Process (s, i) o -- ^ A process that produces output 98 | analyse machine extract = go (initial machine) 99 | where 100 | -- go :: s -> [i] -> Process (s, i) o 101 | go _ [] = Done 102 | go s (i:is) 103 | | final machine s = Done 104 | | alpha machine i = 105 | case delta machine s i of 106 | Nothing -> Fail (s, i) 107 | Just s' -> 108 | case extract s i of 109 | Nothing -> go s' is 110 | Just o -> Prod o (go s' is) 111 | | otherwise = go s is 112 | 113 | -- | Machines sometimes need to operate on coarser input than they are defined 114 | -- for. This function takes a function that refines input and a machine that 115 | -- works on refined input, and produces a machine that can work on coarse input. 116 | refineM :: (i -> j) -> Machine s j -> Machine s i 117 | refineM refine machine = Machine 118 | { initial = initial machine 119 | , final = final machine 120 | , alpha = alpha machine . refine 121 | , delta = \s -> delta machine s . refine 122 | } 123 | 124 | -------------------------------------------------------------------------------- 125 | -- | This function produces a process that outputs all the states that a 126 | -- machine goes through. 127 | simulate :: Machine s i -> [i] -> Process (s, i) (s, i) 128 | simulate machine = analyse machine (\s i -> delta machine s i >>= \s' -> return (s', i)) 129 | 130 | -------------------------------------------------------------------------------- 131 | -- | A state augmented by Timestamp information is held in `profileState`. 132 | -- When the state changes, `profileMap` stores a map between each state 133 | -- and its cumulative time. 134 | data Profile s = Profile 135 | { profileState :: s -- ^ The current state 136 | , profileTime :: Timestamp -- ^ The entry time of the state 137 | } deriving (Show) 138 | 139 | -- | This function takes a machine and profiles its state. 140 | profileM :: Ord s 141 | => (i -> Timestamp) 142 | -> Machine s i 143 | -> Machine (Profile s) i 144 | profileM timer machine = Machine 145 | { initial = Profile (initial machine) 0 146 | , final = final machine . profileState 147 | , alpha = alpha machine 148 | , delta = profileMDelta 149 | } 150 | where 151 | profileMDelta (Profile s _) i = do 152 | s' <- delta machine s i 153 | return $ Profile s' (timer i) 154 | 155 | -- | extractProfile returns the state, the time this state was made, 156 | -- and the time spent in this state. 157 | extractProfile :: (i -> Timestamp) -- ^ Extracts current timestamp 158 | -> Profile s -- ^ A profiled state 159 | -> i -- ^ Some input 160 | -> Maybe (s, Timestamp, Timestamp) -- ^ (state, currentTime, elapsedTime) 161 | extractProfile timer p i = Just (profileState p, profileTime p, timer i - profileTime p) 162 | 163 | profile :: (Ord s, Eq s) 164 | => Machine s i -- ^ A machine to profile 165 | -> (i -> Timestamp) -- ^ Converts input to timestamps 166 | -> [i] -- ^ The list of input 167 | -> Process (Profile s, i) (s, Timestamp, Timestamp) 168 | profile machine timer = 169 | analyse (profileM timer machine) 170 | (extractProfile timer) 171 | 172 | profileIndexed :: (Ord k, Ord s, Eq s) 173 | => Machine s i 174 | -> (i -> Maybe k) 175 | -> (i -> Timestamp) 176 | -> [i] 177 | -> Process (Map k (Profile s), i) (k, (s, Timestamp, Timestamp)) 178 | profileIndexed machine index timer = 179 | analyse (indexM index (profileM timer machine)) 180 | (extractIndexed (extractProfile timer) index) 181 | 182 | extractIndexed :: Ord k => (s -> i -> Maybe o) -> (i -> Maybe k) -> (Map k s -> i -> Maybe (k, o)) 183 | extractIndexed extract index m i = do 184 | k <- index i 185 | s <- M.lookup k m 186 | o <- extract s i 187 | return (k, o) 188 | 189 | -- | An indexed machine takes a function that multiplexes the input to a key 190 | -- and then takes a machine description to an indexed machine. 191 | indexM :: Ord k 192 | => (i -> Maybe k) -- ^ An indexing function 193 | -> Machine s i -- ^ A machine to index with 194 | -> Machine (Map k s) i -- ^ The indexed machine 195 | indexM index machine = Machine 196 | { initial = M.empty 197 | , final = indexMFinal 198 | , alpha = indexMAlpha 199 | , delta = indexMDelta 200 | } 201 | where 202 | -- An indexer never reaches a final state: it is always possible that 203 | -- an event comes along that is accepted by a machine that is not 204 | -- yet in in the index. 205 | -- 206 | -- An alternative view is that the indexer is in a final state if all its 207 | -- elements are, but this would not allow the creation of new indexes: 208 | -- indexMFinal m = not (M.null m) && (all (final machine) . M.elems $ m) 209 | indexMFinal = const False 210 | 211 | -- The alphabet of the indexer is that of its elements. 212 | indexMAlpha = alpha machine 213 | 214 | -- If the index is not yet in the mapping, we start a new machine in its 215 | -- initial state. The indexer fails if indexed state fails. 216 | indexMDelta m i = do 217 | k <- index i 218 | let state = fromMaybe (initial machine) (M.lookup k m) 219 | state' <- delta machine state i 220 | return $ M.insert k state' m 221 | 222 | profileRouted :: (Ord k, Ord s, Eq s, Eq r) 223 | => Machine s i 224 | -> Machine r i 225 | -> (r -> i -> Maybe k) 226 | -> (i -> Timestamp) 227 | -> [i] 228 | -> Process ((Map k (Profile s), r), i) (k, (s, Timestamp, Timestamp)) 229 | profileRouted machine router index timer = 230 | analyse (routeM router index (profileM timer machine)) 231 | (extractRouted (extractProfile timer) index) 232 | 233 | extractRouted :: Ord k => (s -> i -> Maybe o) -> (r -> i -> Maybe k) -> ((Map k s, r) -> i -> Maybe (k, o)) 234 | extractRouted extract index (m, r) i = do 235 | k <- index r i 236 | s <- M.lookup k m 237 | o <- extract s i 238 | return (k, o) 239 | 240 | 241 | -- | A machine can be indexed not only by the inputs, but also by the state 242 | -- of an intermediary routing machine. This is a generalisation of indexM. 243 | routeM :: (Ord k) 244 | => Machine r i 245 | -> (r -> i -> Maybe k) 246 | -> Machine s i 247 | -> Machine (Map k s, r) i 248 | routeM router index machine = Machine 249 | { initial = (M.empty, initial router) 250 | , final = routeMFinal 251 | , alpha = routeMAlpha 252 | , delta = routeMDelta 253 | } 254 | where 255 | -- As with indexers, there is no final state. 256 | routeMFinal = const False 257 | 258 | -- The alphabet is that of the router combined with the machine 259 | routeMAlpha i = alpha router i || alpha machine i 260 | 261 | routeMDelta (m, r) i = do 262 | r' <- if alpha router i 263 | then delta router r i 264 | else return r 265 | m' <- if alpha machine i 266 | then case index r' i of 267 | Just k -> do 268 | s' <- delta machine (fromMaybe (initial machine) (M.lookup k m)) i 269 | return $ M.insert k s' m 270 | Nothing -> return m 271 | else return m 272 | return (m', r') 273 | -------------------------------------------------------------------------------- /src/GHC/RTS/Events/Analysis/Capability.hs: -------------------------------------------------------------------------------- 1 | module GHC.RTS.Events.Analysis.Capability 2 | ( capabilityThreadPoolMachine 3 | , capabilityThreadRunMachine 4 | , capabilityThreadIndexer 5 | , capabilityTaskPoolMachine 6 | , capabilityTaskOSMachine 7 | ) 8 | where 9 | 10 | import GHC.RTS.Events 11 | import GHC.RTS.Events.Analysis 12 | 13 | import Data.Map (Map) 14 | import qualified Data.Map as M 15 | 16 | -- | This state machine tracks threads residing on capabilities. 17 | -- Each thread can only reside on one capability, but can be migrated between 18 | -- them. 19 | capabilityThreadPoolMachine :: Machine (Map ThreadId Int) Event 20 | capabilityThreadPoolMachine = Machine 21 | { initial = M.empty 22 | , final = const False 23 | , alpha = capabilityThreadPoolMachineAlpha 24 | , delta = capabilityThreadPoolMachineDelta 25 | } 26 | where 27 | capabilityThreadPoolMachineAlpha evt = case evSpec evt of 28 | (CreateThread _) -> True 29 | (StopThread _ _) -> True 30 | (MigrateThread _ _) -> True 31 | _ -> False 32 | 33 | capabilityThreadPoolMachineDelta mapping evt = do 34 | capId <- evCap evt 35 | case evSpec evt of 36 | (CreateThread threadId) -> insertThread threadId capId mapping 37 | (StopThread threadId ThreadFinished) -> deleteThread threadId mapping 38 | (StopThread _ _) -> Just mapping 39 | (MigrateThread threadId capId') -> deleteThread threadId mapping >>= 40 | insertThread threadId capId' 41 | _ -> Nothing 42 | where 43 | insertThread :: ThreadId -> Int -> Map ThreadId Int -> Maybe (Map ThreadId Int) 44 | insertThread threadId capId m 45 | | threadId `M.member` m = Nothing -- The thread already exists 46 | | otherwise = Just $ M.insert threadId capId m 47 | 48 | deleteThread :: ThreadId -> Map ThreadId Int -> Maybe (Map ThreadId Int) 49 | deleteThread threadId m 50 | | threadId `M.notMember` m = Nothing -- The thread doesn't exist 51 | | otherwise = Just $ M.delete threadId m 52 | 53 | -- | This state machine tracks threads running on capabilities, only one thread 54 | -- may run on a capability at a time. 55 | capabilityThreadRunMachine :: Machine (Map Int ThreadId) Event 56 | capabilityThreadRunMachine = Machine 57 | { initial = M.empty 58 | , final = const False 59 | , alpha = threadRunAlpha 60 | , delta = threadRunDelta 61 | } 62 | where 63 | threadRunAlpha event = case evSpec event of 64 | -- TODO: can threads be migrated while they are running? 65 | -- TODO: take into account paused threads 66 | (RunThread _) -> True 67 | (StopThread _ _ ) -> True 68 | _ -> False 69 | 70 | -- The indexer fails if a thread is inserted where one already exists, 71 | -- or if a thread is deleted that doesn't exist. 72 | threadRunDelta mapping e = do 73 | capId <- evCap e 74 | case evSpec $ e of 75 | (RunThread threadId) -> runThread capId threadId mapping 76 | (StopThread threadId _ ) -> stopThread threadId mapping 77 | _ -> Just mapping 78 | where 79 | runThread :: Int -> ThreadId -> Map Int ThreadId -> Maybe (Map Int ThreadId) 80 | runThread capId threadId m 81 | | capId `M.member` m = Nothing -- A thread is already on this cap 82 | | threadId `elem` M.elems m = Nothing -- This thread is already on a cap 83 | | otherwise = Just $ M.insert capId threadId m 84 | stopThread :: ThreadId -> Map Int ThreadId -> Maybe (Map Int ThreadId) 85 | stopThread threadId m 86 | | notElem threadId . M.elems $ m = Nothing -- The thread doesn't exist 87 | | otherwise = Just $ M.filter (/= threadId) m 88 | 89 | capabilityThreadIndexer :: Map Int ThreadId -> Event -> Maybe ThreadId 90 | capabilityThreadIndexer m evt = case evSpec evt of 91 | (CreateSparkThread threadId) -> Just threadId 92 | (CreateThread threadId) -> Just threadId 93 | (RunThread threadId) -> Just threadId 94 | (StopThread threadId _) -> Just threadId 95 | (ThreadRunnable threadId) -> Just threadId 96 | (MigrateThread threadId _) -> Just threadId 97 | (WakeupThread threadId capId) -> if Just capId == evCap evt 98 | then Just threadId 99 | else Nothing 100 | _ -> mThreadId 101 | where 102 | mThreadId = evCap evt >>= (\capId -> M.lookup capId m) 103 | 104 | -- | This state machine tracks Haskell tasks, represented by TaskId, 105 | -- residing on capabilities. 106 | -- Each Haskell task can only reside on one capability, but can be migrated 107 | -- between them. 108 | capabilityTaskPoolMachine :: Machine (Map TaskId Int) Event 109 | capabilityTaskPoolMachine = Machine 110 | { initial = M.empty 111 | , final = const False 112 | , alpha = capabilityTaskPoolMachineAlpha 113 | , delta = capabilityTaskPoolMachineDelta 114 | } 115 | where 116 | capabilityTaskPoolMachineAlpha evt = case evSpec evt of 117 | TaskCreate{} -> True 118 | TaskDelete{} -> True 119 | TaskMigrate{} -> True 120 | _ -> False 121 | 122 | capabilityTaskPoolMachineDelta mapping evt = do 123 | case evSpec evt of 124 | TaskCreate {taskId, cap} -> insertTask taskId cap mapping 125 | TaskDelete {taskId} -> deleteTask taskId Nothing mapping 126 | TaskMigrate {taskId, cap, new_cap} -> 127 | deleteTask taskId (Just cap) mapping >>= 128 | insertTask taskId new_cap 129 | _ -> Nothing 130 | where 131 | insertTask :: TaskId -> Int -> Map TaskId Int 132 | -> Maybe (Map TaskId Int) 133 | insertTask taskId cap m 134 | | taskId `M.member` m = Nothing -- The task already exists. 135 | | otherwise = Just $ M.insert taskId cap m 136 | 137 | deleteTask :: TaskId -> Maybe Int -> Map TaskId Int 138 | -> Maybe (Map TaskId Int) 139 | deleteTask taskId expectedcap m 140 | | Just oldcap <- M.lookup taskId m 141 | , maybe True (==oldcap) expectedcap 142 | = Just $ M.delete taskId m 143 | | otherwise 144 | = Nothing -- The task doesn't exist, or does but with an unexpected cap. 145 | 146 | -- | This state machine tracks Haskell tasks (represented by the KernelThreadId 147 | -- of their OS thread) residing on capabilities and additionally 148 | -- tracks the (immutable) assignment of OS thread ids (KernelThreadId) 149 | -- to tasks ids (TaskId). 150 | -- Each Haskell task can only reside on one capability, but can be migrated 151 | -- between them. 152 | -- 153 | -- Invariant for the @(Map KernelThreadId Int, Map TaskId KernelThreadId)@ 154 | -- type: the second map is an injection (verified by the machine 155 | -- in 'insertTaskOS') and the following sets are equal: 156 | -- keys of the fist map and values of the second 157 | -- (follows from the construction of the maps by the machine). 158 | -- 159 | -- The machine verifies as much as 'capabilityTaskPoolMachine' and additionally 160 | -- the data invariant, and offers a richer verification profile. 161 | capabilityTaskOSMachine :: Machine (Map KernelThreadId Int, 162 | Map TaskId KernelThreadId) 163 | Event 164 | capabilityTaskOSMachine = Machine 165 | { initial = (M.empty, M.empty) 166 | , final = const False 167 | , alpha = capabilityTaskOSMachineAlpha 168 | , delta = capabilityTaskOSMachineDelta 169 | } 170 | where 171 | capabilityTaskOSMachineAlpha evt = case evSpec evt of 172 | TaskCreate{} -> True 173 | TaskDelete{} -> True 174 | TaskMigrate{} -> True 175 | _ -> False 176 | 177 | capabilityTaskOSMachineDelta mapping evt = do 178 | case evSpec evt of 179 | TaskCreate {taskId, cap, tid} -> insertTaskOS taskId cap tid mapping 180 | TaskDelete {taskId} -> deleteTaskOS taskId mapping 181 | TaskMigrate {taskId, new_cap} -> migrateTaskOS taskId new_cap mapping 182 | _ -> Nothing 183 | where 184 | insertTaskOS :: TaskId -> Int -> KernelThreadId 185 | -> (Map KernelThreadId Int, Map TaskId KernelThreadId) 186 | -> Maybe (Map KernelThreadId Int, Map TaskId KernelThreadId) 187 | insertTaskOS taskId cap tid (m, ma) 188 | | taskId `M.member` ma = Nothing -- The task already exists. 189 | | tid `M.member` m = Nothing -- The OS thread already exists. 190 | | otherwise = Just (M.insert tid cap m, 191 | M.insert taskId tid ma) 192 | 193 | deleteTaskOS :: TaskId -> (Map KernelThreadId Int, 194 | Map TaskId KernelThreadId) 195 | -> Maybe (Map KernelThreadId Int, Map TaskId KernelThreadId) 196 | deleteTaskOS taskId (m, ma) = 197 | case M.lookup taskId ma of 198 | Nothing -> Nothing -- The task doesn't exist. 199 | Just tid -> Just (M.delete tid m, 200 | M.delete taskId ma) 201 | 202 | migrateTaskOS :: TaskId -> Int -> (Map KernelThreadId Int, 203 | Map TaskId KernelThreadId) 204 | -> Maybe (Map KernelThreadId Int, Map TaskId KernelThreadId) 205 | migrateTaskOS taskId new_cap (m, ma) = 206 | case M.lookup taskId ma of 207 | Nothing -> Nothing -- The task doesn't exist. 208 | Just tid -> Just (M.insert tid new_cap m, 209 | ma) -- The assignment is immutable. 210 | -------------------------------------------------------------------------------- /src/GHC/RTS/Events/Analysis/SparkThread.hs: -------------------------------------------------------------------------------- 1 | module GHC.RTS.Events.Analysis.SparkThread 2 | ( SparkThreadState (..) 3 | , sparkThreadMachine 4 | , capabilitySparkThreadMachine 5 | , capabilitySparkThreadIndexer 6 | ) 7 | where 8 | 9 | import GHC.RTS.Events 10 | import GHC.RTS.Events.Analysis 11 | 12 | import Data.Map (Map) 13 | import qualified Data.Map as M 14 | import Data.Set (Set) 15 | import qualified Data.Set as S 16 | 17 | data SparkThreadState 18 | = SparkThreadInitial 19 | | SparkThreadCreated 20 | | SparkThreadRunning Int 21 | | SparkThreadPaused Int 22 | | SparkThreadFinal 23 | deriving (Eq, Ord, Show) 24 | 25 | sparkThreadMachine :: Machine SparkThreadState EventInfo 26 | sparkThreadMachine = Machine 27 | { initial = SparkThreadInitial 28 | , final = sparkThreadFinal 29 | , alpha = sparkThreadAlpha 30 | , delta = sparkThreadDelta 31 | } 32 | where 33 | sparkThreadFinal SparkThreadFinal = True 34 | sparkThreadFinal _ = False 35 | 36 | -- sparkThreadAlpha (CreateSparkThread _) = True 37 | sparkThreadAlpha (RunThread _) = True 38 | sparkThreadAlpha (StopThread _ _) = True 39 | sparkThreadAlpha SparkRun = True 40 | sparkThreadAlpha (SparkSteal _) = True 41 | sparkThreadAlpha _ = False 42 | 43 | -- SparkThreadInitial 44 | -- sparkThreadDelta SparkThreadInitial (CreateSparkThread _) = Just SparkThreadInitial 45 | sparkThreadDelta SparkThreadInitial (RunThread _) = Just SparkThreadCreated 46 | -- SparkThreadCreated 47 | sparkThreadDelta SparkThreadCreated SparkRun = Just (SparkThreadRunning 0) 48 | sparkThreadDelta SparkThreadCreated (SparkSteal _) = Just (SparkThreadRunning 0) 49 | sparkThreadDelta SparkThreadCreated (StopThread _ ThreadFinished) = Just SparkThreadFinal 50 | -- SparkThreadRunning 51 | sparkThreadDelta (SparkThreadRunning _) (StopThread _ ThreadFinished) = Just SparkThreadFinal 52 | sparkThreadDelta (SparkThreadRunning n) (StopThread _ _) = Just (SparkThreadPaused n) 53 | sparkThreadDelta (SparkThreadRunning n) SparkRun = Just (SparkThreadRunning (n+1)) 54 | sparkThreadDelta (SparkThreadRunning n) (SparkSteal _) = Just (SparkThreadRunning (n+1)) 55 | -- SparkThreadPaused 56 | sparkThreadDelta (SparkThreadPaused n) (RunThread _) = Just (SparkThreadRunning n) 57 | -- Other 58 | sparkThreadDelta _ _ = Nothing 59 | 60 | capabilitySparkThreadMachine :: Machine (Map Int ThreadId, Set ThreadId) Event 61 | capabilitySparkThreadMachine = Machine 62 | { initial = (M.empty, S.empty) 63 | , final = const False 64 | , alpha = capabilitySparkThreadAlpha 65 | , delta = capabilitySparkThreadDelta 66 | } 67 | where 68 | capabilitySparkThreadAlpha evt = case evSpec evt of 69 | (CreateSparkThread _) -> True 70 | (RunThread _) -> True 71 | (StopThread _ _) -> True 72 | _ -> False 73 | capabilitySparkThreadDelta (m, s) evt = do 74 | capId <- evCap evt 75 | case evSpec evt of 76 | (CreateSparkThread threadId) -> createThread threadId 77 | (StopThread threadId _) -> pauseThread threadId 78 | (RunThread threadId) -> runThread capId threadId 79 | _ -> Just (m, s) 80 | where 81 | createThread :: ThreadId -> Maybe (Map Int ThreadId, Set ThreadId) 82 | createThread threadId 83 | | S.member threadId s = Nothing -- A spark thread with this Id already created 84 | | otherwise = Just (m, S.insert threadId s) 85 | 86 | runThread :: Int -> ThreadId -> Maybe (Map Int ThreadId, Set ThreadId) 87 | runThread capId threadId 88 | | M.member capId m = Nothing -- A thread is already on this cap 89 | | threadId `elem` M.elems m = Nothing -- This thread is already on a cap 90 | | S.notMember threadId s = Just (m, s) -- Not a spark thread 91 | | otherwise = Just (M.insert capId threadId m, S.insert threadId s) 92 | 93 | stopThread :: ThreadId -> Maybe (Map Int ThreadId, Set ThreadId) 94 | stopThread threadId = Just (M.filter (/= threadId) m, S.delete threadId s) 95 | 96 | pauseThread :: ThreadId -> Maybe (Map Int ThreadId, Set ThreadId) 97 | pauseThread threadId = Just (M.filter (/= threadId) m, s) 98 | 99 | capabilitySparkThreadIndexer :: (Map Int ThreadId, Set ThreadId) -> Event -> Maybe ThreadId 100 | capabilitySparkThreadIndexer (m, s) evt = case evSpec evt of 101 | (CreateThread threadId) -> inSparkThreadPool threadId 102 | (RunThread threadId) -> inSparkThreadPool threadId 103 | (StopThread threadId _) -> inSparkThreadPool threadId 104 | _ -> evCap evt >>= (\capId -> M.lookup capId m) 105 | where 106 | inSparkThreadPool :: ThreadId -> Maybe ThreadId 107 | inSparkThreadPool threadId 108 | | S.member threadId s = Just threadId 109 | | otherwise = Nothing 110 | 111 | -------------------------------------------------------------------------------- /src/GHC/RTS/Events/Analysis/Thread.hs: -------------------------------------------------------------------------------- 1 | module GHC.RTS.Events.Analysis.Thread 2 | ( ThreadState (..) 3 | , threadMachine 4 | ) 5 | where 6 | 7 | import GHC.RTS.Events 8 | import GHC.RTS.Events.Analysis 9 | 10 | -------------------------------------------------------------------------------- 11 | -- | This datatype defines the state machine for a single thread. 12 | data ThreadState 13 | = ThreadInitial 14 | | ThreadQueued 15 | | ThreadRunning 16 | | ThreadStopped 17 | | ThreadFinal 18 | deriving (Show, Eq, Ord) 19 | 20 | -- | This state machine tracks the events processed by a thread. 21 | threadMachine :: Machine ThreadState EventInfo 22 | threadMachine = Machine 23 | { initial = ThreadInitial 24 | , final = threadFinal 25 | , alpha = threadAlpha 26 | , delta = threadDelta 27 | } 28 | where 29 | threadFinal ThreadFinal = True 30 | threadFinal _ = False 31 | 32 | threadAlpha (CreateThread _) = True 33 | threadAlpha (RunThread _) = True 34 | threadAlpha (StopThread _ _) = True 35 | threadAlpha (WakeupThread _ _) = True 36 | threadAlpha _ = False 37 | 38 | -- ThreadInitial 39 | threadDelta ThreadInitial (CreateThread _) = Just ThreadQueued 40 | -- ThreadQueued 41 | threadDelta ThreadQueued (RunThread _) = Just ThreadRunning 42 | threadDelta ThreadQueued (WakeupThread _ _) = Just ThreadQueued 43 | -- ThreadRunning 44 | threadDelta ThreadRunning (StopThread _ StackOverflow) = Just ThreadQueued 45 | threadDelta ThreadRunning (StopThread _ HeapOverflow) = Just ThreadQueued 46 | threadDelta ThreadRunning (StopThread _ ForeignCall) = Just ThreadQueued 47 | threadDelta ThreadRunning (StopThread _ ThreadFinished) = Just ThreadFinal 48 | threadDelta ThreadRunning (StopThread _ _) = Just ThreadStopped 49 | -- ThreadStopped 50 | threadDelta ThreadStopped (RunThread _) = Just ThreadRunning 51 | threadDelta ThreadStopped (WakeupThread _ _) = Just ThreadQueued 52 | -- Unknown 53 | threadDelta _ _ = Nothing -------------------------------------------------------------------------------- /src/GHC/RTS/Events/Incremental.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE CPP #-} 2 | {-# LANGUAGE OverloadedStrings #-} 3 | {-# LANGUAGE MultiWayIf #-} 4 | 5 | module GHC.RTS.Events.Incremental 6 | ( -- * Incremental API 7 | Decoder(..) 8 | , decodeHeader 9 | , decodeEvents 10 | , decodeEventLog 11 | 12 | -- * Lazy API 13 | , readHeader 14 | , readEvents 15 | , readEvents' 16 | , readEventLog 17 | , readEventLogOrFail 18 | ) where 19 | import Control.Monad 20 | import Data.Either 21 | import Data.Maybe 22 | import Prelude 23 | 24 | import qualified Data.Binary.Get as G 25 | import qualified Data.ByteString as B 26 | import qualified Data.ByteString.Lazy as BL 27 | import qualified Data.ByteString.Lazy.Internal as BL 28 | import qualified Data.IntMap.Strict as IM 29 | 30 | import GHC.RTS.EventParserUtils 31 | import GHC.RTS.EventTypes 32 | import GHC.RTS.Events.Binary 33 | 34 | #define EVENTLOG_CONSTANTS_ONLY 35 | #include "EventLogFormat.h" 36 | 37 | -- | The unfolding of the decoding process. 38 | data Decoder a 39 | = Consume (B.ByteString -> Decoder a) 40 | -- ^ The decoder has consumed all the available input and needs more to 41 | -- continue. 42 | | Produce !a (Decoder a) 43 | -- ^ The decoder has returned a decoded value and the next decoder state to 44 | -- continue. 45 | | Done B.ByteString 46 | -- ^ The decoder has ended with leftover input. 47 | | Error B.ByteString String 48 | -- ^ The decoder has encountered an error with leftover input and an error 49 | -- message. 50 | 51 | -- | Push an input chunk to the decoder 52 | pushChunk :: Decoder a -> B.ByteString -> Decoder a 53 | pushChunk decoder chunk = case decoder of 54 | Consume k -> k chunk 55 | Produce a decoder' -> Produce a $ decoder' `pushChunk` chunk 56 | Done leftover -> Done $ leftover `B.append` chunk 57 | Error leftover err -> Error (leftover `B.append` chunk) err 58 | 59 | -- | Decode a header and continue with the provided decoder 60 | withHeader 61 | :: (Header -> B.ByteString -> Decoder r) 62 | -- ^ Continuation 63 | -> Decoder r 64 | withHeader f = go $ G.runGetIncremental getHeader 65 | where 66 | go decoder = case decoder of 67 | G.Done leftover _ header -> f header leftover 68 | G.Partial k -> Consume $ \chunk -> go $ k $ Just chunk 69 | G.Fail leftover _ err -> Error leftover err 70 | 71 | -- | Decode a header 72 | decodeHeader :: Decoder Header 73 | decodeHeader = withHeader $ \header leftover -> Produce header $ Done leftover 74 | 75 | -- | Decode events 76 | decodeEvents :: Header -> Decoder Event 77 | decodeEvents header = go (0 :: Int) Nothing decoder0 78 | where 79 | decoder0 = mkEventDecoder header 80 | go !remaining !blockCap decoder = case decoder of 81 | G.Done leftover consumed r -> do 82 | let !decoder' = decoder0 `G.pushChunk` leftover 83 | case r of 84 | Just event -> case evSpec event of 85 | EventBlock {..} -> 86 | go (fromIntegral block_size) (mkCap cap) decoder' 87 | _ -> do 88 | let 89 | !remaining' = remaining - fromIntegral consumed 90 | !blockCap' = if remaining' > 0 then blockCap else Nothing 91 | !event' = event { evCap = blockCap } 92 | Produce event' $ go remaining' blockCap' decoder' 93 | Nothing -> go remaining blockCap decoder' 94 | G.Partial k -> 95 | Consume $ \chunk -> go remaining blockCap $ k $ Just chunk 96 | G.Fail leftover _ err -> 97 | Error leftover err 98 | 99 | -- | Decode a header and events 100 | decodeEventLog :: Decoder Event 101 | decodeEventLog = withHeader $ \header leftover -> 102 | decodeEvents header `pushChunk` leftover 103 | 104 | -- | Read a header from a lazy bytestring and return the header and the 105 | -- leftover input for subsequent decoding. 106 | -- 107 | -- Note that the input must contain a whole header in one go. If incremental 108 | -- parsing of a header is necessary, use 'decodeHeader' instead. 109 | readHeader :: BL.ByteString -> Either String (Header, BL.ByteString) 110 | readHeader = go $ Left decodeHeader 111 | where 112 | go r bytes = case r of 113 | Left decoder -> case decoder of 114 | Produce header decoder' -> case decoder' of 115 | Done leftover -> Right (header, BL.Chunk leftover bytes) 116 | _ -> Left "readHeader: unexpected decoder" 117 | Consume k -> case bytes of 118 | BL.Empty -> Left "readHeader: not enough bytes" 119 | BL.Chunk chunk chunks -> go (Left $! k chunk) chunks 120 | Done _ -> Left "readHeader: unexpected termination" 121 | Error _ err -> Left err 122 | Right header -> Right (header, bytes) 123 | 124 | 125 | -- | Read events from a lazy bytestring. It returns an error message if it 126 | -- encounters an error while decoding the header. 127 | -- 128 | -- Note that it doesn't fail if it consumes all input in the middle of decoding 129 | -- of an event. 130 | readEvents :: Header -> BL.ByteString -> ([Event], Maybe String) 131 | readEvents header = f . break isLeft . readEvents' header 132 | where 133 | f (rs, ls) = (rights rs, listToMaybe (lefts ls)) 134 | 135 | -- | Read events from a lazy bytestring. It returns an error message if it 136 | -- encounters an error while decoding the header. 137 | -- 138 | -- Note that it doesn't fail if it consumes all input in the middle of decoding 139 | -- of an event. 140 | readEvents' :: Header -> BL.ByteString -> [Either String Event] 141 | readEvents' header = go (decodeEvents header) 142 | where 143 | go :: Decoder Event -> BL.ByteString -> [Either String Event] 144 | go decoder bytes = case decoder of 145 | Produce event decoder' -> Right event : go decoder' bytes 146 | Consume k -> case bytes of 147 | BL.Empty -> [] 148 | BL.Chunk chunk chunks -> go (k chunk) chunks 149 | Done {} -> [] 150 | Error _ err -> [Left err] 151 | 152 | -- | Read an entire event log from a lazy bytestring. It returns an error message if it 153 | -- encounters an error while decoding. 154 | -- 155 | -- Note that it doesn't fail if it consumes all input in the middle of decoding 156 | -- of an event. 157 | readEventLog :: BL.ByteString -> Either String (EventLog, Maybe String) 158 | readEventLog bytes = do 159 | (header, bytes') <- readHeader bytes 160 | case readEvents header bytes' of 161 | (events, err) -> return (EventLog header (Data events), err) 162 | 163 | -- | Read an entire event log from a lazy bytestring. It returns an error message if it 164 | -- encounters an error while decoding. 165 | -- 166 | -- This will raise an error if a malformed event is encountered during decoding. 167 | readEventLogOrFail :: BL.ByteString -> Either String EventLog 168 | readEventLogOrFail bytes = do 169 | (header, bs') <- readHeader bytes 170 | let events = zipWith idOrThrowErr [1..] (readEvents' header bs') 171 | return $ EventLog header (Data events) 172 | where 173 | idOrThrowErr :: Int -> Either String Event -> Event 174 | idOrThrowErr i (Left err) = error $ "readEventLogOrFail: error deserialising event " ++ show i ++ ": " ++ err 175 | idOrThrowErr _ (Right ev) = ev 176 | 177 | -- | Makes a decoder with all the required parsers when given a Header 178 | mkEventDecoder :: Header -> G.Decoder (Maybe Event) 179 | mkEventDecoder header = G.runGetIncremental $ getEvent parsers 180 | where 181 | imap = IM.fromList [(fromIntegral (num t), t) | t <- eventTypes header] 182 | 183 | event_parsers = concat 184 | [ standardParsers 185 | , parRTSParsers sz_tid 186 | , mercuryParsers 187 | , perfParsers 188 | , heapProfParsers 189 | , timeProfParsers 190 | , binaryEventParsers 191 | , tickyParsers 192 | ] 193 | parsers = EventParsers $ mkEventTypeParsers imap event_parsers 194 | -------------------------------------------------------------------------------- /src/GHC/RTS/Events/Merge.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE CPP #-} 2 | module GHC.RTS.Events.Merge (mergeEventLogs) where 3 | 4 | import GHC.RTS.Events 5 | import Data.Monoid 6 | import Data.List (foldl') 7 | import qualified Data.Map as M 8 | import Data.Word (Word32) 9 | import Prelude 10 | 11 | -- TODO: add a merge mode where the events are synchronized using 12 | -- the wall clock time event at the start of both event logs (for newer GHCs). 13 | -- Such merge is not associative so we either need to take many arguments 14 | -- or cope with event logs with many wall clock time events (assume they 15 | -- are products of previous merges). To decide. 16 | 17 | {- 18 | GHC numbers caps and capsets in sequential order, starting at 0. Threads are 19 | similarly numbered, but start at 1. In order to merge logs 'x' and 'y', 20 | we find the # of occupied numbers for each variable type in 'x', 21 | then increment each variable in 'y' by that amount. 22 | We assume that if a number is occupied, so are all lower numbers. 23 | This guarantees that variables in each log don't clash, 24 | and that the meaning of each reference to a thread/cap/capset is 25 | preserved. 26 | -} 27 | 28 | mergeEventLogs :: EventLog -> EventLog -> EventLog 29 | mergeEventLogs (EventLog h1 (Data xs)) (EventLog h2 (Data ys)) = 30 | let headerMap = M.fromList . map (\ et@EventType {num} -> (num, et)) 31 | m1 = headerMap $ eventTypes h1 32 | m2 = headerMap $ eventTypes h2 33 | combine et1 et2 | et1 == et2 = et1 34 | combine _ _ = error "can't merge event logs with inconsistent headers" 35 | m = M.unionWith combine m1 m2 36 | h = Header $ M.elems m 37 | in h == h `seq` -- Detect inconsistency ASAP. 38 | EventLog h . Data . mergeOn evTime xs $ shift (maxVars xs) ys 39 | 40 | mergeOn :: Ord b => (a -> b) -> [a] -> [a] -> [a] 41 | mergeOn _ [] ys = ys 42 | mergeOn _ xs [] = xs 43 | mergeOn f (x:xs) (y:ys) | f x <= f y = x : mergeOn f xs (y:ys) 44 | | otherwise = y : mergeOn f (x:xs) ys 45 | 46 | -- TODO: rename, since these are not maximal values, but numbers of used values 47 | data MaxVars = MaxVars { mcapset :: !Word32 48 | , mcap :: !Int 49 | , mthread :: !ThreadId } 50 | -- TODO introduce parallel RTS process and machine var.s 51 | 52 | combineMaxVars :: MaxVars -> MaxVars -> MaxVars 53 | combineMaxVars (MaxVars a b c) (MaxVars x y z) = 54 | MaxVars (max a x) (b + y) (max c z) 55 | 56 | #if MIN_VERSION_base(4,11,0) 57 | instance Semigroup MaxVars where 58 | (<>) = combineMaxVars 59 | #endif 60 | 61 | instance Monoid MaxVars where 62 | mempty = MaxVars 0 0 0 63 | #if MIN_VERSION_base(4,11,0) 64 | mappend = (<>) 65 | #else 66 | mappend = combineMaxVars 67 | #endif 68 | -- avoid space leaks: 69 | mconcat = foldl' mappend mempty 70 | 71 | -- For caps we find the maximum value by summing the @Startup@ declarations. 72 | -- TODO: it's not trivial to add CapCreate since we don't know 73 | -- if created caps are guaranteed to be numbered consecutively or not 74 | -- (are they? is it asserted in GHC code somewhere?). We might instead 75 | -- just scan all events mentioning a cap and take the maximum, 76 | -- but it's a slower and much longer code, requiring constant maintenance. 77 | maxVars :: [Event] -> MaxVars 78 | maxVars = mconcat . map (maxSpec . evSpec) 79 | where 80 | -- only checking binding sites right now, sufficient? 81 | maxSpec (Startup n) = mempty { mcap = n } 82 | -- Threads start at 1. 83 | maxSpec (CreateThread t) = mempty { mthread = t } 84 | maxSpec (CreateSparkThread t) = mempty { mthread = t } 85 | -- Capsets start at 0. 86 | maxSpec (CapsetCreate cs _) = mempty {mcapset = cs + 1 } 87 | maxSpec _ = mempty 88 | 89 | sh :: Num a => a -> a -> a 90 | sh x y = x + y 91 | 92 | updateSpec :: (EventInfo -> EventInfo) -> Event -> Event 93 | updateSpec f (Event {evTime = t, evSpec = s, evCap = cap}) = 94 | Event {evTime = t, evSpec = f s, evCap = cap} 95 | 96 | shift :: MaxVars -> [Event] -> [Event] 97 | shift (MaxVars mcs mc mt) = map (updateSpec shift') 98 | where 99 | -- -1 marks a block that isn't attached to a particular capability 100 | shift' (CreateThread t) = CreateThread $ sh mt t 101 | shift' (RunThread t) = RunThread $ sh mt t 102 | shift' (StopThread t s) = StopThread (sh mt t) s 103 | shift' (ThreadRunnable t) = ThreadRunnable $ sh mt t 104 | shift' (MigrateThread t c) = MigrateThread (sh mt t) (sh mc c) 105 | shift' (WakeupThread t c) = WakeupThread (sh mt t) (sh mc c) 106 | shift' (ThreadLabel t l) = ThreadLabel (sh mt t) l 107 | shift' (CreateSparkThread t) = CreateSparkThread (sh mt t) 108 | shift' (SparkSteal c) = SparkSteal (sh mc c) 109 | shift' (TaskCreate tk c tid) = TaskCreate tk (sh mc c) tid 110 | shift' (TaskMigrate tk c1 c2) = TaskMigrate tk (sh mc c1) (sh mc c2) 111 | shift' (CapCreate c) = CapCreate (sh mc c) -- TODO: correct? 112 | shift' (CapDelete c) = CapDelete (sh mc c) -- TODO: correct? 113 | shift' (CapDisable c) = CapDisable (sh mc c) 114 | shift' (CapEnable c) = CapEnable (sh mc c) 115 | shift' (CapsetCreate cs cst) = CapsetCreate (sh mcs cs) cst 116 | shift' (CapsetDelete cs) = CapsetDelete (sh mcs cs) 117 | shift' (CapsetAssignCap cs c) = CapsetAssignCap (sh mcs cs) (sh mc c) 118 | shift' (CapsetRemoveCap cs c) = CapsetRemoveCap (sh mcs cs) (sh mc c) 119 | shift' (RtsIdentifier cs rts) = RtsIdentifier (sh mcs cs) rts 120 | shift' (ProgramArgs cs as) = ProgramArgs (sh mcs cs) as 121 | shift' (ProgramEnv cs es) = ProgramEnv (sh mcs cs) es 122 | shift' (OsProcessPid cs pid) = OsProcessPid (sh mcs cs) pid 123 | shift' (OsProcessParentPid cs ppid) = OsProcessParentPid (sh mcs cs) ppid 124 | shift' (WallClockTime cs sec nsec) = WallClockTime (sh mcs cs) sec nsec 125 | shift' x = x 126 | -- TODO extend by new shift for Eden events 127 | -------------------------------------------------------------------------------- /test/Roundtrip.hs: -------------------------------------------------------------------------------- 1 | import Control.Monad 2 | import System.Exit 3 | 4 | import GHC.RTS.Events 5 | import GHC.RTS.Events.Incremental 6 | import Utils (files) 7 | 8 | -- | Check that an event log round-trips through encoding/decoding. 9 | checkRoundtrip :: FilePath -> IO Bool 10 | checkRoundtrip logFile = do 11 | putStrLn logFile 12 | Right eventlog <- readEventLogFromFile logFile 13 | let Right (roundtripped, _) = readEventLog $ serialiseEventLog eventlog 14 | if show roundtripped == show eventlog 15 | then return True 16 | else putStrLn "bad" >> return False 17 | 18 | main :: IO () 19 | main = do 20 | successes <- mapM checkRoundtrip files 21 | unless (and successes) exitFailure 22 | -------------------------------------------------------------------------------- /test/TestVersions.hs: -------------------------------------------------------------------------------- 1 | {- 2 | This test parses sample event logs from each major GHC version and compares 3 | the pretty printed output with reference output. 4 | 5 | When tests fail, use a diff tool to compare the output of "ghc-events show" with 6 | the reference file. Resolve the differences in either the library code or the 7 | reference file, and 'darcs record' the changes. 8 | 9 | Steps to produce event log and reference output: 10 | $ ghc --make queens.hs -o queens-ghc-$VERSION -threaded -eventlog 11 | $ queens-ghc-$VERSION 8 +RTS -N4 -ls 12 | $ ghc-events show queens-ghc-$VERSION.eventlog > queens-ghc-$VERSION.eventlog.reference 13 | 14 | Where queens.hs is http://darcs.haskell.org/nofib/parallel/queens/Main.hs 15 | -} 16 | 17 | import System.Exit (exitFailure) 18 | 19 | import GHC.RTS.Events 20 | import Utils (files, diffLines) 21 | 22 | testFile :: FilePath -> IO Bool 23 | testFile f = do 24 | e <- readEventLogFromFile f 25 | let oops s = putStrLn (f ++ ": failure " ++ s) >> return False 26 | case e of 27 | Left m -> oops m 28 | Right newlogdata -> do 29 | oldlog <- readFile (f ++ ".reference") 30 | let newlog = ppEventLog RawTime newlogdata ++ "\n" in 31 | if oldlog == newlog 32 | then putStrLn (f ++ ": success") >> return True 33 | else do putStrLn $ diffLines oldlog newlog 34 | oops "pretty print output does not match" 35 | 36 | main :: IO () 37 | main = do 38 | successes <- mapM testFile files 39 | if and successes 40 | then return () 41 | else exitFailure 42 | -------------------------------------------------------------------------------- /test/Utils.hs: -------------------------------------------------------------------------------- 1 | module Utils where 2 | 3 | files :: [FilePath] 4 | files = map ("test/"++) 5 | [ "nonmoving-gc.eventlog" 6 | , "nonmoving-gc-census.eventlog" 7 | , "nonmoving-gc-census-T23340.eventlog" 8 | , "nonmoving-gc-pruned-segments.eventlog" 9 | , "parallelTest.eventlog" 10 | , "sleep.h.eventlog" 11 | , "sleep.hC.eventlog" 12 | , "sleep.hm.eventlog" 13 | , "sleep.hd.eventlog" 14 | , "sleep.hy.eventlog" 15 | , "stop.hT.eventlog" 16 | , "hello-ghc-8.2.2.eventlog", "hello-ghc-8.6.5.eventlog" 17 | , "biographical-samples.eventlog" 18 | , "time-prof.eventlog" 19 | , "trace-binary-event.eventlog" 20 | , "trace-binary-nonutf.eventlog" 21 | , "unicode.eventlog" 22 | , "ticky-ticky.eventlog" 23 | , "ticky-begin-sample.eventlog" 24 | , "ticky-new.eventlog" 25 | , "ticky-json.eventlog" 26 | ] 27 | 28 | 29 | -- Code to help print the differences between a working test and a failing test. 30 | diffLines :: String -> String -> String 31 | diffLines o n = diff 1 (lines o) (lines n) 32 | 33 | diff :: Int -> [String] -> [String] -> String 34 | diff _ [] [] = "Logs match" 35 | diff l [] (n:ns) = "Extra lines in new log at line " ++ show l ++ ":\n" ++ 36 | (unlines (n:ns)) 37 | diff l (o:os) [] = "Missing lines in new log at line " ++ show l ++ ":\n" ++ 38 | (unlines (o:os)) 39 | diff l (o:os) (n:ns) = if (o == n) 40 | then diff (l+1) os ns 41 | else "Different output at line " ++ show l ++ ":\n" ++ 42 | "Original: " ++ o ++ "\n" ++ 43 | "New: " ++ n 44 | -------------------------------------------------------------------------------- /test/WriteMerge.hs: -------------------------------------------------------------------------------- 1 | {- 2 | This test checks the functionality of `ghc-events merge` and writeEventLogToFile 3 | -} 4 | import Control.Monad 5 | import qualified Data.ByteString.Lazy as BL 6 | import Data.List (( \\ )) 7 | import Data.Maybe (fromJust) 8 | import System.Exit (exitFailure) 9 | 10 | import GHC.RTS.Events 11 | import GHC.RTS.Events.Incremental (readEventLog) 12 | import Utils (files, diffLines) 13 | 14 | -- Failing test cases due to changes introduced some time in the past but 15 | -- went unnoticed. Needs fixing. TODO 16 | failingCases :: [FilePath] 17 | failingCases = map ("test/"++) 18 | [ "queens-ghc-6.12.1.eventlog" 19 | , "queens-ghc-7.0.2.eventlog" 20 | , "mandelbrot-mmc-2011-06-14.eventlog" 21 | , "782stop.eventlog"] 22 | 23 | rewriteLog :: EventLog -> EventLog 24 | rewriteLog oldLog = case readEventLog (serialiseEventLog oldLog) of 25 | Left reason -> error reason 26 | Right (newLog, _) -> newLog 27 | 28 | testFile :: FilePath -> IO Bool 29 | testFile f = do 30 | e <- readEventLogFromFile f 31 | let oops s = putStrLn (f ++ ": failure " ++ s) >> return False 32 | case e of 33 | Left m -> oops m 34 | Right log -> do 35 | let old = ppEventLog log 36 | let new = ppEventLog $ rewriteLog log 37 | if old == new 38 | then putStrLn (f ++ ": success") >> return True 39 | else do 40 | putStrLn $ diffLines old new 41 | oops "re-written file does not match the original" 42 | 43 | main :: IO () 44 | main = do 45 | successes <- mapM testFile files 46 | unless (and successes) exitFailure 47 | -------------------------------------------------------------------------------- /test/biographical-samples.eventlog: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haskell/ghc-events/23a4082569ca2006186931d8f35933bfce7bb67c/test/biographical-samples.eventlog -------------------------------------------------------------------------------- /test/biographical-samples.eventlog.reference: -------------------------------------------------------------------------------- 1 | Event Types: 2 | 0: Create thread (size 4) 3 | 1: Run thread (size 4) 4 | 2: Stop thread (size 10) 5 | 3: Thread runnable (size 4) 6 | 4: Migrate thread (size 6) 7 | 8: Wakeup thread (size 6) 8 | 9: Starting GC (size 0) 9 | 10: Finished GC (size 0) 10 | 11: Request sequential GC (size 0) 11 | 12: Request parallel GC (size 0) 12 | 15: Create spark thread (size 4) 13 | 16: Log message (size variable) 14 | 18: Block marker (size 14) 15 | 19: User message (size variable) 16 | 20: GC idle (size 0) 17 | 21: GC working (size 0) 18 | 22: GC done (size 0) 19 | 25: Create capability set (size 6) 20 | 26: Delete capability set (size 4) 21 | 27: Add capability to capability set (size 6) 22 | 28: Remove capability from capability set (size 6) 23 | 29: RTS name and version (size variable) 24 | 30: Program arguments (size variable) 25 | 31: Program environment variables (size variable) 26 | 32: Process ID (size 8) 27 | 33: Parent process ID (size 8) 28 | 34: Spark counters (size 56) 29 | 35: Spark create (size 0) 30 | 36: Spark dud (size 0) 31 | 37: Spark overflow (size 0) 32 | 38: Spark run (size 0) 33 | 39: Spark steal (size 2) 34 | 40: Spark fizzle (size 0) 35 | 41: Spark GC (size 0) 36 | 43: Wall clock time (size 16) 37 | 44: Thread label (size variable) 38 | 45: Create capability (size 2) 39 | 46: Delete capability (size 2) 40 | 47: Disable capability (size 2) 41 | 48: Enable capability (size 2) 42 | 49: Total heap mem ever allocated (size 12) 43 | 50: Current heap size (size 12) 44 | 51: Current heap live data (size 12) 45 | 52: Heap static parameters (size 38) 46 | 53: GC statistics (size 58) 47 | 54: Synchronise stop-the-world GC (size 0) 48 | 55: Task create (size 18) 49 | 56: Task migrate (size 12) 50 | 57: Task delete (size 8) 51 | 58: User marker (size variable) 52 | 59: Empty event for bug #9003 (size 0) 53 | 160: Start of heap profile (size variable) 54 | 161: Cost center definition (size variable) 55 | 162: Start of heap profile sample (size 8) 56 | 163: Heap profile cost-centre sample (size variable) 57 | 164: Heap profile string sample (size variable) 58 | 165: End of heap profile sample (size 8) 59 | 166: Start of heap profile (biographical) sample (size 16) 60 | 181: User binary message (size variable) 61 | 62 | Events: 63 | 169333: created capset 0 of type CapsetOsProcess 64 | 169544: created capset 1 of type CapsetClockDomain 65 | 170610: created cap 0 66 | 170796: assigned cap 0 to capset 0 67 | 170992: assigned cap 0 to capset 1 68 | 171937: capset 1: wall clock time 1567931398s 509066000ns (unix epoch) 69 | 173588: capset 0: pid 31969 70 | 174939: capset 0: parent pid 10639 71 | 177812: capset 0: RTS version "GHC-8.9.0.20190907 rts_p" 72 | 178578: capset 0: args: ["./Test","+RTS","-hb","-l-au"] 73 | 31392757: start heap profiling 0 at sampling period 100000000 broken down by biography 74 | 31394184: cost centre 119 IDLE in IDLE at 75 | 31395244: cost centre 118 PINNED in SYSTEM at 76 | 31407386: cost centre 117 DONT_CARE in MAIN at 77 | 31407903: cost centre 116 OVERHEAD_of in PROFILING at 78 | 31408542: cost centre 115 GC in GC at 79 | 31409070: cost centre 114 SYSTEM in SYSTEM at 80 | 31409545: cost centre 113 MAIN in MAIN at 81 | 31418864: cost centre 112 CAF in GHC.Types at CAF 82 | 31419667: cost centre 111 CAF in GHC.Tuple at CAF 83 | 31420469: cost centre 110 CAF in GHC.PrimopWrappers at CAF 84 | 31428485: cost centre 109 CAF in GHC.Classes at CAF 85 | 31428997: cost centre 108 CAF in GHC.CString at CAF 86 | 31429601: cost centre 107 CAF in GHC.Integer.Type at CAF 87 | 31430128: cost centre 106 CAF in GHC.Integer.Logarithms.Internals at CAF 88 | 31430691: cost centre 105 CAF in GHC.Integer.Logarithms at CAF 89 | 31431318: cost centre 104 CAF in GHC.Event.Array at CAF 90 | 31431622: cost centre 103 CAF in GHC.Event.Arr at CAF 91 | 31432097: cost centre 102 CAF in System.Posix.Types at CAF 92 | 31432661: cost centre 101 CAF in GHC.Event.Poll at CAF 93 | 31433140: cost centre 100 CAF in GHC.Event.PSQ at CAF 94 | 31433663: cost centre 99 CAF in GHC.Event.Manager at CAF 95 | 31434201: cost centre 98 CAF in GHC.Event.Internal at CAF 96 | 31434663: cost centre 97 CAF in GHC.Event.IntTable at CAF 97 | 31435133: cost centre 96 CAF in GHC.Event.EPoll at CAF 98 | 31435653: cost centre 95 CAF in GHC.Event.Control at CAF 99 | 31443721: cost centre 94 CAF in GHC.Storable at CAF 100 | 31444197: cost centre 93 CAF in GHC.IO.Unsafe at CAF 101 | 31444906: cost centre 92 CAF in GHC.IO.IOMode at CAF 102 | 31445411: cost centre 91 CAF in GHC.IO.Handle.Text at CAF 103 | 31445869: cost centre 90 CAF in GHC.IO.FD at CAF 104 | 31446390: cost centre 89 CAF in GHC.IO.Device at CAF 105 | 31446934: cost centre 88 CAF in GHC.IO.BufferedIO at CAF 106 | 31447494: cost centre 87 CAF in GHC.Float.RealFracMethods at CAF 107 | 31447802: cost centre 86 CAF in GHC.Float.ConversionUtils at CAF 108 | 31448323: cost centre 85 CAF in GHC.Float at CAF 109 | 31448843: cost centre 84 CAF in GHC.Fingerprint.Type at CAF 110 | 31449296: cost centre 83 CAF in GHC.Fingerprint at CAF 111 | 31449625: cost centre 82 CAF in GHC.Char at CAF 112 | 31450153: cost centre 81 CAF in Foreign.Storable at CAF 113 | 31450756: cost centre 80 CAF in Foreign.Marshal.Array at CAF 114 | 31451306: cost centre 79 CAF in Foreign.Marshal.Alloc at CAF 115 | 31451871: cost centre 78 CAF in Foreign.C.Types at CAF 116 | 31452378: cost centre 77 CAF in Foreign.C.String at CAF 117 | 31452937: cost centre 76 CAF in Foreign.C.Error at CAF 118 | 31453478: cost centre 75 CAF in Data.Type.Equality at CAF 119 | 31453871: cost centre 74 CAF in Data.Tuple at CAF 120 | 31454313: cost centre 73 CAF in Data.Proxy at CAF 121 | 31454744: cost centre 72 CAF in Data.Maybe at CAF 122 | 31455173: cost centre 71 CAF in Data.Dynamic at CAF 123 | 31455677: cost centre 70 CAF in Data.Bits at CAF 124 | 31456087: cost centre 69 CAF in Control.Monad.Fail at CAF 125 | 31463389: cost centre 68 CAF in GHC.Event.Unique at CAF 126 | 31463855: cost centre 67 CAF in GHC.Event.TimerManager at CAF 127 | 31464340: cost centre 66 CAF in GHC.Event.Thread at CAF 128 | 31465122: cost centre 65 CAF in Data.Typeable.Internal at CAF 129 | 31465744: cost centre 64 CAF in Data.Semigroup.Internal at CAF 130 | 31466240: cost centre 63 CAF in Data.OldList at CAF 131 | 31466732: cost centre 62 CAF in Data.Functor.Utils at CAF 132 | 31467208: cost centre 61 CAF in Text.Read.Lex at CAF 133 | 31467721: cost centre 60 CAF in Text.ParserCombinators.ReadPrec at CAF 134 | 31468212: cost centre 59 CAF in Text.ParserCombinators.ReadP at CAF 135 | 31468673: cost centre 58 CAF in System.Posix.Internals at CAF 136 | 31469160: cost centre 57 CAF in System.IO at CAF 137 | 31469684: cost centre 56 CAF in Numeric at CAF 138 | 31470694: cost centre 55 CAF in GHC.Word at CAF 139 | 31471264: cost centre 54 CAF in GHC.Weak at CAF 140 | 31471733: cost centre 53 CAF in GHC.Unicode at CAF 141 | 31472232: cost centre 52 CAF in GHC.TypeNats at CAF 142 | 31472794: cost centre 51 CAF in GHC.TypeLits at CAF 143 | 31473276: cost centre 50 CAF in GHC.TopHandler at CAF 144 | 31473659: cost centre 49 CAF in GHC.Stack.Types at CAF 145 | 31474048: cost centre 48 CAF in GHC.Stack.CCS at CAF 146 | 31474486: cost centre 47 CAF in GHC.Stable at CAF 147 | 31482298: cost centre 46 CAF in GHC.Show at CAF 148 | 31482887: cost centre 45 CAF in GHC.STRef at CAF 149 | 31483377: cost centre 44 CAF in GHC.ST at CAF 150 | 31490773: cost centre 43 CAF in GHC.Real at CAF 151 | 31491247: cost centre 42 CAF in GHC.Read at CAF 152 | 31491645: cost centre 41 CAF in GHC.Ptr at CAF 153 | 31492243: cost centre 40 CAF in GHC.Pack at CAF 154 | 31492760: cost centre 39 CAF in GHC.Num at CAF 155 | 31493257: cost centre 38 CAF in GHC.Natural at CAF 156 | 31493736: cost centre 37 CAF in GHC.MVar at CAF 157 | 31494342: cost centre 36 CAF in GHC.Maybe at CAF 158 | 31494857: cost centre 35 CAF in GHC.List at CAF 159 | 31495381: cost centre 34 CAF in GHC.Int at CAF 160 | 31496151: cost centre 33 CAF in GHC.IORef at CAF 161 | 31496720: cost centre 32 CAF in GHC.IO.Handle.Types at CAF 162 | 31497222: cost centre 31 CAF in GHC.IO.Handle.Internals at CAF 163 | 31497685: cost centre 30 CAF in GHC.IO.Handle.FD at CAF 164 | 31504927: cost centre 29 CAF in GHC.IO.Handle at CAF 165 | 31505610: cost centre 28 CAF in GHC.IO.Exception at CAF 166 | 31506077: cost centre 27 CAF in GHC.IO.Encoding.UTF8 at CAF 167 | 31506496: cost centre 26 CAF in GHC.IO.Encoding.UTF32 at CAF 168 | 31507003: cost centre 25 CAF in GHC.IO.Encoding.UTF16 at CAF 169 | 31507583: cost centre 24 CAF in GHC.IO.Encoding.Types at CAF 170 | 31508035: cost centre 23 CAF in GHC.IO.Encoding.Latin1 at CAF 171 | 31508493: cost centre 22 CAF in GHC.IO.Encoding.Iconv at CAF 172 | 31508910: cost centre 21 CAF in GHC.IO.Encoding.Failure at CAF 173 | 31509429: cost centre 20 CAF in GHC.IO.Encoding at CAF 174 | 31509888: cost centre 19 CAF in GHC.IO.Buffer at CAF 175 | 31510384: cost centre 18 CAF in GHC.IO at CAF 176 | 31516785: cost centre 17 CAF in GHC.Generics at CAF 177 | 31517461: cost centre 16 CAF in GHC.ForeignPtr at CAF 178 | 31517919: cost centre 15 CAF in GHC.Foreign at CAF 179 | 31518406: cost centre 14 CAF in GHC.Exception.Type at CAF 180 | 31518840: cost centre 13 CAF in GHC.Exception at CAF 181 | 31519595: cost centre 12 CAF in GHC.Err at CAF 182 | 31520090: cost centre 11 CAF in GHC.Enum at CAF 183 | 31520663: cost centre 10 CAF in GHC.Conc.Sync at CAF 184 | 31521144: cost centre 9 CAF in GHC.Conc.Signal at CAF 185 | 31521606: cost centre 8 CAF in GHC.Conc.IO at CAF 186 | 31522099: cost centre 7 CAF in GHC.Base at CAF 187 | 31522596: cost centre 6 CAF in GHC.Arr at CAF 188 | 31523134: cost centre 5 CAF in Data.Monoid at CAF 189 | 31523621: cost centre 4 CAF in Data.Foldable at CAF 190 | 31524050: cost centre 3 CAF in Data.Either at CAF 191 | 31524535: cost centre 2 CAF in Control.Exception.Base at CAF 192 | 31525043: cost centre 1 CAF in Main at CAF 193 | 4710848398: removed cap 0 from capset 0 194 | 4710848571: removed cap 0 from capset 1 195 | 4710848777: deleted cap 0 196 | 4710848928: deleted capset 0 197 | 4710848972: deleted capset 1 198 | 4710856797: start heap prof sample 7 at time 866544061 199 | 4710858622: heap prof sample 0, residency 65379400, label VOID 200 | 4710858814: heap prof sample 0, residency 163449936, label LAG 201 | 4710858905: heap prof sample 0, residency 120, label USE 202 | 4710858989: heap prof sample 0, residency 37656, label INHERENT_USE 203 | 4710859120: heap prof sample 0, residency 0, label DRAG 204 | 4710859224: end prof sample 7 205 | 4710871439: start heap prof sample 7 at time 1892144224 206 | 4710871873: heap prof sample 0, residency 132361288, label VOID 207 | 4710871941: heap prof sample 0, residency 330904656, label LAG 208 | 4710872002: heap prof sample 0, residency 120, label USE 209 | 4710872059: heap prof sample 0, residency 37656, label INHERENT_USE 210 | 4710872127: heap prof sample 0, residency 0, label DRAG 211 | 4710872202: end prof sample 7 212 | 4710873620: start heap prof sample 7 at time 2671749143 213 | 4710873913: heap prof sample 0, residency 194095536, label VOID 214 | 4710873959: heap prof sample 0, residency 314763008, label LAG 215 | 4710874007: heap prof sample 0, residency 144, label USE 216 | 4710874067: heap prof sample 0, residency 37656, label INHERENT_USE 217 | 4710874115: heap prof sample 0, residency 0, label DRAG 218 | 4710874161: end prof sample 7 219 | 4710875374: start heap prof sample 7 at time 3372819397 220 | 4710875663: heap prof sample 0, residency 260169216, label VOID 221 | 4710875711: heap prof sample 0, residency 149578808, label LAG 222 | 4710875761: heap prof sample 0, residency 144, label USE 223 | 4710875807: heap prof sample 0, residency 37656, label INHERENT_USE 224 | 4710875854: heap prof sample 0, residency 0, label DRAG 225 | 4710875900: end prof sample 7 226 | 4710877077: start heap prof sample 7 at time 4040839252 227 | 4710877399: heap prof sample 0, residency 308465712, label VOID 228 | 4710877444: heap prof sample 0, residency 1672, label LAG 229 | 4710877490: heap prof sample 0, residency 120, label USE 230 | 4710877536: heap prof sample 0, residency 37656, label INHERENT_USE 231 | 4710877580: heap prof sample 0, residency 0, label DRAG 232 | 4710877635: end prof sample 7 233 | 4710878860: start heap prof sample 7 at time 4512086494 234 | 4710879189: heap prof sample 0, residency 91410480, label VOID 235 | 4710879235: heap prof sample 0, residency 1672, label LAG 236 | 4710879280: heap prof sample 0, residency 120, label USE 237 | 4710879338: heap prof sample 0, residency 37656, label INHERENT_USE 238 | 4710879385: heap prof sample 0, residency 0, label DRAG 239 | 4710879429: end prof sample 7 240 | 241 | -------------------------------------------------------------------------------- /test/ghc-9.2-events.eventlog: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haskell/ghc-events/23a4082569ca2006186931d8f35933bfce7bb67c/test/ghc-9.2-events.eventlog -------------------------------------------------------------------------------- /test/hello-ghc-8.2.2.eventlog: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haskell/ghc-events/23a4082569ca2006186931d8f35933bfce7bb67c/test/hello-ghc-8.2.2.eventlog -------------------------------------------------------------------------------- /test/hello-ghc-8.2.2.eventlog.reference: -------------------------------------------------------------------------------- 1 | Event Types: 2 | 0: Create thread (size 4) 3 | 1: Run thread (size 4) 4 | 2: Stop thread (size 10) 5 | 3: Thread runnable (size 4) 6 | 4: Migrate thread (size 6) 7 | 8: Wakeup thread (size 6) 8 | 9: Starting GC (size 0) 9 | 10: Finished GC (size 0) 10 | 11: Request sequential GC (size 0) 11 | 12: Request parallel GC (size 0) 12 | 15: Create spark thread (size 4) 13 | 16: Log message (size variable) 14 | 18: Block marker (size 14) 15 | 19: User message (size variable) 16 | 20: GC idle (size 0) 17 | 21: GC working (size 0) 18 | 22: GC done (size 0) 19 | 25: Create capability set (size 6) 20 | 26: Delete capability set (size 4) 21 | 27: Add capability to capability set (size 6) 22 | 28: Remove capability from capability set (size 6) 23 | 29: RTS name and version (size variable) 24 | 30: Program arguments (size variable) 25 | 31: Program environment variables (size variable) 26 | 32: Process ID (size 8) 27 | 33: Parent process ID (size 8) 28 | 34: Spark counters (size 56) 29 | 35: Spark create (size 0) 30 | 36: Spark dud (size 0) 31 | 37: Spark overflow (size 0) 32 | 38: Spark run (size 0) 33 | 39: Spark steal (size 2) 34 | 40: Spark fizzle (size 0) 35 | 41: Spark GC (size 0) 36 | 43: Wall clock time (size 16) 37 | 44: Thread label (size variable) 38 | 45: Create capability (size 2) 39 | 46: Delete capability (size 2) 40 | 47: Disable capability (size 2) 41 | 48: Enable capability (size 2) 42 | 49: Total heap mem ever allocated (size 12) 43 | 50: Current heap size (size 12) 44 | 51: Current heap live data (size 12) 45 | 52: Heap static parameters (size 38) 46 | 53: GC statistics (size 50) 47 | 54: Synchronise stop-the-world GC (size 0) 48 | 55: Task create (size 18) 49 | 56: Task migrate (size 12) 50 | 57: Task delete (size 8) 51 | 58: User marker (size variable) 52 | 59: Empty event for bug #9003 (size 0) 53 | 160: Start of heap profile (size variable) 54 | 161: Cost center definition (size variable) 55 | 162: Start of heap profile sample (size 8) 56 | 163: Heap profile cost-centre sample (size variable) 57 | 164: Heap profile string sample (size variable) 58 | 59 | Events: 60 | 693200: created capset 0 of type CapsetOsProcess 61 | 693300: created capset 1 of type CapsetClockDomain 62 | 693800: created cap 0 63 | 693800: assigned cap 0 to capset 0 64 | 693900: assigned cap 0 to capset 1 65 | 702500: capset 1: wall clock time 1557798469s 605000000ns (unix epoch) 66 | 702700: capset 0: pid 21152 67 | 717500: capset 0: RTS version "GHC-8.2.2 rts_l" 68 | 717900: capset 0: args: ["hellofib.exe","+RTS","-l"] 69 | 782000: capset 0: env: ["=::=::\\","=D:=D:\\Open\\ThreadScope","=ExitCode=00000000","ALLUSERSPROFILE=C:\\ProgramData","ANDROID_AVD_HOME=D:\\Program\\AndroidSDK\\.android\\avd","ANDROID_HOME=D:\\Program\\AndroidSDK","ANDROID_SDK_HOME=D:\\Program\\AndroidSDK","APPDATA=C:\\Users\\sighi\\AppData\\Roaming","APR_ICONV_PATH=D:\\Program\\Subversion\\iconv","asl.log=Destination=file","BAZEL_VC=D:\\Program\\Microsoft Visual Studio\\VC\\","BAZEL_VS=D:\\Program\\Microsoft Visual Studio\\","CARGO_HOME=D:\\Program\\Rust\\.cargo","CFLAGS=-std=gnu11 -Wall -pedantic -D_CRT_SECURE_NO_WARNINGS -D_USE_MATH_DEFINES","CHERE_INVOKING=enabled_from_arguments","CL=/std:c++14 /utf-8 /W3 /Ot /D_CRT_SECURE_NO_WARNINGS","CLASSPATH=.;D:\\Program\\Java\\jdk1.8.0_152\\lib;D:\\Program\\Java\\jdk1.8.0_152\\jre\\lib;D:\\Program\\JRuby\\lib;D:\\Program\\JRuby\\lib\\jni\\x86_64-Windows;D:\\Program\\Java\\logstash-5.6.1\\logstash-core\\lib;D:\\Program\\Java\\elasticsearch-2.3.1\\lib;","CLCACHE_DIR=D:\\Program\\CLCache\\Cache","CommonProgramFiles=C:\\Program Files\\Common Files","CommonProgramFiles(x86)=C:\\Program Files (x86)\\Common Files","CommonProgramW6432=C:\\Program Files\\Common Files","COMPUTERNAME=HT-PC","ComSpec=C:\\WINDOWS\\system32\\cmd.exe","CONDA_BAT=D:\\Program\\Conda\\condabin\\conda.bat","CONDA_EXE=D:\\Program\\Conda\\Scripts\\conda.exe","CONDA_SHLVL=0","CPPFLAGS=-std=c++14 -Wall -pedantic -D_CRT_SECURE_NO_WARNINGS -D_USE_MATH_DEFINES","CUDA_PATH=C:\\Program Files\\NVIDIA GPU Computing Toolkit\\CUDA\\v10.1","CUDA_PATH_V10_1=C:\\Program Files\\NVIDIA GPU Computing Toolkit\\CUDA\\v10.1","CUDA_PATH_V8_0=C:\\Program Files\\NVIDIA GPU Computing Toolkit\\CUDA\\v8.0","CUDA_PATH_V9_0=C:\\Program Files\\NVIDIA GPU Computing Toolkit\\CUDA\\v9.0","DriverData=C:\\Windows\\System32\\Drivers\\DriverData","ELECTRON_MIRROR=https://npm.taobao.org/mirrors/electron/","FPS_BROWSER_APP_PROFILE_STRING=Internet Explorer","FPS_BROWSER_USER_PROFILE_STRING=Default","GOPATH=C:\\Users\\sighi\\go;","GOROOT=D:\\Program\\Go\\","GRADLE_HOME=D:\\Gradle","GRADLE_USER_HOME=D:\\Gradle\\.gradle","GUROBI_HOME=D:\\Program\\Gurobi\\win64","HADOOP_HOME=D:\\Program\\hadoop-2.8.3","HOMEDRIVE=C:","HOMEPATH=\\Users\\sighi","ICPP_COMPILER19=D:\\Program\\IntelSWTools\\compilers_and_libraries_2019.0.117\\windows\\","INTEL_DEV_REDIST=C:\\Program Files (x86)\\Common Files\\Intel\\Shared Libraries\\","INTEL_LICENSE_FILE=C:\\Program Files (x86)\\Common Files\\Intel\\Licenses","JAVA_HOME=D:\\Program\\Java\\jdk1.8.0_152","JDK_HOME=D:\\Program\\Java\\jdk1.8.0_152","JRE_HOME=D:\\Program\\Java\\jdk1.8.0_152\\jre","JUPYTER=D:\\Program\\Conda\\Scripts\\jupyter.exe","LOCALAPPDATA=C:\\Users\\sighi\\AppData\\Local","LOGONSERVER=\\\\HT-PC","M2_HOME=D:\\Maven","MACHINE_STORAGE_PATH=D:\\Machines\\MobyLinuxVM","MAVEN_HOME=D:\\Maven","MKLProductDir=D:\\Stack\\program\\x86_64-windows\\msys2-20161025\\MKL","MKL_NUM_THREADS=4","MOZ_PLUGIN_PATH=D:\\Program\\Foxit Reader\\plugins\\","msbuildemitsolution=1","MSMPI_BENCHMARKS=D:\\Program\\MS-MPI\\Benchmarks\\","MSMPI_BIN=D:\\Program\\MS-MPI\\Bin\\","MSMPI_INC=D:\\Program\\MS-MPI\\Include\\","MSMPI_LIB32=D:\\Program\\MS-MPI\\Lib\\x86\\","MSMPI_LIB64=D:\\Program\\MS-MPI\\Lib\\x64\\","MSYS2_PATH_TYPE=inherit","MVN_HOME=D:\\Maven","NUMBA_CPU_FEATURES=+sse4.2","NUMBA_CPU_NAME=skylake","NUMBER_OF_PROCESSORS=8","NVCUDASAMPLES10_1_ROOT=C:\\ProgramData\\NVIDIA Corporation\\CUDA Samples\\v10.1","NVCUDASAMPLES8_0_ROOT=C:\\ProgramData\\NVIDIA Corporation\\CUDA Samples\\v8.0","NVCUDASAMPLES9_0_ROOT=C:\\ProgramData\\NVIDIA Corporation\\CUDA Samples\\v9.0","NVCUDASAMPLES_ROOT=C:\\ProgramData\\NVIDIA Corporation\\CUDA Samples\\v10.1","NVMW_IOJS_ORG_MIRROR=http://npm.taobao.org/mirrors/iojs","NVMW_NODEJS_ORG_MIRROR=http://npm.taobao.org/mirrors/node","NVMW_NPM_MIRROR=http://npm.taobao.org/mirrors/npm","NVM_HOME=D:\\Program\\Node","NVM_IOJS_ORG_MIRROR=http://npm.taobao.org/mirrors/iojs","NVM_NODEJS_ORG_MIRROR=http://npm.taobao.org/mirrors/node","NVM_SYMLINK=D:\\Program\\Node\\nodejs","NVTOOLSEXT_PATH=C:\\Program Files\\NVIDIA Corporation\\NvToolsExt\\","OneDrive=C:\\Users\\sighi\\OneDrive","OneDriveConsumer=C:\\Users\\sighi\\OneDrive","OS=Windows_NT","Path=D:\\Program\\Conda\\condabin;D:\\Program\\MS-MPI\\Bin\\;C:\\Program Files (x86)\\Common Files\\Intel\\Shared Libraries\\redist\\intel64_win\\mpirt;C:\\Program Files (x86)\\Common Files\\Intel\\Shared Libraries\\redist\\intel64_win\\compiler;C:\\Windows;C:\\Windows\\system32;C:\\Windows\\System32\\Wbem;C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\;D:\\Program\\VulkanSDK\\Bin;D:\\Program\\Java;D:\\Program\\Java\\jdk1.8.0_152\\bin;D:\\Sbt\\bin;D:\\Maven\\bin;D:\\Gradle\\bin;D:\\Program\\Conda;D:\\Program\\Conda\\Scripts;D:\\Program\\Conda\\Library\\bin;D:\\Program\\Graphviz\\bin;D:\\Program\\You-Get\\bin;C:\\Program Files\\NVIDIA Corporation\\NVSMI;C:\\Program Files\\NVIDIA GPU Computing Toolkit\\CUDA\\v10.1\\bin;C:\\Program Files\\NVIDIA GPU Computing Toolkit\\CUDA\\v10.1\\libnvvp;C:\\Program Files\\NVIDIA GPU Computing Toolkit\\CUDA\\v10.1\\nvvm\\bin;D:\\Program\\TeXLive\\bin\\win32;D:\\Program\\TeXLive\\tlpkg\\tlgs\\bin;D:\\Program\\hadoop-2.8.3\\bin;D:\\Program\\spark-2.2.0-bin-hadoop2.7\\bin;D:\\Program\\Flink\\bin;D:\\Program\\CMake\\bin;D:\\Stack\\program;D:\\Stack\\program\\idris;D:\\Program\\Subversion\\bin;D:\\Program\\Microsoft Visual Studio\\VC\\Auxiliary\\Build;C:\\Program Files (x86)\\Windows Kits\\10\\Microsoft Application Virtualization\\Sequencer\\;C:\\Program Files (x86)\\GtkSharp\\2.12\\bin;D:\\Program\\Doxygen;D:\\Program\\MATLAB\\runtime\\win64;D:\\Program\\MATLAB\\bin;D:\\Stack\\program\\x86_64-windows\\msys2-20161025\\MKL\\Library\\bin;D:\\Program\\CLCache;D:\\Program\\Php;C:\\WINDOWS\\System32\\OpenSSH\\;D:\\Stack\\program\\x86_64-windows\\msys2-20161025\\usr\\bin;D:\\Stack\\program\\x86_64-windows\\msys2-20161025\\mingw64\\bin;C:\\Program Files (x86)\\Windows Kits\\10\\Windows Performance Toolkit\\;D:\\Program\\Go\\bin;C:\\Users\\sighi\\.mujoco\\mjpro150\\bin;D:\\Program\\Gurobi\\win64\\bin;D:\\Program\\Git\\cmd;C:\\Program Files\\dotnet\\;D:\\Program\\MongoDB-4.1.6\\bin;D:\\Program\\Erlang\\bin;D:\\Program\\Node;D:\\Program\\Node\\nodejs;D:\\Program\\Mercurial\\;D:\\Program\\Microsoft VS Code\\bin;C:\\Program Files\\NVIDIA Corporation\\Nsight Compute 2019.1\\;C:\\Program Files (x86)\\NVIDIA Corporation\\PhysX\\Common;C:\\Program Files\\NVIDIA Corporation\\NVIDIA NvDLISR;D:\\Program\\Rust\\.cargo\\bin;D:\\Program\\JRuby\\bin;C:\\Users\\sighi\\AppData\\Local\\Microsoft\\WindowsApps;D:\\Open\\ghc\\inplace\\bin;C:\\Program Files\\Docker\\Docker\\Resources\\bin;D:\\Program\\Foundationdb\\bin;D:\\Program\\Java\\kafka_2.12-1.0.0\\bin\\windows;D:\\Stack\\program\\x86_64-windows\\ghc-8.4.3\\bin;D:\\Stack\\program\\x86_64-windows\\msys2-20161025;D:\\Local\\go\\bin;\"D;\\Program\\Julia\\bin\";D:\\Program\\MS-MPI\\Bin;","PATHEXT=.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC;.RB;.RBW","PROCESSOR_ARCHITECTURE=AMD64","PROCESSOR_IDENTIFIER=Intel64 Family 6 Model 94 Stepping 3, GenuineIntel","PROCESSOR_LEVEL=6","PROCESSOR_REVISION=5e03","ProgramData=C:\\ProgramData","ProgramFiles=C:\\Program Files","ProgramFiles(x86)=C:\\Program Files (x86)","ProgramW6432=C:\\Program Files","PROMPT=$P$G","PSModulePath=C:\\Program Files\\WindowsPowerShell\\Modules;C:\\WINDOWS\\system32\\WindowsPowerShell\\v1.0\\Modules;C:\\Program Files (x86)\\Windows Kits\\10\\Microsoft Application Virtualization\\Sequencer\\AppvPkgConverter;C:\\Program Files (x86)\\Windows Kits\\10\\Microsoft Application Virtualization\\Sequencer\\AppvSequencer;C:\\Program Files\\Intel\\Wired Networking\\","PUBLIC=C:\\Users\\Public","PYTHON_MIRROR=http://npm.taobao.org/mirrors/python","RUBYOPT=-Eutf-8","RUSTC_WRAPPER=sccache","RUSTUP_DIST_ROOT=https://mirrors.ustc.edu.cn/rust-static","RUSTUP_DIST_SERVER=https://mirrors.ustc.edu.cn/rust-static","RUSTUP_HOME=D:\\Program\\Rust\\.multirust","RUSTUP_UPDATE_ROOT=https://mirrors.ustc.edu.cn/rust-static/rustup","RUST_BACKTRACE=1","SASS_BINARY_SITE=http://npm.taobao.org/mirrors/node-sass","SBT_HOME=D:\\Sbt","SBT_OPTS=-Dsbt.override.build.repos=true","SCCACHE_DIR=D:\\Local\\sccache","SESSIONNAME=Console","SPARK_HOME=D:\\Program\\spark-2.2.0-bin-hadoop2.7","STACK_ROOT=D:\\Stack","SystemDrive=C:","SystemRoot=C:\\WINDOWS","TEMP=D:\\Local\\Temp","TMP=D:\\Local\\Temp","TMPDIR=C:\\Users\\Public\\Documents\\Wondershare\\CreatorTemp","USERDOMAIN=HT-PC","USERDOMAIN_ROAMINGPROFILE=HT-PC","USERNAME=sighi","USERPROFILE=C:\\Users\\sighi","VCINSTALLDIR=D:\\Program\\Microsoft Visual Studio\\","VCPKG_DEFAULT_TRIPLET=x64-windows","VK_SDK_PATH=D:\\Program\\VulkanSDK","VS2017INSTALLDIR=D:\\Program\\Microsoft Visual Studio","VSCMD_ARG_app_plat=Desktop","VSCMD_ARG_HOST_ARCH=x64","VSCMD_ARG_TGT_ARCH=x64","VSCMD_START_DIR=.","VSCMD_VER=15.4.2","VULKAN_SDK=D:\\Program\\VulkanSDK","windir=C:\\WINDOWS","WindowsLibPath=C:\\Program Files (x86)\\Windows Kits\\10\\UnionMetadata\\10.0.16299.0;C:\\Program Files (x86)\\Windows Kits\\10\\References\\10.0.16299.0"] 70 | 909500: heap stats for heap capset 0: generations 2, 0 bytes max heap size, 1048576 bytes alloc area size, 1048576 bytes mblock size, 4096 bytes block size 71 | 1139300: task 0x163dce0 created on cap 0 with OS kernel thread 19148 72 | 1152400: cap 0: creating thread 1 73 | 1157500: cap 0: running thread 1 74 | 1489500: cap 0: stopping thread 1 (stack overflow) 75 | 1493200: cap 0: running thread 1 76 | 1546100: cap 0: stopping thread 1 (blocked on I/O write) 77 | 1773200: cap 0: running thread 1 78 | 1791900: cap 0: stopping thread 1 (thread finished) 79 | 1792300: task 0x163dce0 deleted 80 | 1808400: task 0x163dce0 created on cap 0 with OS kernel thread 19148 81 | 1808600: cap 0: creating thread 2 82 | 1808900: cap 0: running thread 2 83 | 1818800: cap 0: stopping thread 2 (thread finished) 84 | 1818900: task 0x163dce0 deleted 85 | 1820000: cap 0: starting GC 86 | 1857600: cap 0: GC working 87 | 2101400: cap 0: GC idle 88 | 2101400: cap 0: GC done 89 | 2102400: cap 0: GC idle 90 | 2102400: cap 0: GC done 91 | 2102700: cap 0: GC idle 92 | 2102700: cap 0: GC done 93 | 2104000: cap 0: allocated on heap capset 0: 82048 total bytes till now 94 | 2105300: cap 0: all caps stopped for GC 95 | 2105300: cap 0: finished GC 96 | 2105400: cap 0: GC stats for heap capset 0: generation 1, 1784 bytes copied, 26744 bytes slop, 937984 bytes fragmentation, 1 par threads, 0 bytes max par copied, 1784 bytes total par copied 97 | 2105500: cap 0: live data in heap capset 0: 42888 bytes 98 | 2105600: cap 0: size of heap capset 0: 2097152 bytes 99 | 2116200: cap 0: allocated on heap capset 0: 82048 total bytes till now 100 | 2121200: removed cap 0 from capset 0 101 | 2121300: removed cap 0 from capset 1 102 | 2121400: deleted cap 0 103 | 2121500: deleted capset 0 104 | 2121600: deleted capset 1 105 | 106 | -------------------------------------------------------------------------------- /test/hello-ghc-8.6.5.eventlog: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haskell/ghc-events/23a4082569ca2006186931d8f35933bfce7bb67c/test/hello-ghc-8.6.5.eventlog -------------------------------------------------------------------------------- /test/hello-ghc-8.6.5.eventlog.reference: -------------------------------------------------------------------------------- 1 | Event Types: 2 | 0: Create thread (size 4) 3 | 1: Run thread (size 4) 4 | 2: Stop thread (size 10) 5 | 3: Thread runnable (size 4) 6 | 4: Migrate thread (size 6) 7 | 8: Wakeup thread (size 6) 8 | 9: Starting GC (size 0) 9 | 10: Finished GC (size 0) 10 | 11: Request sequential GC (size 0) 11 | 12: Request parallel GC (size 0) 12 | 15: Create spark thread (size 4) 13 | 16: Log message (size variable) 14 | 18: Block marker (size 14) 15 | 19: User message (size variable) 16 | 20: GC idle (size 0) 17 | 21: GC working (size 0) 18 | 22: GC done (size 0) 19 | 25: Create capability set (size 6) 20 | 26: Delete capability set (size 4) 21 | 27: Add capability to capability set (size 6) 22 | 28: Remove capability from capability set (size 6) 23 | 29: RTS name and version (size variable) 24 | 30: Program arguments (size variable) 25 | 31: Program environment variables (size variable) 26 | 32: Process ID (size 8) 27 | 33: Parent process ID (size 8) 28 | 34: Spark counters (size 56) 29 | 35: Spark create (size 0) 30 | 36: Spark dud (size 0) 31 | 37: Spark overflow (size 0) 32 | 38: Spark run (size 0) 33 | 39: Spark steal (size 2) 34 | 40: Spark fizzle (size 0) 35 | 41: Spark GC (size 0) 36 | 43: Wall clock time (size 16) 37 | 44: Thread label (size variable) 38 | 45: Create capability (size 2) 39 | 46: Delete capability (size 2) 40 | 47: Disable capability (size 2) 41 | 48: Enable capability (size 2) 42 | 49: Total heap mem ever allocated (size 12) 43 | 50: Current heap size (size 12) 44 | 51: Current heap live data (size 12) 45 | 52: Heap static parameters (size 38) 46 | 53: GC statistics (size 58) 47 | 54: Synchronise stop-the-world GC (size 0) 48 | 55: Task create (size 18) 49 | 56: Task migrate (size 12) 50 | 57: Task delete (size 8) 51 | 58: User marker (size variable) 52 | 59: Empty event for bug #9003 (size 0) 53 | 160: Start of heap profile (size variable) 54 | 161: Cost center definition (size variable) 55 | 162: Start of heap profile sample (size 8) 56 | 163: Heap profile cost-centre sample (size variable) 57 | 164: Heap profile string sample (size variable) 58 | 59 | Events: 60 | 595100: created capset 0 of type CapsetOsProcess 61 | 595200: created capset 1 of type CapsetClockDomain 62 | 596200: created cap 0 63 | 596200: assigned cap 0 to capset 0 64 | 596300: assigned cap 0 to capset 1 65 | 598100: capset 1: wall clock time 1557798534s 953000000ns (unix epoch) 66 | 598200: capset 0: pid 15908 67 | 599000: capset 0: RTS version "GHC-8.6.5 rts_l" 68 | 599300: capset 0: args: ["hellofib.exe","+RTS","-l"] 69 | 636500: capset 0: env: ["=::=::\\","=D:=D:\\Open\\ThreadScope","=ExitCode=00000000","ALLUSERSPROFILE=C:\\ProgramData","ANDROID_AVD_HOME=D:\\Program\\AndroidSDK\\.android\\avd","ANDROID_HOME=D:\\Program\\AndroidSDK","ANDROID_SDK_HOME=D:\\Program\\AndroidSDK","APPDATA=C:\\Users\\sighi\\AppData\\Roaming","APR_ICONV_PATH=D:\\Program\\Subversion\\iconv","asl.log=Destination=file","BAZEL_VC=D:\\Program\\Microsoft Visual Studio\\VC\\","BAZEL_VS=D:\\Program\\Microsoft Visual Studio\\","CARGO_HOME=D:\\Program\\Rust\\.cargo","CFLAGS=-std=gnu11 -Wall -pedantic -D_CRT_SECURE_NO_WARNINGS -D_USE_MATH_DEFINES","CHERE_INVOKING=enabled_from_arguments","CL=/std:c++14 /utf-8 /W3 /Ot /D_CRT_SECURE_NO_WARNINGS","CLASSPATH=.;D:\\Program\\Java\\jdk1.8.0_152\\lib;D:\\Program\\Java\\jdk1.8.0_152\\jre\\lib;D:\\Program\\JRuby\\lib;D:\\Program\\JRuby\\lib\\jni\\x86_64-Windows;D:\\Program\\Java\\logstash-5.6.1\\logstash-core\\lib;D:\\Program\\Java\\elasticsearch-2.3.1\\lib;","CLCACHE_DIR=D:\\Program\\CLCache\\Cache","CommonProgramFiles=C:\\Program Files\\Common Files","CommonProgramFiles(x86)=C:\\Program Files (x86)\\Common Files","CommonProgramW6432=C:\\Program Files\\Common Files","COMPUTERNAME=HT-PC","ComSpec=C:\\WINDOWS\\system32\\cmd.exe","CONDA_BAT=D:\\Program\\Conda\\condabin\\conda.bat","CONDA_EXE=D:\\Program\\Conda\\Scripts\\conda.exe","CONDA_SHLVL=0","CPPFLAGS=-std=c++14 -Wall -pedantic -D_CRT_SECURE_NO_WARNINGS -D_USE_MATH_DEFINES","CUDA_PATH=C:\\Program Files\\NVIDIA GPU Computing Toolkit\\CUDA\\v10.1","CUDA_PATH_V10_1=C:\\Program Files\\NVIDIA GPU Computing Toolkit\\CUDA\\v10.1","CUDA_PATH_V8_0=C:\\Program Files\\NVIDIA GPU Computing Toolkit\\CUDA\\v8.0","CUDA_PATH_V9_0=C:\\Program Files\\NVIDIA GPU Computing Toolkit\\CUDA\\v9.0","DriverData=C:\\Windows\\System32\\Drivers\\DriverData","ELECTRON_MIRROR=https://npm.taobao.org/mirrors/electron/","FPS_BROWSER_APP_PROFILE_STRING=Internet Explorer","FPS_BROWSER_USER_PROFILE_STRING=Default","GOPATH=C:\\Users\\sighi\\go;","GOROOT=D:\\Program\\Go\\","GRADLE_HOME=D:\\Gradle","GRADLE_USER_HOME=D:\\Gradle\\.gradle","GUROBI_HOME=D:\\Program\\Gurobi\\win64","HADOOP_HOME=D:\\Program\\hadoop-2.8.3","HOMEDRIVE=C:","HOMEPATH=\\Users\\sighi","ICPP_COMPILER19=D:\\Program\\IntelSWTools\\compilers_and_libraries_2019.0.117\\windows\\","INTEL_DEV_REDIST=C:\\Program Files (x86)\\Common Files\\Intel\\Shared Libraries\\","INTEL_LICENSE_FILE=C:\\Program Files (x86)\\Common Files\\Intel\\Licenses","JAVA_HOME=D:\\Program\\Java\\jdk1.8.0_152","JDK_HOME=D:\\Program\\Java\\jdk1.8.0_152","JRE_HOME=D:\\Program\\Java\\jdk1.8.0_152\\jre","JUPYTER=D:\\Program\\Conda\\Scripts\\jupyter.exe","LOCALAPPDATA=C:\\Users\\sighi\\AppData\\Local","LOGONSERVER=\\\\HT-PC","M2_HOME=D:\\Maven","MACHINE_STORAGE_PATH=D:\\Machines\\MobyLinuxVM","MAVEN_HOME=D:\\Maven","MKLProductDir=D:\\Stack\\program\\x86_64-windows\\msys2-20161025\\MKL","MKL_NUM_THREADS=4","MOZ_PLUGIN_PATH=D:\\Program\\Foxit Reader\\plugins\\","msbuildemitsolution=1","MSMPI_BENCHMARKS=D:\\Program\\MS-MPI\\Benchmarks\\","MSMPI_BIN=D:\\Program\\MS-MPI\\Bin\\","MSMPI_INC=D:\\Program\\MS-MPI\\Include\\","MSMPI_LIB32=D:\\Program\\MS-MPI\\Lib\\x86\\","MSMPI_LIB64=D:\\Program\\MS-MPI\\Lib\\x64\\","MSYS2_PATH_TYPE=inherit","MVN_HOME=D:\\Maven","NUMBA_CPU_FEATURES=+sse4.2","NUMBA_CPU_NAME=skylake","NUMBER_OF_PROCESSORS=8","NVCUDASAMPLES10_1_ROOT=C:\\ProgramData\\NVIDIA Corporation\\CUDA Samples\\v10.1","NVCUDASAMPLES8_0_ROOT=C:\\ProgramData\\NVIDIA Corporation\\CUDA Samples\\v8.0","NVCUDASAMPLES9_0_ROOT=C:\\ProgramData\\NVIDIA Corporation\\CUDA Samples\\v9.0","NVCUDASAMPLES_ROOT=C:\\ProgramData\\NVIDIA Corporation\\CUDA Samples\\v10.1","NVMW_IOJS_ORG_MIRROR=http://npm.taobao.org/mirrors/iojs","NVMW_NODEJS_ORG_MIRROR=http://npm.taobao.org/mirrors/node","NVMW_NPM_MIRROR=http://npm.taobao.org/mirrors/npm","NVM_HOME=D:\\Program\\Node","NVM_IOJS_ORG_MIRROR=http://npm.taobao.org/mirrors/iojs","NVM_NODEJS_ORG_MIRROR=http://npm.taobao.org/mirrors/node","NVM_SYMLINK=D:\\Program\\Node\\nodejs","NVTOOLSEXT_PATH=C:\\Program Files\\NVIDIA Corporation\\NvToolsExt\\","OneDrive=C:\\Users\\sighi\\OneDrive","OneDriveConsumer=C:\\Users\\sighi\\OneDrive","OS=Windows_NT","Path=D:\\Program\\Conda\\condabin;D:\\Program\\MS-MPI\\Bin\\;C:\\Program Files (x86)\\Common Files\\Intel\\Shared Libraries\\redist\\intel64_win\\mpirt;C:\\Program Files (x86)\\Common Files\\Intel\\Shared Libraries\\redist\\intel64_win\\compiler;C:\\Windows;C:\\Windows\\system32;C:\\Windows\\System32\\Wbem;C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\;D:\\Program\\VulkanSDK\\Bin;D:\\Program\\Java;D:\\Program\\Java\\jdk1.8.0_152\\bin;D:\\Sbt\\bin;D:\\Maven\\bin;D:\\Gradle\\bin;D:\\Program\\Conda;D:\\Program\\Conda\\Scripts;D:\\Program\\Conda\\Library\\bin;D:\\Program\\Graphviz\\bin;D:\\Program\\You-Get\\bin;C:\\Program Files\\NVIDIA Corporation\\NVSMI;C:\\Program Files\\NVIDIA GPU Computing Toolkit\\CUDA\\v10.1\\bin;C:\\Program Files\\NVIDIA GPU Computing Toolkit\\CUDA\\v10.1\\libnvvp;C:\\Program Files\\NVIDIA GPU Computing Toolkit\\CUDA\\v10.1\\nvvm\\bin;D:\\Program\\TeXLive\\bin\\win32;D:\\Program\\TeXLive\\tlpkg\\tlgs\\bin;D:\\Program\\hadoop-2.8.3\\bin;D:\\Program\\spark-2.2.0-bin-hadoop2.7\\bin;D:\\Program\\Flink\\bin;D:\\Program\\CMake\\bin;D:\\Stack\\program;D:\\Stack\\program\\idris;D:\\Program\\Subversion\\bin;D:\\Program\\Microsoft Visual Studio\\VC\\Auxiliary\\Build;C:\\Program Files (x86)\\Windows Kits\\10\\Microsoft Application Virtualization\\Sequencer\\;C:\\Program Files (x86)\\GtkSharp\\2.12\\bin;D:\\Program\\Doxygen;D:\\Program\\MATLAB\\runtime\\win64;D:\\Program\\MATLAB\\bin;D:\\Stack\\program\\x86_64-windows\\msys2-20161025\\MKL\\Library\\bin;D:\\Program\\CLCache;D:\\Program\\Php;C:\\WINDOWS\\System32\\OpenSSH\\;D:\\Stack\\program\\x86_64-windows\\msys2-20161025\\usr\\bin;D:\\Stack\\program\\x86_64-windows\\msys2-20161025\\mingw64\\bin;C:\\Program Files (x86)\\Windows Kits\\10\\Windows Performance Toolkit\\;D:\\Program\\Go\\bin;C:\\Users\\sighi\\.mujoco\\mjpro150\\bin;D:\\Program\\Gurobi\\win64\\bin;D:\\Program\\Git\\cmd;C:\\Program Files\\dotnet\\;D:\\Program\\MongoDB-4.1.6\\bin;D:\\Program\\Erlang\\bin;D:\\Program\\Node;D:\\Program\\Node\\nodejs;D:\\Program\\Mercurial\\;D:\\Program\\Microsoft VS Code\\bin;C:\\Program Files\\NVIDIA Corporation\\Nsight Compute 2019.1\\;C:\\Program Files (x86)\\NVIDIA Corporation\\PhysX\\Common;C:\\Program Files\\NVIDIA Corporation\\NVIDIA NvDLISR;D:\\Program\\Rust\\.cargo\\bin;D:\\Program\\JRuby\\bin;C:\\Users\\sighi\\AppData\\Local\\Microsoft\\WindowsApps;D:\\Open\\ghc\\inplace\\bin;C:\\Program Files\\Docker\\Docker\\Resources\\bin;D:\\Program\\Foundationdb\\bin;D:\\Program\\Java\\kafka_2.12-1.0.0\\bin\\windows;D:\\Stack\\program\\x86_64-windows\\ghc-8.4.3\\bin;D:\\Stack\\program\\x86_64-windows\\msys2-20161025;D:\\Local\\go\\bin;\"D;\\Program\\Julia\\bin\";D:\\Program\\MS-MPI\\Bin;","PATHEXT=.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC;.RB;.RBW","PROCESSOR_ARCHITECTURE=AMD64","PROCESSOR_IDENTIFIER=Intel64 Family 6 Model 94 Stepping 3, GenuineIntel","PROCESSOR_LEVEL=6","PROCESSOR_REVISION=5e03","ProgramData=C:\\ProgramData","ProgramFiles=C:\\Program Files","ProgramFiles(x86)=C:\\Program Files (x86)","ProgramW6432=C:\\Program Files","PROMPT=$P$G","PSModulePath=C:\\Program Files\\WindowsPowerShell\\Modules;C:\\WINDOWS\\system32\\WindowsPowerShell\\v1.0\\Modules;C:\\Program Files (x86)\\Windows Kits\\10\\Microsoft Application Virtualization\\Sequencer\\AppvPkgConverter;C:\\Program Files (x86)\\Windows Kits\\10\\Microsoft Application Virtualization\\Sequencer\\AppvSequencer;C:\\Program Files\\Intel\\Wired Networking\\","PUBLIC=C:\\Users\\Public","PYTHON_MIRROR=http://npm.taobao.org/mirrors/python","RUBYOPT=-Eutf-8","RUSTC_WRAPPER=sccache","RUSTUP_DIST_ROOT=https://mirrors.ustc.edu.cn/rust-static","RUSTUP_DIST_SERVER=https://mirrors.ustc.edu.cn/rust-static","RUSTUP_HOME=D:\\Program\\Rust\\.multirust","RUSTUP_UPDATE_ROOT=https://mirrors.ustc.edu.cn/rust-static/rustup","RUST_BACKTRACE=1","SASS_BINARY_SITE=http://npm.taobao.org/mirrors/node-sass","SBT_HOME=D:\\Sbt","SBT_OPTS=-Dsbt.override.build.repos=true","SCCACHE_DIR=D:\\Local\\sccache","SESSIONNAME=Console","SPARK_HOME=D:\\Program\\spark-2.2.0-bin-hadoop2.7","STACK_ROOT=D:\\Stack","SystemDrive=C:","SystemRoot=C:\\WINDOWS","TEMP=D:\\Local\\Temp","TMP=D:\\Local\\Temp","TMPDIR=C:\\Users\\Public\\Documents\\Wondershare\\CreatorTemp","USERDOMAIN=HT-PC","USERDOMAIN_ROAMINGPROFILE=HT-PC","USERNAME=sighi","USERPROFILE=C:\\Users\\sighi","VCINSTALLDIR=D:\\Program\\Microsoft Visual Studio\\","VCPKG_DEFAULT_TRIPLET=x64-windows","VK_SDK_PATH=D:\\Program\\VulkanSDK","VS2017INSTALLDIR=D:\\Program\\Microsoft Visual Studio","VSCMD_ARG_app_plat=Desktop","VSCMD_ARG_HOST_ARCH=x64","VSCMD_ARG_TGT_ARCH=x64","VSCMD_START_DIR=.","VSCMD_VER=15.4.2","VULKAN_SDK=D:\\Program\\VulkanSDK","windir=C:\\WINDOWS","WindowsLibPath=C:\\Program Files (x86)\\Windows Kits\\10\\UnionMetadata\\10.0.16299.0;C:\\Program Files (x86)\\Windows Kits\\10\\References\\10.0.16299.0"] 70 | 820600: heap stats for heap capset 0: generations 2, 0 bytes max heap size, 1048576 bytes alloc area size, 1048576 bytes mblock size, 4096 bytes block size 71 | 1119300: task 0x10630a0 created on cap 0 with OS kernel thread 16112 72 | 1124800: cap 0: creating thread 1 73 | 1130000: cap 0: running thread 1 74 | 1660500: cap 0: stopping thread 1 (stack overflow) 75 | 1667600: cap 0: running thread 1 76 | 1718400: cap 0: stopping thread 1 (blocked on I/O write) 77 | 2132500: cap 0: running thread 1 78 | 2135600: cap 0: stopping thread 1 (thread finished) 79 | 2163600: task 0x10630a0 deleted 80 | 2172200: task 0x10630a0 created on cap 0 with OS kernel thread 16112 81 | 2172400: cap 0: creating thread 2 82 | 2172800: cap 0: running thread 2 83 | 2205900: cap 0: stopping thread 2 (thread finished) 84 | 2206100: task 0x10630a0 deleted 85 | 2211300: cap 0: starting GC 86 | 2211900: cap 0: GC working 87 | 2980100: cap 0: GC idle 88 | 2980100: cap 0: GC done 89 | 2988500: cap 0: GC idle 90 | 2988600: cap 0: GC done 91 | 2988800: cap 0: GC idle 92 | 2988800: cap 0: GC done 93 | 2993900: cap 0: allocated on heap capset 0: 83088 total bytes till now 94 | 2998500: cap 0: finished GC 95 | 2998600: cap 0: all caps stopped for GC 96 | 2998600: cap 0: GC stats for heap capset 0: generation 1, 3120 bytes copied, 25408 bytes slop, 937984 bytes fragmentation, 1 par threads, 0 bytes max par copied, 3120 bytes total par copied, 0 bytes balanced par copied 97 | 2999100: cap 0: live data in heap capset 0: 44224 bytes 98 | 2999200: cap 0: size of heap capset 0: 2097152 bytes 99 | 3010700: cap 0: allocated on heap capset 0: 83088 total bytes till now 100 | 3011600: removed cap 0 from capset 0 101 | 3011700: removed cap 0 from capset 1 102 | 3011800: deleted cap 0 103 | 3011900: deleted capset 0 104 | 3012000: deleted capset 1 105 | 106 | -------------------------------------------------------------------------------- /test/nonmoving-gc-census-T23340.eventlog: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haskell/ghc-events/23a4082569ca2006186931d8f35933bfce7bb67c/test/nonmoving-gc-census-T23340.eventlog -------------------------------------------------------------------------------- /test/nonmoving-gc-census-T23340.eventlog.reference: -------------------------------------------------------------------------------- 1 | Event Types: 2 | 0: Create thread (size 4) 3 | 1: Run thread (size 4) 4 | 2: Stop thread (size 10) 5 | 3: Thread runnable (size 4) 6 | 4: Migrate thread (size 6) 7 | 8: Wakeup thread (size 6) 8 | 9: Starting GC (size 0) 9 | 10: Finished GC (size 0) 10 | 11: Request sequential GC (size 0) 11 | 12: Request parallel GC (size 0) 12 | 15: Create spark thread (size 4) 13 | 16: Log message (size variable) 14 | 18: Block marker (size 14) 15 | 19: User message (size variable) 16 | 20: GC idle (size 0) 17 | 21: GC working (size 0) 18 | 22: GC done (size 0) 19 | 25: Create capability set (size 6) 20 | 26: Delete capability set (size 4) 21 | 27: Add capability to capability set (size 6) 22 | 28: Remove capability from capability set (size 6) 23 | 29: RTS name and version (size variable) 24 | 30: Program arguments (size variable) 25 | 31: Program environment variables (size variable) 26 | 32: Process ID (size 8) 27 | 33: Parent process ID (size 8) 28 | 34: Spark counters (size 56) 29 | 35: Spark create (size 0) 30 | 36: Spark dud (size 0) 31 | 37: Spark overflow (size 0) 32 | 38: Spark run (size 0) 33 | 39: Spark steal (size 2) 34 | 40: Spark fizzle (size 0) 35 | 41: Spark GC (size 0) 36 | 42: Intern string (size variable) 37 | 43: Wall clock time (size 16) 38 | 44: Thread label (size variable) 39 | 45: Create capability (size 2) 40 | 46: Delete capability (size 2) 41 | 47: Disable capability (size 2) 42 | 48: Enable capability (size 2) 43 | 49: Total heap memory ever allocated (size 12) 44 | 50: Current heap size (number of allocated mblocks) (size 12) 45 | 51: Current heap live data (size 12) 46 | 52: Heap static parameters (size 38) 47 | 53: GC statistics (size 58) 48 | 54: Synchronise stop-the-world GC (size 0) 49 | 55: Task create (size 18) 50 | 56: Task migrate (size 12) 51 | 57: Task delete (size 8) 52 | 58: User marker (size variable) 53 | 59: Empty event for bug #9003 (size 0) 54 | 90: The RTS attempted to return heap memory to the OS (size 16) 55 | 91: Report the size of the heap in blocks (size 12) 56 | 160: Start of heap profile (size variable) 57 | 161: Cost-centre definition (size variable) 58 | 162: Start of heap profile sample (size 8) 59 | 163: Heap profile cost-centre sample (size variable) 60 | 164: Heap profile string sample (size variable) 61 | 165: End of heap profile sample (size 8) 62 | 166: Start of heap profile (biographical) sample (size 16) 63 | 167: Time profile cost-centre stack (size variable) 64 | 168: Start of a time profile (size 8) 65 | 169: An IPE entry (size variable) 66 | 181: User binary message (size variable) 67 | 200: Begin concurrent mark phase (size 0) 68 | 201: End concurrent mark phase (size 4) 69 | 202: Begin concurrent GC synchronisation (size 0) 70 | 203: End concurrent mark synchronisation (size 0) 71 | 204: Begin concurrent sweep phase (size 0) 72 | 205: End concurrent sweep phase (size 0) 73 | 206: Update remembered set flushed (size 2) 74 | 207: Nonmoving heap census (size 14) 75 | 210: Ticky-ticky entry counter definition (size variable) 76 | 211: Ticky-ticky entry counter sample (size 32) 77 | 212: Ticky-ticky entry counter begin sample (size 0) 78 | 79 | Events: 80 | 219698: capset 1: wall clock time 1694431580s 894343000ns (unix epoch) 81 | 220498: capset 0: pid 2073360 82 | 221298: capset 0: parent pid 1906706 83 | 222298: capset 0: RTS version "GHC-9.9.20230901 rts_v" 84 | 222498: capset 0: args: ["nofib/shootout/binary-trees/Main","15","11","+RTS","-xn","-l-an"] 85 | 3158969: Starting nonmoving GC preparation 86 | 3161769: Marking roots for nonmoving GC 87 | 3162369: Finished marking roots for nonmoving GC 88 | 3162369: Finished nonmoving GC preparation 89 | 3165069: concurrent mark began 90 | 3483866: concurrent mark ended: marked 2789 objects 91 | 3484166: concurrent mark began 92 | 3484166: concurrent mark ended: marked 1 objects 93 | 3484266: concurrent mark began 94 | 3484266: concurrent mark ended: marked 1 objects 95 | 3490366: concurrent sweep began 96 | 3490566: concurrent sweep ended 97 | 3493366: nonmoving heap census 8: 0 active segments, 0 filled segments, 0 live blocks 98 | 3494866: nonmoving heap census 16: 0 active segments, 0 filled segments, 38 live blocks 99 | 3495766: nonmoving heap census 24: 0 active segments, 0 filled segments, 99 live blocks 100 | 3496466: nonmoving heap census 32: 0 active segments, 0 filled segments, 5 live blocks 101 | 3496966: nonmoving heap census 40: 0 active segments, 0 filled segments, 0 live blocks 102 | 3497466: nonmoving heap census 48: 0 active segments, 0 filled segments, 0 live blocks 103 | 3498166: nonmoving heap census 56: 0 active segments, 0 filled segments, 0 live blocks 104 | 3499866: nonmoving heap census 64: 0 active segments, 0 filled segments, 0 live blocks 105 | 3500366: nonmoving heap census 72: 0 active segments, 0 filled segments, 0 live blocks 106 | 3527666: nonmoving heap census 80: 0 active segments, 0 filled segments, 0 live blocks 107 | 3527866: nonmoving heap census 88: 0 active segments, 0 filled segments, 0 live blocks 108 | 3528366: nonmoving heap census 96: 0 active segments, 0 filled segments, 0 live blocks 109 | 3528766: nonmoving heap census 104: 0 active segments, 0 filled segments, 0 live blocks 110 | 3529066: nonmoving heap census 112: 0 active segments, 0 filled segments, 0 live blocks 111 | 3529366: nonmoving heap census 120: 0 active segments, 0 filled segments, 0 live blocks 112 | 3529566: nonmoving heap census 128: 0 active segments, 0 filled segments, 0 live blocks 113 | 3529866: nonmoving heap census 256: 0 active segments, 0 filled segments, 0 live blocks 114 | 3529966: nonmoving heap census 512: 0 active segments, 0 filled segments, 0 live blocks 115 | 3530066: nonmoving heap census 1024: 0 active segments, 0 filled segments, 0 live blocks 116 | 3530166: nonmoving heap census 2048: 0 active segments, 0 filled segments, 0 live blocks 117 | 3530266: nonmoving heap census 4096: 0 active segments, 0 filled segments, 0 live blocks 118 | 3530466: nonmoving heap census 8192: 0 active segments, 0 filled segments, 0 live blocks 119 | 3530566: nonmoving heap census 16384: 0 active segments, 0 filled segments, 0 live blocks 120 | 30946697: Starting nonmoving GC preparation 121 | 30949497: Marking roots for nonmoving GC 122 | 30949997: Finished marking roots for nonmoving GC 123 | 30950097: Finished nonmoving GC preparation 124 | 30957296: concurrent mark began 125 | 31188794: concurrent mark ended: marked 10999 objects 126 | 31188894: concurrent mark began 127 | 31189694: concurrent mark ended: marked 12 objects 128 | 31189794: concurrent mark began 129 | 31189794: concurrent mark ended: marked 1 objects 130 | 31189794: concurrent mark began 131 | 31189894: concurrent mark ended: marked 1 objects 132 | 31190794: concurrent sweep began 133 | 31230594: concurrent sweep ended 134 | 31232294: nonmoving heap census 8: 0 active segments, 0 filled segments, 0 live blocks 135 | 31233394: nonmoving heap census 16: 0 active segments, 0 filled segments, 54 live blocks 136 | 31234094: nonmoving heap census 24: 0 active segments, 0 filled segments, 120 live blocks 137 | 31236194: nonmoving heap census 32: 2 active segments, 4 filled segments, 4100 live blocks 138 | 31236594: nonmoving heap census 40: 0 active segments, 0 filled segments, 1 live blocks 139 | 31236994: nonmoving heap census 48: 0 active segments, 0 filled segments, 3 live blocks 140 | 31237294: nonmoving heap census 56: 0 active segments, 0 filled segments, 0 live blocks 141 | 31237594: nonmoving heap census 64: 0 active segments, 0 filled segments, 2 live blocks 142 | 31237894: nonmoving heap census 72: 0 active segments, 0 filled segments, 0 live blocks 143 | 31238094: nonmoving heap census 80: 0 active segments, 0 filled segments, 0 live blocks 144 | 31238394: nonmoving heap census 88: 0 active segments, 0 filled segments, 0 live blocks 145 | 31238694: nonmoving heap census 96: 0 active segments, 0 filled segments, 0 live blocks 146 | 31238894: nonmoving heap census 104: 0 active segments, 0 filled segments, 0 live blocks 147 | 31239094: nonmoving heap census 112: 0 active segments, 0 filled segments, 0 live blocks 148 | 31239394: nonmoving heap census 120: 0 active segments, 0 filled segments, 0 live blocks 149 | 31239594: nonmoving heap census 128: 0 active segments, 0 filled segments, 1 live blocks 150 | 31239694: nonmoving heap census 256: 0 active segments, 0 filled segments, 1 live blocks 151 | 31239794: nonmoving heap census 512: 0 active segments, 0 filled segments, 0 live blocks 152 | 31239894: nonmoving heap census 1024: 0 active segments, 0 filled segments, 1 live blocks 153 | 31239994: nonmoving heap census 2048: 0 active segments, 0 filled segments, 0 live blocks 154 | 31240094: nonmoving heap census 4096: 0 active segments, 0 filled segments, 0 live blocks 155 | 31240294: nonmoving heap census 8192: 0 active segments, 0 filled segments, 0 live blocks 156 | 31240294: nonmoving heap census 16384: 0 active segments, 0 filled segments, 0 live blocks 157 | 58695524: Starting nonmoving GC preparation 158 | 58698024: Marking roots for nonmoving GC 159 | 58698924: Finished marking roots for nonmoving GC 160 | 58699024: Finished nonmoving GC preparation 161 | 58708324: concurrent mark began 162 | 58950222: concurrent mark ended: marked 10996 objects 163 | 58950422: concurrent mark began 164 | 58951222: concurrent mark ended: marked 12 objects 165 | 58951222: concurrent mark began 166 | 58951322: concurrent mark ended: marked 1 objects 167 | 58951322: concurrent mark began 168 | 58951322: concurrent mark ended: marked 1 objects 169 | 58952922: concurrent sweep began 170 | 58992921: concurrent sweep ended 171 | 58995021: nonmoving heap census 8: 0 active segments, 0 filled segments, 0 live blocks 172 | 58996121: nonmoving heap census 16: 0 active segments, 0 filled segments, 54 live blocks 173 | 58996721: nonmoving heap census 24: 0 active segments, 0 filled segments, 120 live blocks 174 | 58998821: nonmoving heap census 32: 2 active segments, 4 filled segments, 4100 live blocks 175 | 58999321: nonmoving heap census 40: 0 active segments, 0 filled segments, 1 live blocks 176 | 58999821: nonmoving heap census 48: 0 active segments, 0 filled segments, 3 live blocks 177 | 59000121: nonmoving heap census 56: 0 active segments, 0 filled segments, 0 live blocks 178 | 59000421: nonmoving heap census 64: 0 active segments, 0 filled segments, 2 live blocks 179 | 59000721: nonmoving heap census 72: 0 active segments, 0 filled segments, 0 live blocks 180 | 59001021: nonmoving heap census 80: 0 active segments, 0 filled segments, 0 live blocks 181 | 59001321: nonmoving heap census 88: 0 active segments, 0 filled segments, 0 live blocks 182 | 59001721: nonmoving heap census 96: 0 active segments, 0 filled segments, 0 live blocks 183 | 59001921: nonmoving heap census 104: 0 active segments, 0 filled segments, 0 live blocks 184 | 59002221: nonmoving heap census 112: 0 active segments, 0 filled segments, 0 live blocks 185 | 59002421: nonmoving heap census 120: 0 active segments, 0 filled segments, 0 live blocks 186 | 59002621: nonmoving heap census 128: 0 active segments, 0 filled segments, 1 live blocks 187 | 59002821: nonmoving heap census 256: 0 active segments, 0 filled segments, 1 live blocks 188 | 59002921: nonmoving heap census 512: 0 active segments, 0 filled segments, 0 live blocks 189 | 59003021: nonmoving heap census 1024: 0 active segments, 0 filled segments, 1 live blocks 190 | 59003121: nonmoving heap census 2048: 0 active segments, 0 filled segments, 0 live blocks 191 | 59003221: nonmoving heap census 4096: 0 active segments, 0 filled segments, 0 live blocks 192 | 59003421: nonmoving heap census 8192: 0 active segments, 0 filled segments, 0 live blocks 193 | 59003421: nonmoving heap census 16384: 0 active segments, 0 filled segments, 0 live blocks 194 | 60250409: Starting nonmoving GC preparation 195 | 60251309: Marking roots for nonmoving GC 196 | 60251709: Finished marking roots for nonmoving GC 197 | 60251709: Finished nonmoving GC preparation 198 | 60252909: concurrent mark began 199 | 60308008: concurrent mark ended: marked 1897 objects 200 | 60308108: concurrent mark began 201 | 60308508: concurrent mark ended: marked 8 objects 202 | 60308608: concurrent mark began 203 | 60308708: concurrent mark ended: marked 1 objects 204 | 60308708: concurrent mark began 205 | 60308808: concurrent mark ended: marked 2 objects 206 | 60309608: concurrent sweep began 207 | 60314808: concurrent sweep ended 208 | 60316708: nonmoving heap census 8: 0 active segments, 0 filled segments, 0 live blocks 209 | 60317708: nonmoving heap census 16: 0 active segments, 0 filled segments, 55 live blocks 210 | 60318408: nonmoving heap census 24: 0 active segments, 0 filled segments, 121 live blocks 211 | 60320508: nonmoving heap census 32: 2 active segments, 0 filled segments, 37 live blocks 212 | 60320908: nonmoving heap census 40: 0 active segments, 0 filled segments, 1 live blocks 213 | 60321408: nonmoving heap census 48: 0 active segments, 0 filled segments, 3 live blocks 214 | 60321708: nonmoving heap census 56: 0 active segments, 0 filled segments, 0 live blocks 215 | 60322008: nonmoving heap census 64: 0 active segments, 0 filled segments, 2 live blocks 216 | 60322308: nonmoving heap census 72: 0 active segments, 0 filled segments, 0 live blocks 217 | 60322608: nonmoving heap census 80: 0 active segments, 0 filled segments, 0 live blocks 218 | 60322808: nonmoving heap census 88: 0 active segments, 0 filled segments, 0 live blocks 219 | 60323408: nonmoving heap census 96: 0 active segments, 0 filled segments, 0 live blocks 220 | 60323608: nonmoving heap census 104: 0 active segments, 0 filled segments, 0 live blocks 221 | 60323808: nonmoving heap census 112: 0 active segments, 0 filled segments, 0 live blocks 222 | 60324008: nonmoving heap census 120: 0 active segments, 0 filled segments, 0 live blocks 223 | 60324208: nonmoving heap census 128: 0 active segments, 0 filled segments, 1 live blocks 224 | 60324408: nonmoving heap census 256: 0 active segments, 0 filled segments, 1 live blocks 225 | 60324508: nonmoving heap census 512: 0 active segments, 0 filled segments, 0 live blocks 226 | 60324608: nonmoving heap census 1024: 0 active segments, 0 filled segments, 1 live blocks 227 | 60324708: nonmoving heap census 2048: 0 active segments, 0 filled segments, 0 live blocks 228 | 60324808: nonmoving heap census 4096: 0 active segments, 0 filled segments, 0 live blocks 229 | 60324808: nonmoving heap census 8192: 0 active segments, 0 filled segments, 0 live blocks 230 | 60324908: nonmoving heap census 16384: 0 active segments, 0 filled segments, 0 live blocks 231 | 232 | -------------------------------------------------------------------------------- /test/nonmoving-gc-census.eventlog: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haskell/ghc-events/23a4082569ca2006186931d8f35933bfce7bb67c/test/nonmoving-gc-census.eventlog -------------------------------------------------------------------------------- /test/nonmoving-gc-census.eventlog.reference: -------------------------------------------------------------------------------- 1 | Event Types: 2 | 0: Create thread (size 4) 3 | 1: Run thread (size 4) 4 | 2: Stop thread (size 10) 5 | 3: Thread runnable (size 4) 6 | 4: Migrate thread (size 6) 7 | 8: Wakeup thread (size 6) 8 | 9: Starting GC (size 0) 9 | 10: Finished GC (size 0) 10 | 11: Request sequential GC (size 0) 11 | 12: Request parallel GC (size 0) 12 | 15: Create spark thread (size 4) 13 | 16: Log message (size variable) 14 | 18: Block marker (size 14) 15 | 19: User message (size variable) 16 | 20: GC idle (size 0) 17 | 21: GC working (size 0) 18 | 22: GC done (size 0) 19 | 25: Create capability set (size 6) 20 | 26: Delete capability set (size 4) 21 | 27: Add capability to capability set (size 6) 22 | 28: Remove capability from capability set (size 6) 23 | 29: RTS name and version (size variable) 24 | 30: Program arguments (size variable) 25 | 31: Program environment variables (size variable) 26 | 32: Process ID (size 8) 27 | 33: Parent process ID (size 8) 28 | 34: Spark counters (size 56) 29 | 35: Spark create (size 0) 30 | 36: Spark dud (size 0) 31 | 37: Spark overflow (size 0) 32 | 38: Spark run (size 0) 33 | 39: Spark steal (size 2) 34 | 40: Spark fizzle (size 0) 35 | 41: Spark GC (size 0) 36 | 43: Wall clock time (size 16) 37 | 44: Thread label (size variable) 38 | 45: Create capability (size 2) 39 | 46: Delete capability (size 2) 40 | 47: Disable capability (size 2) 41 | 48: Enable capability (size 2) 42 | 49: Total heap mem ever allocated (size 12) 43 | 50: Current heap size (size 12) 44 | 51: Current heap live data (size 12) 45 | 52: Heap static parameters (size 38) 46 | 53: GC statistics (size 58) 47 | 54: Synchronise stop-the-world GC (size 0) 48 | 55: Task create (size 18) 49 | 56: Task migrate (size 12) 50 | 57: Task delete (size 8) 51 | 58: User marker (size variable) 52 | 59: Empty event for bug #9003 (size 0) 53 | 160: Start of heap profile (size variable) 54 | 161: Cost center definition (size variable) 55 | 162: Start of heap profile sample (size 8) 56 | 163: Heap profile cost-centre sample (size variable) 57 | 164: Heap profile string sample (size variable) 58 | 165: End of heap profile sample (size 8) 59 | 166: Start of heap profile (biographical) sample (size 16) 60 | 167: Time profile cost-centre stack (size variable) 61 | 168: Start of a time profile (size 8) 62 | 181: User binary message (size variable) 63 | 200: Begin concurrent mark phase (size 0) 64 | 201: End concurrent mark phase (size 4) 65 | 202: Begin concurrent GC synchronisation (size 0) 66 | 203: End concurrent GC synchronisation (size 0) 67 | 204: Begin concurrent sweep (size 0) 68 | 205: End concurrent sweep (size 0) 69 | 206: Update remembered set flushed (size 2) 70 | 207: Nonmoving heap census (size 13) 71 | 72 | Events: 73 | 227855: capset 1: wall clock time 1587597517s 544758000ns (unix epoch) 74 | 229418: capset 0: pid 1158 75 | 231368: capset 0: parent pid 25700 76 | 233264: capset 0: RTS version "GHC-8.11.0.20200422 rts_thr_l" 77 | 233773: capset 0: args: ["nofib/shootout/binary-trees/Main","15","11","+RTS","-xn","-l-an"] 78 | 2789899: Starting nonmoving GC preparation 79 | 2811955: Marking roots for nonmoving GC 80 | 2813333: Finished marking roots for nonmoving GC 81 | 2813512: Finished nonmoving GC preparation 82 | 2872560: concurrent mark began 83 | 3320668: concurrent mark ended: marked 2869 objects 84 | 3337805: post-mark synchronization began 85 | 3337996: post-mark synchronization began 86 | 3682910: cap 0: update remembered set flushed by 0 87 | 3683825: concurrent mark began 88 | 3692251: concurrent mark ended: marked 1042 objects 89 | 3692392: concurrent mark began 90 | 3692462: concurrent mark ended: marked 1 objects 91 | 3692552: concurrent mark began 92 | 3692621: concurrent mark ended: marked 1 objects 93 | 3716334: post-mark synchronization ended 94 | 3716512: post-mark synchronization ended 95 | 3720779: concurrent sweep began 96 | 3721599: concurrent sweep ended 97 | 3726029: nonmoving heap census 8: 0 active segments, 0 filled segments, 0 live blocks 98 | 3728053: nonmoving heap census 16: 0 active segments, 0 filled segments, 54 live blocks 99 | 3729679: nonmoving heap census 32: 0 active segments, 0 filled segments, 128 live blocks 100 | 3730314: nonmoving heap census 64: 0 active segments, 0 filled segments, 0 live blocks 101 | 3730776: nonmoving heap census 128: 0 active segments, 0 filled segments, 0 live blocks 102 | 3731036: nonmoving heap census 256: 0 active segments, 0 filled segments, 0 live blocks 103 | 3731339: nonmoving heap census 512: 0 active segments, 0 filled segments, 0 live blocks 104 | 3731574: nonmoving heap census 1024: 0 active segments, 0 filled segments, 0 live blocks 105 | 3731786: nonmoving heap census 2048: 0 active segments, 0 filled segments, 0 live blocks 106 | 3731990: nonmoving heap census 4096: 0 active segments, 0 filled segments, 0 live blocks 107 | 3732268: nonmoving heap census 8192: 0 active segments, 0 filled segments, 0 live blocks 108 | 3732469: nonmoving heap census 16384: 0 active segments, 0 filled segments, 0 live blocks 109 | 32362284: Starting nonmoving GC preparation 110 | 32371855: Marking roots for nonmoving GC 111 | 32373519: Finished marking roots for nonmoving GC 112 | 32373686: Finished nonmoving GC preparation 113 | 32557821: concurrent mark began 114 | 33910745: concurrent mark ended: marked 16928 objects 115 | 33914172: concurrent mark began 116 | 33916300: concurrent mark ended: marked 13 objects 117 | 33924796: post-mark synchronization began 118 | 33925033: post-mark synchronization began 119 | 34219802: cap 0: update remembered set flushed by 0 120 | 34221200: concurrent mark began 121 | 34240845: concurrent mark ended: marked 1084 objects 122 | 34241350: concurrent mark began 123 | 34241419: concurrent mark ended: marked 1 objects 124 | 34241632: concurrent mark began 125 | 34241702: concurrent mark ended: marked 1 objects 126 | 34271446: post-mark synchronization ended 127 | 34271858: post-mark synchronization ended 128 | 34283960: concurrent sweep began 129 | 34559614: concurrent sweep ended 130 | 34563964: nonmoving heap census 8: 0 active segments, 0 filled segments, 0 live blocks 131 | 34576318: nonmoving heap census 16: 3 active segments, 0 filled segments, 1259 live blocks 132 | 34591543: nonmoving heap census 32: 6 active segments, 4 filled segments, 6385 live blocks 133 | 34596442: nonmoving heap census 64: 4 active segments, 1 filled segments, 1031 live blocks 134 | 34597260: nonmoving heap census 128: 0 active segments, 0 filled segments, 42 live blocks 135 | 34597718: nonmoving heap census 256: 0 active segments, 0 filled segments, 1 live blocks 136 | 34598055: nonmoving heap census 512: 0 active segments, 0 filled segments, 1 live blocks 137 | 34598375: nonmoving heap census 1024: 0 active segments, 0 filled segments, 4 live blocks 138 | 34598666: nonmoving heap census 2048: 0 active segments, 0 filled segments, 0 live blocks 139 | 34598997: nonmoving heap census 4096: 0 active segments, 0 filled segments, 0 live blocks 140 | 34599265: nonmoving heap census 8192: 0 active segments, 0 filled segments, 0 live blocks 141 | 34599501: nonmoving heap census 16384: 0 active segments, 0 filled segments, 0 live blocks 142 | 67279769: Starting nonmoving GC preparation 143 | 67281581: Marking roots for nonmoving GC 144 | 67282874: Finished marking roots for nonmoving GC 145 | 67283133: Finished nonmoving GC preparation 146 | 67370910: concurrent mark began 147 | 68397276: concurrent mark ended: marked 16875 objects 148 | 68398499: concurrent mark began 149 | 68399339: concurrent mark ended: marked 13 objects 150 | 68402178: post-mark synchronization began 151 | 68402344: post-mark synchronization began 152 | 68682534: cap 0: update remembered set flushed by 0 153 | 68683459: concurrent mark began 154 | 68688876: concurrent mark ended: marked 352 objects 155 | 68689271: concurrent mark began 156 | 68689388: concurrent mark ended: marked 1 objects 157 | 68689515: concurrent mark began 158 | 68689626: concurrent mark ended: marked 1 objects 159 | 68704339: post-mark synchronization ended 160 | 68704591: post-mark synchronization ended 161 | 68710131: concurrent sweep began 162 | 68830040: concurrent sweep ended 163 | 68834054: nonmoving heap census 8: 0 active segments, 0 filled segments, 0 live blocks 164 | 68843935: nonmoving heap census 16: 3 active segments, 1 filled segments, 2855 live blocks 165 | 68858424: nonmoving heap census 32: 6 active segments, 3 filled segments, 5846 live blocks 166 | 68862979: nonmoving heap census 64: 4 active segments, 0 filled segments, 703 live blocks 167 | 68863622: nonmoving heap census 128: 0 active segments, 0 filled segments, 43 live blocks 168 | 68863967: nonmoving heap census 256: 0 active segments, 0 filled segments, 1 live blocks 169 | 68864313: nonmoving heap census 512: 0 active segments, 0 filled segments, 1 live blocks 170 | 68864669: nonmoving heap census 1024: 0 active segments, 0 filled segments, 5 live blocks 171 | 68865004: nonmoving heap census 2048: 0 active segments, 0 filled segments, 0 live blocks 172 | 68865354: nonmoving heap census 4096: 0 active segments, 0 filled segments, 0 live blocks 173 | 68865670: nonmoving heap census 8192: 0 active segments, 0 filled segments, 0 live blocks 174 | 68865931: nonmoving heap census 16384: 0 active segments, 0 filled segments, 0 live blocks 175 | 119827283: Starting nonmoving GC preparation 176 | 119830728: Marking roots for nonmoving GC 177 | 119831795: Finished marking roots for nonmoving GC 178 | 119831988: Finished nonmoving GC preparation 179 | 119938842: concurrent mark began 180 | 121053293: concurrent mark ended: marked 16438 objects 181 | 121056540: concurrent mark began 182 | 121057919: concurrent mark ended: marked 13 objects 183 | 121066516: post-mark synchronization began 184 | 121066859: post-mark synchronization began 185 | 121154737: cap 0: update remembered set flushed by 0 186 | 121161224: concurrent mark began 187 | 121186040: concurrent mark ended: marked 1079 objects 188 | 121186533: concurrent mark began 189 | 121186646: concurrent mark ended: marked 1 objects 190 | 121186774: concurrent mark began 191 | 121186841: concurrent mark ended: marked 1 objects 192 | 121231348: post-mark synchronization ended 193 | 121231969: post-mark synchronization ended 194 | 121242597: concurrent sweep began 195 | 121385240: concurrent sweep ended 196 | 121390264: nonmoving heap census 8: 0 active segments, 0 filled segments, 0 live blocks 197 | 121405730: nonmoving heap census 16: 3 active segments, 0 filled segments, 1568 live blocks 198 | 121430287: nonmoving heap census 32: 7 active segments, 3 filled segments, 6270 live blocks 199 | 121436146: nonmoving heap census 64: 4 active segments, 1 filled segments, 897 live blocks 200 | 121437265: nonmoving heap census 128: 0 active segments, 0 filled segments, 43 live blocks 201 | 121437840: nonmoving heap census 256: 0 active segments, 0 filled segments, 1 live blocks 202 | 121438948: nonmoving heap census 512: 0 active segments, 0 filled segments, 1 live blocks 203 | 121439371: nonmoving heap census 1024: 0 active segments, 0 filled segments, 5 live blocks 204 | 121439723: nonmoving heap census 2048: 0 active segments, 0 filled segments, 0 live blocks 205 | 121440083: nonmoving heap census 4096: 0 active segments, 0 filled segments, 0 live blocks 206 | 121440368: nonmoving heap census 8192: 0 active segments, 0 filled segments, 0 live blocks 207 | 121441292: nonmoving heap census 16384: 0 active segments, 0 filled segments, 0 live blocks 208 | 148361407: Starting nonmoving GC preparation 209 | 148365127: Marking roots for nonmoving GC 210 | 148366468: Finished marking roots for nonmoving GC 211 | 148366670: Finished nonmoving GC preparation 212 | 148527085: concurrent mark began 213 | 149775840: concurrent mark ended: marked 15225 objects 214 | 149778324: concurrent mark began 215 | 149779513: concurrent mark ended: marked 13 objects 216 | 149810324: post-mark synchronization began 217 | 149810665: post-mark synchronization began 218 | 149850617: cap 0: update remembered set flushed by 0 219 | 149851300: concurrent mark began 220 | 149866270: concurrent mark ended: marked 1049 objects 221 | 149866671: concurrent mark began 222 | 149866848: concurrent mark ended: marked 1 objects 223 | 149867039: concurrent mark began 224 | 149867202: concurrent mark ended: marked 1 objects 225 | 149874824: post-mark synchronization ended 226 | 149875168: post-mark synchronization ended 227 | 149901246: concurrent sweep began 228 | 150026135: concurrent sweep ended 229 | 150031083: nonmoving heap census 8: 0 active segments, 0 filled segments, 0 live blocks 230 | 150045140: nonmoving heap census 16: 3 active segments, 1 filled segments, 3342 live blocks 231 | 150066310: nonmoving heap census 32: 8 active segments, 3 filled segments, 5613 live blocks 232 | 150071204: nonmoving heap census 64: 4 active segments, 0 filled segments, 567 live blocks 233 | 150071885: nonmoving heap census 128: 0 active segments, 0 filled segments, 44 live blocks 234 | 150073125: nonmoving heap census 256: 0 active segments, 0 filled segments, 1 live blocks 235 | 150073558: nonmoving heap census 512: 0 active segments, 0 filled segments, 1 live blocks 236 | 150074077: nonmoving heap census 1024: 0 active segments, 0 filled segments, 6 live blocks 237 | 150074414: nonmoving heap census 2048: 0 active segments, 0 filled segments, 0 live blocks 238 | 150074832: nonmoving heap census 4096: 0 active segments, 0 filled segments, 0 live blocks 239 | 150075820: nonmoving heap census 8192: 0 active segments, 0 filled segments, 0 live blocks 240 | 150076102: nonmoving heap census 16384: 0 active segments, 0 filled segments, 0 live blocks 241 | 176942302: Starting nonmoving GC preparation 242 | 176945061: Marking roots for nonmoving GC 243 | 176946066: Finished marking roots for nonmoving GC 244 | 176946253: Finished nonmoving GC preparation 245 | 177039035: concurrent mark began 246 | 177741825: concurrent mark ended: marked 15542 objects 247 | 177744446: concurrent mark began 248 | 177745256: concurrent mark ended: marked 13 objects 249 | 177750528: post-mark synchronization began 250 | 177750635: post-mark synchronization began 251 | 177896570: cap 0: update remembered set flushed by 0 252 | 177896939: concurrent mark began 253 | 177910616: concurrent mark ended: marked 1082 objects 254 | 177911218: concurrent mark began 255 | 177911307: concurrent mark ended: marked 1 objects 256 | 177911422: concurrent mark began 257 | 177911493: concurrent mark ended: marked 1 objects 258 | 177919949: post-mark synchronization ended 259 | 177920053: post-mark synchronization ended 260 | 177925925: concurrent sweep began 261 | 178017822: concurrent sweep ended 262 | 178020408: nonmoving heap census 8: 0 active segments, 0 filled segments, 0 live blocks 263 | 178026736: nonmoving heap census 16: 1 active segments, 1 filled segments, 2963 live blocks 264 | 178041784: nonmoving heap census 32: 7 active segments, 3 filled segments, 5977 live blocks 265 | 178045269: nonmoving heap census 64: 4 active segments, 1 filled segments, 757 live blocks 266 | 178045812: nonmoving heap census 128: 0 active segments, 0 filled segments, 44 live blocks 267 | 178046142: nonmoving heap census 256: 0 active segments, 0 filled segments, 1 live blocks 268 | 178046413: nonmoving heap census 512: 0 active segments, 0 filled segments, 1 live blocks 269 | 178046632: nonmoving heap census 1024: 0 active segments, 0 filled segments, 6 live blocks 270 | 178047048: nonmoving heap census 2048: 0 active segments, 0 filled segments, 0 live blocks 271 | 178047379: nonmoving heap census 4096: 0 active segments, 0 filled segments, 0 live blocks 272 | 178047876: nonmoving heap census 8192: 0 active segments, 0 filled segments, 0 live blocks 273 | 178048246: nonmoving heap census 16384: 0 active segments, 0 filled segments, 0 live blocks 274 | 202506857: Starting nonmoving GC preparation 275 | 202508058: Marking roots for nonmoving GC 276 | 202517509: Finished marking roots for nonmoving GC 277 | 202517677: Finished nonmoving GC preparation 278 | 202566458: concurrent mark began 279 | 203074473: concurrent mark ended: marked 16604 objects 280 | 203074950: concurrent mark began 281 | 203075547: concurrent mark ended: marked 13 objects 282 | 203078118: post-mark synchronization began 283 | 203078232: post-mark synchronization began 284 | 203131205: cap 0: update remembered set flushed by 0 285 | 203131506: concurrent mark began 286 | 203140444: concurrent mark ended: marked 1083 objects 287 | 203140572: concurrent mark began 288 | 203140635: concurrent mark ended: marked 1 objects 289 | 203140714: concurrent mark began 290 | 203140783: concurrent mark ended: marked 1 objects 291 | 203149980: post-mark synchronization ended 292 | 203150083: post-mark synchronization ended 293 | 203153609: concurrent sweep began 294 | 203241257: concurrent sweep ended 295 | 203243717: nonmoving heap census 8: 0 active segments, 0 filled segments, 0 live blocks 296 | 203252554: nonmoving heap census 16: 3 active segments, 1 filled segments, 3188 live blocks 297 | 203263495: nonmoving heap census 32: 7 active segments, 4 filled segments, 6373 live blocks 298 | 203266345: nonmoving heap census 64: 4 active segments, 1 filled segments, 947 live blocks 299 | 203266828: nonmoving heap census 128: 0 active segments, 0 filled segments, 45 live blocks 300 | 203267099: nonmoving heap census 256: 0 active segments, 0 filled segments, 1 live blocks 301 | 203267302: nonmoving heap census 512: 0 active segments, 0 filled segments, 1 live blocks 302 | 203267563: nonmoving heap census 1024: 0 active segments, 0 filled segments, 7 live blocks 303 | 203267805: nonmoving heap census 2048: 0 active segments, 0 filled segments, 0 live blocks 304 | 203268121: nonmoving heap census 4096: 0 active segments, 0 filled segments, 0 live blocks 305 | 203268260: nonmoving heap census 8192: 0 active segments, 0 filled segments, 0 live blocks 306 | 203268439: nonmoving heap census 16384: 0 active segments, 0 filled segments, 0 live blocks 307 | 224422635: Starting nonmoving GC preparation 308 | 224424065: Marking roots for nonmoving GC 309 | 224424970: Finished marking roots for nonmoving GC 310 | 224425126: Finished nonmoving GC preparation 311 | 224506119: concurrent mark began 312 | 225279214: concurrent mark ended: marked 15033 objects 313 | 225280063: concurrent mark began 314 | 225280703: concurrent mark ended: marked 13 objects 315 | 225283313: post-mark synchronization began 316 | 225283479: post-mark synchronization began 317 | 225341600: cap 0: update remembered set flushed by 0 318 | 225342335: concurrent mark began 319 | 225351353: concurrent mark ended: marked 1049 objects 320 | 225351605: concurrent mark began 321 | 225351675: concurrent mark ended: marked 1 objects 322 | 225351773: concurrent mark began 323 | 225351842: concurrent mark ended: marked 1 objects 324 | 225383632: post-mark synchronization ended 325 | 225383831: post-mark synchronization ended 326 | 225388468: concurrent sweep began 327 | 225553609: concurrent sweep ended 328 | 225557870: nonmoving heap census 8: 0 active segments, 0 filled segments, 0 live blocks 329 | 225572051: nonmoving heap census 16: 3 active segments, 0 filled segments, 1860 live blocks 330 | 225587504: nonmoving heap census 32: 6 active segments, 3 filled segments, 5705 live blocks 331 | 225592583: nonmoving heap census 64: 4 active segments, 0 filled segments, 621 live blocks 332 | 225593429: nonmoving heap census 128: 0 active segments, 0 filled segments, 46 live blocks 333 | 225593797: nonmoving heap census 256: 0 active segments, 0 filled segments, 1 live blocks 334 | 225594147: nonmoving heap census 512: 0 active segments, 0 filled segments, 1 live blocks 335 | 225594554: nonmoving heap census 1024: 0 active segments, 0 filled segments, 8 live blocks 336 | 225594804: nonmoving heap census 2048: 0 active segments, 0 filled segments, 0 live blocks 337 | 225595452: nonmoving heap census 4096: 0 active segments, 0 filled segments, 0 live blocks 338 | 225596376: nonmoving heap census 8192: 0 active segments, 0 filled segments, 0 live blocks 339 | 225597481: nonmoving heap census 16384: 0 active segments, 0 filled segments, 0 live blocks 340 | 341 | -------------------------------------------------------------------------------- /test/nonmoving-gc-pruned-segments.eventlog: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haskell/ghc-events/23a4082569ca2006186931d8f35933bfce7bb67c/test/nonmoving-gc-pruned-segments.eventlog -------------------------------------------------------------------------------- /test/nonmoving-gc.eventlog: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haskell/ghc-events/23a4082569ca2006186931d8f35933bfce7bb67c/test/nonmoving-gc.eventlog -------------------------------------------------------------------------------- /test/nonmoving-gc.eventlog.reference: -------------------------------------------------------------------------------- 1 | Event Types: 2 | 0: Create thread (size 4) 3 | 1: Run thread (size 4) 4 | 2: Stop thread (size 10) 5 | 3: Thread runnable (size 4) 6 | 4: Migrate thread (size 6) 7 | 8: Wakeup thread (size 6) 8 | 9: Starting GC (size 0) 9 | 10: Finished GC (size 0) 10 | 11: Request sequential GC (size 0) 11 | 12: Request parallel GC (size 0) 12 | 15: Create spark thread (size 4) 13 | 16: Log message (size variable) 14 | 18: Block marker (size 14) 15 | 19: User message (size variable) 16 | 20: GC idle (size 0) 17 | 21: GC working (size 0) 18 | 22: GC done (size 0) 19 | 25: Create capability set (size 6) 20 | 26: Delete capability set (size 4) 21 | 27: Add capability to capability set (size 6) 22 | 28: Remove capability from capability set (size 6) 23 | 29: RTS name and version (size variable) 24 | 30: Program arguments (size variable) 25 | 31: Program environment variables (size variable) 26 | 32: Process ID (size 8) 27 | 33: Parent process ID (size 8) 28 | 34: Spark counters (size 56) 29 | 35: Spark create (size 0) 30 | 36: Spark dud (size 0) 31 | 37: Spark overflow (size 0) 32 | 38: Spark run (size 0) 33 | 39: Spark steal (size 2) 34 | 40: Spark fizzle (size 0) 35 | 41: Spark GC (size 0) 36 | 43: Wall clock time (size 16) 37 | 44: Thread label (size variable) 38 | 45: Create capability (size 2) 39 | 46: Delete capability (size 2) 40 | 47: Disable capability (size 2) 41 | 48: Enable capability (size 2) 42 | 49: Total heap mem ever allocated (size 12) 43 | 50: Current heap size (size 12) 44 | 51: Current heap live data (size 12) 45 | 52: Heap static parameters (size 38) 46 | 53: GC statistics (size 58) 47 | 54: Synchronise stop-the-world GC (size 0) 48 | 55: Task create (size 18) 49 | 56: Task migrate (size 12) 50 | 57: Task delete (size 8) 51 | 58: User marker (size variable) 52 | 59: Empty event for bug #9003 (size 0) 53 | 160: Start of heap profile (size variable) 54 | 161: Cost center definition (size variable) 55 | 162: Start of heap profile sample (size 8) 56 | 163: Heap profile cost-centre sample (size variable) 57 | 164: Heap profile string sample (size variable) 58 | 165: End of heap profile sample (size 8) 59 | 166: Start of heap profile (biographical) sample (size 16) 60 | 167: Time profile cost-centre stack (size variable) 61 | 168: Start of a time profile (size 8) 62 | 181: User binary message (size variable) 63 | 200: Begin concurrent mark phase (size 0) 64 | 201: End concurrent mark phase (size 4) 65 | 202: Begin concurrent GC synchronisation (size 0) 66 | 203: End concurrent GC synchronisation (size 0) 67 | 204: Begin concurrent sweep (size 0) 68 | 205: End concurrent sweep (size 0) 69 | 206: Update remembered set flushed (size 2) 70 | 207: Nonmoving heap census (size 13) 71 | 72 | Events: 73 | 620636: capset 1: wall clock time 1587578331s 829795000ns (unix epoch) 74 | 627395: capset 0: pid 20807 75 | 636419: capset 0: parent pid 18766 76 | 644544: capset 0: RTS version "GHC-8.10.1 rts_thr_debug" 77 | 649853: capset 0: args: ["./Main","10","+RTS","-l-an","-xn"] 78 | 20282519: Starting nonmoving GC preparation 79 | 20305849: Marking roots for nonmoving GC 80 | 20331402: Finished marking roots for nonmoving GC 81 | 20333822: Finished nonmoving GC preparation 82 | 20810540: concurrent mark began 83 | 30089152: concurrent mark ended: marked 6677 objects 84 | 30210049: post-mark synchronization began 85 | 32582336: cap 0: update remembered set flushed by 0 86 | 32608578: concurrent mark began 87 | 35122177: concurrent mark ended: marked 7758 objects 88 | 35126012: concurrent mark began 89 | 35127755: concurrent mark ended: marked 1 objects 90 | 35129046: concurrent mark began 91 | 35129935: concurrent mark ended: marked 1 objects 92 | 35203888: post-mark synchronization ended 93 | 35258771: concurrent sweep began 94 | 35263947: concurrent sweep ended 95 | 96 | -------------------------------------------------------------------------------- /test/parallelTest.eventlog: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haskell/ghc-events/23a4082569ca2006186931d8f35933bfce7bb67c/test/parallelTest.eventlog -------------------------------------------------------------------------------- /test/sleep.h.eventlog: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haskell/ghc-events/23a4082569ca2006186931d8f35933bfce7bb67c/test/sleep.h.eventlog -------------------------------------------------------------------------------- /test/sleep.hC.eventlog: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haskell/ghc-events/23a4082569ca2006186931d8f35933bfce7bb67c/test/sleep.hC.eventlog -------------------------------------------------------------------------------- /test/sleep.hd.eventlog: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haskell/ghc-events/23a4082569ca2006186931d8f35933bfce7bb67c/test/sleep.hd.eventlog -------------------------------------------------------------------------------- /test/sleep.hm.eventlog: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haskell/ghc-events/23a4082569ca2006186931d8f35933bfce7bb67c/test/sleep.hm.eventlog -------------------------------------------------------------------------------- /test/sleep.hy.eventlog: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haskell/ghc-events/23a4082569ca2006186931d8f35933bfce7bb67c/test/sleep.hy.eventlog -------------------------------------------------------------------------------- /test/stop.hT.eventlog: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haskell/ghc-events/23a4082569ca2006186931d8f35933bfce7bb67c/test/stop.hT.eventlog -------------------------------------------------------------------------------- /test/stop.hs: -------------------------------------------------------------------------------- 1 | -- This test program triggers different thread stop encodings in 2 | -- eventlogs, depending on GHC version (black hole, mvar read, mvar) 3 | 4 | module Main where 5 | 6 | import Control.Concurrent 7 | import Debug.Trace 8 | import GHC.Conc 9 | 10 | main = do 11 | putStrLn "suggest to run with +RTS -lsu-g-p -K80m -k10m -H200m -C1s" 12 | 13 | -- define some time-consuming computation 14 | let stuff = ack 3 10 15 | -- create MVars to block on 16 | v1 <- newMVar "full" 17 | v2 <- newEmptyMVar 18 | -- create a thread which blackholes something, and re-fills the MVar 19 | traceEventIO "forking child thread" 20 | forkIO (do traceEventIO "child" 21 | putStrLn ("child thread sez " ++ show stuff) 22 | traceEventIO "filling full MVar" 23 | putMVar v1 "filled full var" 24 | yield 25 | traceEventIO "filling empty MVar" 26 | putMVar v2 "filled empty var" 27 | yield 28 | traceEventIO "child finished" 29 | ) 30 | yield 31 | putStrLn ("and the main thread sez " ++ show stuff) 32 | traceEventIO "emptying full MVar" 33 | s1 <- takeMVar v1 34 | putStrLn ("from MVar: " ++ s1) 35 | traceEventIO "reading empty MVar" 36 | s2 <- readMVar v2 37 | putStrLn ("from MVar: " ++ s2) 38 | 39 | ack :: Integer -> Integer -> Integer 40 | ack 0 m = m+1 41 | ack n 0 = ack (n-1) 1 42 | ack n m = ack (n-1) (ack n (m-1)) 43 | -------------------------------------------------------------------------------- /test/testlog-part.eventlog: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haskell/ghc-events/23a4082569ca2006186931d8f35933bfce7bb67c/test/testlog-part.eventlog -------------------------------------------------------------------------------- /test/testlog.eventlog: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haskell/ghc-events/23a4082569ca2006186931d8f35933bfce7bb67c/test/testlog.eventlog -------------------------------------------------------------------------------- /test/ticky-begin-sample.eventlog: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haskell/ghc-events/23a4082569ca2006186931d8f35933bfce7bb67c/test/ticky-begin-sample.eventlog -------------------------------------------------------------------------------- /test/ticky-begin-sample.eventlog.reference: -------------------------------------------------------------------------------- 1 | Event Types: 2 | 0: Create thread (size 4) 3 | 1: Run thread (size 4) 4 | 2: Stop thread (size 10) 5 | 3: Thread runnable (size 4) 6 | 4: Migrate thread (size 6) 7 | 8: Wakeup thread (size 6) 8 | 9: Starting GC (size 0) 9 | 10: Finished GC (size 0) 10 | 11: Request sequential GC (size 0) 11 | 12: Request parallel GC (size 0) 12 | 15: Create spark thread (size 4) 13 | 16: Log message (size variable) 14 | 18: Block marker (size 14) 15 | 19: User message (size variable) 16 | 20: GC idle (size 0) 17 | 21: GC working (size 0) 18 | 22: GC done (size 0) 19 | 25: Create capability set (size 6) 20 | 26: Delete capability set (size 4) 21 | 27: Add capability to capability set (size 6) 22 | 28: Remove capability from capability set (size 6) 23 | 29: RTS name and version (size variable) 24 | 30: Program arguments (size variable) 25 | 31: Program environment variables (size variable) 26 | 32: Process ID (size 8) 27 | 33: Parent process ID (size 8) 28 | 34: Spark counters (size 56) 29 | 35: Spark create (size 0) 30 | 36: Spark dud (size 0) 31 | 37: Spark overflow (size 0) 32 | 38: Spark run (size 0) 33 | 39: Spark steal (size 2) 34 | 40: Spark fizzle (size 0) 35 | 41: Spark GC (size 0) 36 | 43: Wall clock time (size 16) 37 | 44: Thread label (size variable) 38 | 45: Create capability (size 2) 39 | 46: Delete capability (size 2) 40 | 47: Disable capability (size 2) 41 | 48: Enable capability (size 2) 42 | 49: Total heap mem ever allocated (size 12) 43 | 50: Current heap size (size of allocated mblocks) (size 12) 44 | 51: Current heap live data (size 12) 45 | 52: Heap static parameters (size 38) 46 | 53: GC statistics (size 58) 47 | 54: Synchronise stop-the-world GC (size 0) 48 | 55: Task create (size 18) 49 | 56: Task migrate (size 12) 50 | 57: Task delete (size 8) 51 | 58: User marker (size variable) 52 | 59: Empty event for bug #9003 (size 0) 53 | 90: Memory return statistics (size 16) 54 | 91: Current heap size (size of allocated blocks) (size 12) 55 | 160: Start of heap profile (size variable) 56 | 161: Cost center definition (size variable) 57 | 162: Start of heap profile sample (size 8) 58 | 163: Heap profile cost-centre sample (size variable) 59 | 164: Heap profile string sample (size variable) 60 | 165: End of heap profile sample (size 8) 61 | 166: Start of heap profile (biographical) sample (size 16) 62 | 167: Time profile cost-centre stack (size variable) 63 | 168: Start of a time profile (size 8) 64 | 169: Info Table Source Position (size variable) 65 | 181: User binary message (size variable) 66 | 200: Begin concurrent mark phase (size 0) 67 | 201: End concurrent mark phase (size 4) 68 | 202: Begin concurrent GC synchronisation (size 0) 69 | 203: End concurrent GC synchronisation (size 0) 70 | 204: Begin concurrent sweep (size 0) 71 | 205: End concurrent sweep (size 0) 72 | 206: Update remembered set flushed (size 2) 73 | 207: Nonmoving heap census (size 13) 74 | 210: Ticky-ticky entry counter definition (size variable) 75 | 211: Ticky-ticky entry counter sample (size 32) 76 | 212: Ticky-ticky entry counter begin sample (size 0) 77 | 78 | Events: 79 | 364000: created capset 0 of type CapsetOsProcess 80 | 364000: created capset 1 of type CapsetClockDomain 81 | 367000: created cap 0 82 | 367000: assigned cap 0 to capset 0 83 | 367000: assigned cap 0 to capset 1 84 | 372000: capset 1: wall clock time 1619330426s 424002000ns (unix epoch) 85 | 373000: capset 0: pid 1427 86 | 379000: capset 0: parent pid 62660 87 | 386000: capset 0: RTS version "GHC-9.3.20210422 rts_debug" 88 | 389000: capset 0: args: ["./Test","+RTS","-lT"] 89 | 4695000: heap stats for heap capset 0: generations 2, 0 bytes max heap size, 4194304 bytes alloc area size, 1048576 bytes mblock size, 4096 bytes block size 90 | 4782000: task 0x7f8905405ea0 created on cap 0 with OS kernel thread 14286148 91 | 4784000: cap 0: creating thread 1 92 | 4798000: cap 0: running thread 1 93 | 5139000: cap 0: stopping thread 1 (blocked on I/O write) 94 | 5167000: cap 0: running thread 1 95 | 10528000: cap 0: stopping thread 1 (thread finished) 96 | 10532000: task 0x7f8905405ea0 deleted 97 | 10537000: task 0x7f8905405ea0 created on cap 0 with OS kernel thread 14286148 98 | 10539000: cap 0: creating thread 2 99 | 10540000: cap 0: running thread 2 100 | 10555000: cap 0: stopping thread 2 (thread finished) 101 | 10556000: task 0x7f8905405ea0 deleted 102 | 10609000: cap 0: starting GC 103 | 10643000: cap 0: GC working 104 | 10969000: cap 0: GC idle 105 | 10970000: cap 0: GC done 106 | 10975000: cap 0: GC idle 107 | 10975000: cap 0: GC done 108 | 10976000: cap 0: GC idle 109 | 10976000: cap 0: GC done 110 | 10996000: ticky begin counter sample 111 | 10996000: ticky counter sample 4399605088: entry count: 1001, 120032 allocs, 16 allocd 112 | 11008000: cap 0: memory returned (mblocks): current(5) needed(8) returned(0) 113 | 11024000: cap 0: allocated on heap capset 0: 3244520 total bytes till now 114 | 11025000: cap 0: finished GC 115 | 11029000: cap 0: all caps stopped for GC 116 | 11029000: cap 0: GC stats for heap capset 0: generation 1, 3272 bytes copied, 25304 bytes slop, 892928 bytes fragmentation, 1 par threads, 0 bytes max par copied, 3272 bytes total par copied, 0 bytes balanced par copied 117 | 11030000: cap 0: live data in heap capset 0: 44328 bytes 118 | 11030000: cap 0: size of heap capset 0: 5242880 bytes 119 | 11031000: cap 0: blocks size of heap capset 0: 4268032 bytes 120 | 21006000: ticky counter definition 4399605088, arity: 1, def kinds: M, name: go{v s1bK} (Main) (fun), itbl: 0 121 | 21043000: cap 0: allocated on heap capset 0: 3244520 total bytes till now 122 | 21088000: removed cap 0 from capset 0 123 | 21089000: removed cap 0 from capset 1 124 | 21089000: deleted cap 0 125 | 21090000: deleted capset 0 126 | 21090000: deleted capset 1 127 | 128 | -------------------------------------------------------------------------------- /test/ticky-json.eventlog: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haskell/ghc-events/23a4082569ca2006186931d8f35933bfce7bb67c/test/ticky-json.eventlog -------------------------------------------------------------------------------- /test/ticky-json.eventlog.reference: -------------------------------------------------------------------------------- 1 | Event Types: 2 | 0: Create thread (size 4) 3 | 1: Run thread (size 4) 4 | 2: Stop thread (size 10) 5 | 3: Thread runnable (size 4) 6 | 4: Migrate thread (size 6) 7 | 8: Wakeup thread (size 6) 8 | 9: Starting GC (size 0) 9 | 10: Finished GC (size 0) 10 | 11: Request sequential GC (size 0) 11 | 12: Request parallel GC (size 0) 12 | 15: Create spark thread (size 4) 13 | 16: Log message (size variable) 14 | 18: Block marker (size 14) 15 | 19: User message (size variable) 16 | 20: GC idle (size 0) 17 | 21: GC working (size 0) 18 | 22: GC done (size 0) 19 | 25: Create capability set (size 6) 20 | 26: Delete capability set (size 4) 21 | 27: Add capability to capability set (size 6) 22 | 28: Remove capability from capability set (size 6) 23 | 29: RTS name and version (size variable) 24 | 30: Program arguments (size variable) 25 | 31: Program environment variables (size variable) 26 | 32: Process ID (size 8) 27 | 33: Parent process ID (size 8) 28 | 34: Spark counters (size 56) 29 | 35: Spark create (size 0) 30 | 36: Spark dud (size 0) 31 | 37: Spark overflow (size 0) 32 | 38: Spark run (size 0) 33 | 39: Spark steal (size 2) 34 | 40: Spark fizzle (size 0) 35 | 41: Spark GC (size 0) 36 | 42: Intern string (size variable) 37 | 43: Wall clock time (size 16) 38 | 44: Thread label (size variable) 39 | 45: Create capability (size 2) 40 | 46: Delete capability (size 2) 41 | 47: Disable capability (size 2) 42 | 48: Enable capability (size 2) 43 | 49: Total heap memory ever allocated (size 12) 44 | 50: Current heap size (number of allocated mblocks) (size 12) 45 | 51: Current heap live data (size 12) 46 | 52: Heap static parameters (size 38) 47 | 53: GC statistics (size 58) 48 | 54: Synchronise stop-the-world GC (size 0) 49 | 55: Task create (size 18) 50 | 56: Task migrate (size 12) 51 | 57: Task delete (size 8) 52 | 58: User marker (size variable) 53 | 59: Empty event for bug #9003 (size 0) 54 | 90: The RTS attempted to return heap memory to the OS (size 16) 55 | 91: Report the size of the heap in blocks (size 12) 56 | 160: Start of heap profile (size variable) 57 | 161: Cost-centre definition (size variable) 58 | 162: Start of heap profile sample (size 8) 59 | 163: Heap profile cost-centre sample (size variable) 60 | 164: Heap profile string sample (size variable) 61 | 165: End of heap profile sample (size 8) 62 | 166: Start of heap profile (biographical) sample (size 16) 63 | 167: Time profile cost-centre stack (size variable) 64 | 168: Start of a time profile (size 8) 65 | 169: An IPE entry (size variable) 66 | 181: User binary message (size variable) 67 | 200: Begin concurrent mark phase (size 0) 68 | 201: End concurrent mark phase (size 4) 69 | 202: Begin concurrent GC synchronisation (size 0) 70 | 203: End concurrent mark synchronisation (size 0) 71 | 204: Begin concurrent sweep phase (size 0) 72 | 205: End concurrent sweep phase (size 0) 73 | 206: Update remembered set flushed (size 2) 74 | 207: Nonmoving heap census (size 13) 75 | 210: Ticky-ticky entry counter definition (size variable) 76 | 211: Ticky-ticky entry counter sample (size 32) 77 | 212: Ticky-ticky entry counter begin sample (size 0) 78 | 79 | Events: 80 | 585533: created capset 0 of type CapsetOsProcess 81 | 586678: created capset 1 of type CapsetClockDomain 82 | 589432: created cap 0 83 | 590057: assigned cap 0 to capset 0 84 | 590954: assigned cap 0 to capset 1 85 | 595840: capset 1: wall clock time 1656609214s 321943000ns (unix epoch) 86 | 598830: capset 0: pid 31880 87 | 602782: capset 0: parent pid 9371 88 | 607308: capset 0: RTS version "GHC-9.5.20220630 rts_debug" 89 | 610371: capset 0: args: ["./Hello","+RTS","-lT"] 90 | 968293: heap stats for heap capset 0: generations 2, 0 bytes max heap size, 4194304 bytes alloc area size, 1048576 bytes mblock size, 4096 bytes block size 91 | 1056712: task 0x1053b90 created on cap 0 with OS kernel thread 31880 92 | 1071542: cap 0: creating thread 1 93 | 1077277: cap 0: running thread 1 94 | 1420012: cap 0: stopping thread 1 (thread finished) 95 | 1426364: task 0x1053b90 deleted 96 | 1433418: task 0x1053b90 created on cap 0 with OS kernel thread 31880 97 | 1435703: cap 0: creating thread 2 98 | 1438679: cap 0: running thread 2 99 | 1467338: cap 0: stopping thread 2 (thread finished) 100 | 1469370: task 0x1053b90 deleted 101 | 1482087: cap 0: starting GC 102 | 1527577: cap 0: GC working 103 | 2512669: cap 0: GC idle 104 | 2513189: cap 0: GC done 105 | 2531327: cap 0: GC idle 106 | 2531835: cap 0: GC done 107 | 2534859: cap 0: GC idle 108 | 2535333: cap 0: GC done 109 | 2623092: cap 0: memory returned (mblocks): current(5) needed(8) returned(0) 110 | 2650140: cap 0: allocated on heap capset 0: 50712 total bytes till now 111 | 2653583: cap 0: finished GC 112 | 2654338: cap 0: all caps stopped for GC 113 | 2655011: cap 0: GC stats for heap capset 0: generation 1, 24 bytes copied, 25272 bytes slop, 892928 bytes fragmentation, 1 par threads, 0 bytes max par copied, 24 bytes total par copied, 0 bytes balanced par copied 114 | 2658546: cap 0: live data in heap capset 0: 44360 bytes 115 | 2659723: cap 0: size of heap capset 0: 5242880 bytes 116 | 2660827: cap 0: blocks size of heap capset 0: 4268032 bytes 117 | 10647726: ticky counter definition 11048952, arity: 0, def kinds: , name: Main.main1{v r1zC} (fun), itbl: 4050e0 118 | 10671542: ticky counter definition 11049168, arity: 0, def kinds: , name: Main.main4{v r1zF} (fun), itbl: 4051e0 119 | 10684344: ticky counter definition 11049280, arity: 0, def kinds: , name: :Main.main{v 01D} (fun), itbl: 405260 120 | 10708312: cap 0: allocated on heap capset 0: 50712 total bytes till now 121 | 10781116: removed cap 0 from capset 0 122 | 10781943: removed cap 0 from capset 1 123 | 10783125: deleted cap 0 124 | 10783953: deleted capset 0 125 | 10784693: deleted capset 1 126 | 127 | -------------------------------------------------------------------------------- /test/ticky-new.eventlog: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haskell/ghc-events/23a4082569ca2006186931d8f35933bfce7bb67c/test/ticky-new.eventlog -------------------------------------------------------------------------------- /test/ticky-ticky.eventlog: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haskell/ghc-events/23a4082569ca2006186931d8f35933bfce7bb67c/test/ticky-ticky.eventlog -------------------------------------------------------------------------------- /test/ticky-ticky.eventlog.reference: -------------------------------------------------------------------------------- 1 | Event Types: 2 | 0: Create thread (size 4) 3 | 1: Run thread (size 4) 4 | 2: Stop thread (size 10) 5 | 3: Thread runnable (size 4) 6 | 4: Migrate thread (size 6) 7 | 8: Wakeup thread (size 6) 8 | 9: Starting GC (size 0) 9 | 10: Finished GC (size 0) 10 | 11: Request sequential GC (size 0) 11 | 12: Request parallel GC (size 0) 12 | 15: Create spark thread (size 4) 13 | 16: Log message (size variable) 14 | 18: Block marker (size 14) 15 | 19: User message (size variable) 16 | 20: GC idle (size 0) 17 | 21: GC working (size 0) 18 | 22: GC done (size 0) 19 | 25: Create capability set (size 6) 20 | 26: Delete capability set (size 4) 21 | 27: Add capability to capability set (size 6) 22 | 28: Remove capability from capability set (size 6) 23 | 29: RTS name and version (size variable) 24 | 30: Program arguments (size variable) 25 | 31: Program environment variables (size variable) 26 | 32: Process ID (size 8) 27 | 33: Parent process ID (size 8) 28 | 34: Spark counters (size 56) 29 | 35: Spark create (size 0) 30 | 36: Spark dud (size 0) 31 | 37: Spark overflow (size 0) 32 | 38: Spark run (size 0) 33 | 39: Spark steal (size 2) 34 | 40: Spark fizzle (size 0) 35 | 41: Spark GC (size 0) 36 | 43: Wall clock time (size 16) 37 | 44: Thread label (size variable) 38 | 45: Create capability (size 2) 39 | 46: Delete capability (size 2) 40 | 47: Disable capability (size 2) 41 | 48: Enable capability (size 2) 42 | 49: Total heap mem ever allocated (size 12) 43 | 50: Current heap size (size 12) 44 | 51: Current heap live data (size 12) 45 | 52: Heap static parameters (size 38) 46 | 53: GC statistics (size 58) 47 | 54: Synchronise stop-the-world GC (size 0) 48 | 55: Task create (size 18) 49 | 56: Task migrate (size 12) 50 | 57: Task delete (size 8) 51 | 58: User marker (size variable) 52 | 59: Empty event for bug #9003 (size 0) 53 | 160: Start of heap profile (size variable) 54 | 161: Cost center definition (size variable) 55 | 162: Start of heap profile sample (size 8) 56 | 163: Heap profile cost-centre sample (size variable) 57 | 164: Heap profile string sample (size variable) 58 | 165: End of heap profile sample (size 8) 59 | 166: Start of heap profile (biographical) sample (size 16) 60 | 167: Time profile cost-centre stack (size variable) 61 | 168: Start of a time profile (size 8) 62 | 181: User binary message (size variable) 63 | 200: Begin concurrent mark phase (size 0) 64 | 201: End concurrent mark phase (size 4) 65 | 202: Begin concurrent GC synchronisation (size 0) 66 | 203: End concurrent GC synchronisation (size 0) 67 | 204: Begin concurrent sweep (size 0) 68 | 205: End concurrent sweep (size 0) 69 | 206: Update remembered set flushed (size 2) 70 | 207: Nonmoving heap census (size 13) 71 | 210: Ticky-ticky entry counter definition (size variable) 72 | 211: Ticky-ticky entry counter sample (size 32) 73 | 74 | Events: 75 | 292000: created capset 0 of type CapsetOsProcess 76 | 292000: created capset 1 of type CapsetClockDomain 77 | 293000: created cap 0 78 | 293000: assigned cap 0 to capset 0 79 | 294000: assigned cap 0 to capset 1 80 | 299000: capset 1: wall clock time 1607818763s 73220000ns (unix epoch) 81 | 299000: capset 0: pid 21680 82 | 305000: capset 0: parent pid 9239 83 | 312000: capset 0: RTS version "GHC-9.1.0.20201210 rts_debug" 84 | 315000: capset 0: args: ["./HelloWorld","+RTS","-lT"] 85 | 3772000: heap stats for heap capset 0: generations 2, 0 bytes max heap size, 1048576 bytes alloc area size, 1048576 bytes mblock size, 4096 bytes block size 86 | 3857000: task 0x7fd27f405e90 created on cap 0 with OS kernel thread 32996106 87 | 3861000: cap 0: creating thread 1 88 | 3871000: cap 0: running thread 1 89 | 4051000: cap 0: stopping thread 1 (thread finished) 90 | 4053000: task 0x7fd27f405e90 deleted 91 | 4055000: cap 0: creating thread 2 92 | 4055000: task 0x7fd27f405e90 created on cap 0 with OS kernel thread 32996106 93 | 4056000: cap 0: running thread 2 94 | 4060000: cap 0: stopping thread 2 (thread finished) 95 | 4061000: task 0x7fd27f405e90 deleted 96 | 4084000: cap 0: starting GC 97 | 4107000: cap 0: GC working 98 | 4358000: cap 0: GC idle 99 | 4359000: cap 0: GC done 100 | 4363000: cap 0: GC idle 101 | 4363000: cap 0: GC done 102 | 4364000: cap 0: GC idle 103 | 4364000: cap 0: GC done 104 | 4405000: cap 0: allocated on heap capset 0: 51672 total bytes till now 105 | 4406000: cap 0: finished GC 106 | 4407000: cap 0: all caps stopped for GC 107 | 4407000: cap 0: GC stats for heap capset 0: generation 1, 3320 bytes copied, 25256 bytes slop, 942080 bytes fragmentation, 1 par threads, 0 bytes max par copied, 3320 bytes total par copied, 0 bytes balanced par copied 108 | 4407000: cap 0: live data in heap capset 0: 44376 bytes 109 | 4408000: cap 0: size of heap capset 0: 2097152 bytes 110 | 12419000: ticky counter sample 4535063528: entry count: 1, 0 allocs, 0 allocd 111 | 12420000: ticky counter sample 4535063632: entry count: 1, 0 allocs, 0 allocd 112 | 12421000: ticky counter sample 4535063728: entry count: 1, 0 allocs, 0 allocd 113 | 12434000: ticky counter definition 4535063528, arity: 0, def kinds: , name: Main.main1{v r1sI} (fun), itbl: 0 114 | 12434000: ticky counter definition 4535063632, arity: 0, def kinds: , name: Main.main2{v r1sJ} (fun), itbl: 0 115 | 12434000: ticky counter definition 4535063728, arity: 0, def kinds: , name: :Main.main{v 01D} (fun), itbl: 0 116 | 12448000: cap 0: allocated on heap capset 0: 51672 total bytes till now 117 | 12451000: removed cap 0 from capset 0 118 | 12451000: removed cap 0 from capset 1 119 | 12451000: deleted cap 0 120 | 12451000: deleted capset 0 121 | 12452000: deleted capset 1 122 | 123 | -------------------------------------------------------------------------------- /test/time-prof.eventlog: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haskell/ghc-events/23a4082569ca2006186931d8f35933bfce7bb67c/test/time-prof.eventlog -------------------------------------------------------------------------------- /test/trace-binary-event.eventlog: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haskell/ghc-events/23a4082569ca2006186931d8f35933bfce7bb67c/test/trace-binary-event.eventlog -------------------------------------------------------------------------------- /test/trace-binary-event.eventlog.reference: -------------------------------------------------------------------------------- 1 | Event Types: 2 | 0: Create thread (size 4) 3 | 1: Run thread (size 4) 4 | 2: Stop thread (size 10) 5 | 3: Thread runnable (size 4) 6 | 4: Migrate thread (size 6) 7 | 8: Wakeup thread (size 6) 8 | 9: Starting GC (size 0) 9 | 10: Finished GC (size 0) 10 | 11: Request sequential GC (size 0) 11 | 12: Request parallel GC (size 0) 12 | 15: Create spark thread (size 4) 13 | 16: Log message (size variable) 14 | 18: Block marker (size 14) 15 | 19: User message (size variable) 16 | 20: GC idle (size 0) 17 | 21: GC working (size 0) 18 | 22: GC done (size 0) 19 | 25: Create capability set (size 6) 20 | 26: Delete capability set (size 4) 21 | 27: Add capability to capability set (size 6) 22 | 28: Remove capability from capability set (size 6) 23 | 29: RTS name and version (size variable) 24 | 30: Program arguments (size variable) 25 | 31: Program environment variables (size variable) 26 | 32: Process ID (size 8) 27 | 33: Parent process ID (size 8) 28 | 34: Spark counters (size 56) 29 | 35: Spark create (size 0) 30 | 36: Spark dud (size 0) 31 | 37: Spark overflow (size 0) 32 | 38: Spark run (size 0) 33 | 39: Spark steal (size 2) 34 | 40: Spark fizzle (size 0) 35 | 41: Spark GC (size 0) 36 | 43: Wall clock time (size 16) 37 | 44: Thread label (size variable) 38 | 45: Create capability (size 2) 39 | 46: Delete capability (size 2) 40 | 47: Disable capability (size 2) 41 | 48: Enable capability (size 2) 42 | 49: Total heap mem ever allocated (size 12) 43 | 50: Current heap size (size 12) 44 | 51: Current heap live data (size 12) 45 | 52: Heap static parameters (size 38) 46 | 53: GC statistics (size 58) 47 | 54: Synchronise stop-the-world GC (size 0) 48 | 55: Task create (size 18) 49 | 56: Task migrate (size 12) 50 | 57: Task delete (size 8) 51 | 58: User marker (size variable) 52 | 59: Empty event for bug #9003 (size 0) 53 | 160: Start of heap profile (size variable) 54 | 161: Cost center definition (size variable) 55 | 162: Start of heap profile sample (size 8) 56 | 163: Heap profile cost-centre sample (size variable) 57 | 164: Heap profile string sample (size variable) 58 | 181: User binary message (size variable) 59 | 60 | Events: 61 | 199116: created capset 0 of type CapsetOsProcess 62 | 199197: created capset 1 of type CapsetClockDomain 63 | 199989: created cap 0 64 | 200039: assigned cap 0 to capset 0 65 | 200099: assigned cap 0 to capset 1 66 | 205279: capset 1: wall clock time 1574408715s 234903000ns (unix epoch) 67 | 205437: capset 0: pid 49933 68 | 211311: capset 0: parent pid 44446 69 | 215666: capset 0: RTS version "GHC-8.8.1 rts_l" 70 | 219032: capset 0: args: ["./trace-binary-event","+RTS","-l-au"] 71 | 2871512: cap 0: binary message Hello, . 72 | 15687612: removed cap 0 from capset 0 73 | 15687840: removed cap 0 from capset 1 74 | 15688438: deleted cap 0 75 | 15688758: deleted capset 0 76 | 15688911: deleted capset 1 77 | 78 | -------------------------------------------------------------------------------- /test/trace-binary-nonutf.eventlog: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haskell/ghc-events/23a4082569ca2006186931d8f35933bfce7bb67c/test/trace-binary-nonutf.eventlog -------------------------------------------------------------------------------- /test/trace-binary-nonutf.eventlog.reference: -------------------------------------------------------------------------------- 1 | Event Types: 2 | 0: Create thread (size 4) 3 | 1: Run thread (size 4) 4 | 2: Stop thread (size 10) 5 | 3: Thread runnable (size 4) 6 | 4: Migrate thread (size 6) 7 | 8: Wakeup thread (size 6) 8 | 9: Starting GC (size 0) 9 | 10: Finished GC (size 0) 10 | 11: Request sequential GC (size 0) 11 | 12: Request parallel GC (size 0) 12 | 15: Create spark thread (size 4) 13 | 16: Log message (size variable) 14 | 18: Block marker (size 14) 15 | 19: User message (size variable) 16 | 20: GC idle (size 0) 17 | 21: GC working (size 0) 18 | 22: GC done (size 0) 19 | 25: Create capability set (size 6) 20 | 26: Delete capability set (size 4) 21 | 27: Add capability to capability set (size 6) 22 | 28: Remove capability from capability set (size 6) 23 | 29: RTS name and version (size variable) 24 | 30: Program arguments (size variable) 25 | 31: Program environment variables (size variable) 26 | 32: Process ID (size 8) 27 | 33: Parent process ID (size 8) 28 | 34: Spark counters (size 56) 29 | 35: Spark create (size 0) 30 | 36: Spark dud (size 0) 31 | 37: Spark overflow (size 0) 32 | 38: Spark run (size 0) 33 | 39: Spark steal (size 2) 34 | 40: Spark fizzle (size 0) 35 | 41: Spark GC (size 0) 36 | 43: Wall clock time (size 16) 37 | 44: Thread label (size variable) 38 | 45: Create capability (size 2) 39 | 46: Delete capability (size 2) 40 | 47: Disable capability (size 2) 41 | 48: Enable capability (size 2) 42 | 49: Total heap mem ever allocated (size 12) 43 | 50: Current heap size (size 12) 44 | 51: Current heap live data (size 12) 45 | 52: Heap static parameters (size 38) 46 | 53: GC statistics (size 58) 47 | 54: Synchronise stop-the-world GC (size 0) 48 | 55: Task create (size 18) 49 | 56: Task migrate (size 12) 50 | 57: Task delete (size 8) 51 | 58: User marker (size variable) 52 | 59: Empty event for bug #9003 (size 0) 53 | 160: Start of heap profile (size variable) 54 | 161: Cost center definition (size variable) 55 | 162: Start of heap profile sample (size 8) 56 | 163: Heap profile cost-centre sample (size variable) 57 | 164: Heap profile string sample (size variable) 58 | 165: End of heap profile sample (size 8) 59 | 166: Start of heap profile (biographical) sample (size 16) 60 | 167: Time profile cost-centre stack (size variable) 61 | 168: Start of a time profile (size 8) 62 | 181: User binary message (size variable) 63 | 200: Begin concurrent mark phase (size 0) 64 | 201: End concurrent mark phase (size 4) 65 | 202: Begin concurrent GC synchronisation (size 0) 66 | 203: End concurrent GC synchronisation (size 0) 67 | 204: Begin concurrent sweep (size 0) 68 | 205: End concurrent sweep (size 0) 69 | 206: Update remembered set flushed (size 2) 70 | 207: Nonmoving heap census (size 13) 71 | 72 | Events: 73 | 106238: created capset 0 of type CapsetOsProcess 74 | 106338: created capset 1 of type CapsetClockDomain 75 | 106739: created cap 0 76 | 106739: assigned cap 0 to capset 0 77 | 106839: assigned cap 0 to capset 1 78 | 107739: capset 1: wall clock time 1659558953s 302565000ns (unix epoch) 79 | 108039: capset 0: pid 3092 80 | 108739: capset 0: parent pid 3087 81 | 110040: capset 0: RTS version "GHC-9.0.2 rts_l" 82 | 110640: capset 0: args: ["/home/teo/scratch/repro-ghc-events-utf8/dist-newstyle/build/x86_64-linux/ghc-9.0.2/repro-ghc-events-utf8-0.1.0.0/x/repro/build/repro/repro","+RTS","-l"] 83 | 139850: heap stats for heap capset 0: generations 2, 0 bytes max heap size, 1048576 bytes alloc area size, 1048576 bytes mblock size, 4096 bytes block size 84 | 154856: task 0x92b3b0 created on cap 0 with OS kernel thread 3092 85 | 156356: cap 0: creating thread 1 86 | 157457: cap 0: running thread 1 87 | 166560: cap 0: stopping thread 1 (making a foreign call) 88 | 166960: cap 0: running thread 1 89 | 174963: cap 0: binary message ................................ !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~................................................................................................................................. 90 | 175163: cap 0: stopping thread 1 (thread finished) 91 | 175463: task 0x92b3b0 deleted 92 | 176063: task 0x92b3b0 created on cap 0 with OS kernel thread 3092 93 | 176163: cap 0: creating thread 2 94 | 176263: cap 0: running thread 2 95 | 198571: cap 0: stopping thread 2 (thread finished) 96 | 198671: task 0x92b3b0 deleted 97 | 200972: cap 0: starting GC 98 | 203073: cap 0: GC working 99 | 257893: cap 0: GC idle 100 | 257993: cap 0: GC done 101 | 259193: cap 0: GC idle 102 | 259193: cap 0: GC done 103 | 259493: cap 0: GC idle 104 | 259493: cap 0: GC done 105 | 261194: cap 0: allocated on heap capset 0: 63408 total bytes till now 106 | 261594: cap 0: finished GC 107 | 261694: cap 0: all caps stopped for GC 108 | 261694: cap 0: GC stats for heap capset 0: generation 1, 3216 bytes copied, 21288 bytes slop, 950272 bytes fragmentation, 1 par threads, 0 bytes max par copied, 3216 bytes total par copied, 0 bytes balanced par copied 109 | 261794: cap 0: live data in heap capset 0: 36056 bytes 110 | 261894: cap 0: size of heap capset 0: 2097152 bytes 111 | 266596: cap 0: allocated on heap capset 0: 63408 total bytes till now 112 | 266896: removed cap 0 from capset 0 113 | 266996: removed cap 0 from capset 1 114 | 266996: deleted cap 0 115 | 267096: deleted capset 0 116 | 267096: deleted capset 1 117 | 118 | -------------------------------------------------------------------------------- /test/unicode.eventlog: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/haskell/ghc-events/23a4082569ca2006186931d8f35933bfce7bb67c/test/unicode.eventlog -------------------------------------------------------------------------------- /test/unicode.eventlog.reference: -------------------------------------------------------------------------------- 1 | Event Types: 2 | 0: Create thread (size 4) 3 | 1: Run thread (size 4) 4 | 2: Stop thread (size 10) 5 | 3: Thread runnable (size 4) 6 | 4: Migrate thread (size 6) 7 | 8: Wakeup thread (size 6) 8 | 9: Starting GC (size 0) 9 | 10: Finished GC (size 0) 10 | 11: Request sequential GC (size 0) 11 | 12: Request parallel GC (size 0) 12 | 15: Create spark thread (size 4) 13 | 16: Log message (size variable) 14 | 18: Block marker (size 14) 15 | 19: User message (size variable) 16 | 20: GC idle (size 0) 17 | 21: GC working (size 0) 18 | 22: GC done (size 0) 19 | 25: Create capability set (size 6) 20 | 26: Delete capability set (size 4) 21 | 27: Add capability to capability set (size 6) 22 | 28: Remove capability from capability set (size 6) 23 | 29: RTS name and version (size variable) 24 | 30: Program arguments (size variable) 25 | 31: Program environment variables (size variable) 26 | 32: Process ID (size 8) 27 | 33: Parent process ID (size 8) 28 | 34: Spark counters (size 56) 29 | 35: Spark create (size 0) 30 | 36: Spark dud (size 0) 31 | 37: Spark overflow (size 0) 32 | 38: Spark run (size 0) 33 | 39: Spark steal (size 2) 34 | 40: Spark fizzle (size 0) 35 | 41: Spark GC (size 0) 36 | 43: Wall clock time (size 16) 37 | 44: Thread label (size variable) 38 | 45: Create capability (size 2) 39 | 46: Delete capability (size 2) 40 | 47: Disable capability (size 2) 41 | 48: Enable capability (size 2) 42 | 49: Total heap mem ever allocated (size 12) 43 | 50: Current heap size (size 12) 44 | 51: Current heap live data (size 12) 45 | 52: Heap static parameters (size 38) 46 | 53: GC statistics (size 58) 47 | 54: Synchronise stop-the-world GC (size 0) 48 | 55: Task create (size 18) 49 | 56: Task migrate (size 12) 50 | 57: Task delete (size 8) 51 | 58: User marker (size variable) 52 | 59: Empty event for bug #9003 (size 0) 53 | 160: Start of heap profile (size variable) 54 | 161: Cost center definition (size variable) 55 | 162: Start of heap profile sample (size 8) 56 | 163: Heap profile cost-centre sample (size variable) 57 | 164: Heap profile string sample (size variable) 58 | 181: User binary message (size variable) 59 | 60 | Events: 61 | 199023: created capset 0 of type CapsetOsProcess 62 | 199124: created capset 1 of type CapsetClockDomain 63 | 199641: created cap 0 64 | 199705: assigned cap 0 to capset 0 65 | 199757: assigned cap 0 to capset 1 66 | 205412: capset 1: wall clock time 1576909771s 759746000ns (unix epoch) 67 | 205582: capset 0: pid 85701 68 | 211303: capset 0: parent pid 89650 69 | 215676: capset 0: RTS version "GHC-8.8.1 rts_l" 70 | 218893: capset 0: args: ["./unicode","+RTS","-lu"] 71 | 3684143: heap stats for heap capset 0: generations 2, 0 bytes max heap size, 1048576 bytes alloc area size, 1048576 bytes mblock size, 4096 bytes block size 72 | 3790819: task 0x7fdd0ee00460 created on cap 0 with OS kernel thread 4628350 73 | 3791820: cap 0: creating thread 1 74 | 3801611: cap 0: running thread 1 75 | 3851573: cap 0: こんにちは 76 | 3852417: cap 0: stopping thread 1 (thread finished) 77 | 3853023: task 0x7fdd0ee00460 deleted 78 | 3854106: task 0x7fdd0ee00460 created on cap 0 with OS kernel thread 4628350 79 | 3854259: cap 0: creating thread 2 80 | 3854458: cap 0: running thread 2 81 | 3979871: cap 0: stopping thread 2 (thread finished) 82 | 3980191: task 0x7fdd0ee00460 deleted 83 | 3983762: cap 0: starting GC 84 | 3988279: cap 0: GC working 85 | 4151142: cap 0: GC idle 86 | 4151260: cap 0: GC done 87 | 4152813: cap 0: GC idle 88 | 4152861: cap 0: GC done 89 | 4153142: cap 0: GC idle 90 | 4153184: cap 0: GC done 91 | 4155396: cap 0: allocated on heap capset 0: 42872 total bytes till now 92 | 4156194: cap 0: finished GC 93 | 4156678: cap 0: all caps stopped for GC 94 | 4156798: cap 0: GC stats for heap capset 0: generation 1, 3216 bytes copied, 21256 bytes slop, 950272 bytes fragmentation, 1 par threads, 0 bytes max par copied, 3216 bytes total par copied, 0 bytes balanced par copied 95 | 4157147: cap 0: live data in heap capset 0: 36088 bytes 96 | 4157226: cap 0: size of heap capset 0: 2097152 bytes 97 | 14563387: cap 0: allocated on heap capset 0: 42872 total bytes till now 98 | 14566187: removed cap 0 from capset 0 99 | 14566352: removed cap 0 from capset 1 100 | 14566478: deleted cap 0 101 | 14566778: deleted capset 0 102 | 14566855: deleted capset 1 103 | 104 | --------------------------------------------------------------------------------