On 1 December 2022, members of Well-Typed provided a video guide to profiling memory usage of Haskell applications with tools eventlog2html
and ghc-debug
. I wondered if they would work on Windows 11.
Building eventlog2html
I could build the executable provided by package eventlog2html-0.11.0
with a project level configuration file:
1 2 3 4 5 |
snapshot: lts-22.33 # GHC 9.6.6 extra-deps: # Required because of https://github.com/mpickering/eventlog2html/issues/186 - blaze-html-0.9.1.2 |
Update: Package eventlog2html-0.11.1
, released 17 August 2024, is even simpler as the issue is fixed:
1 |
snapshot: lts-22.33 # GHC 9.6.6 |
Applying eventlog2html
The Stack executable is built with GHC option -rtsopts
, which is equivalent to -rtsopts=all
. So, using Stack to build stack
, after stack purge
, with stack build +RTS -s -l -hT
yields:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
5,612,086,200 bytes allocated in the heap 2,422,745,976 bytes copied during GC 14,621,200 bytes maximum residency (228 sample(s)) 247,280 bytes maximum slop 45 MiB total memory in use (0 MiB lost due to fragmentation) Tot time (elapsed) Avg pause Max pause Gen 0 1296 colls, 0 par 0.078s 0.122s 0.0001s 0.0021s Gen 1 228 colls, 0 par 1.031s 3.352s 0.0147s 0.0331s TASKS: 6 (1 bound, 5 peak workers (5 total), using -N1) SPARKS: 0 (0 converted, 0 overflowed, 0 dud, 0 GC'd, 0 fizzled) INIT time 0.000s ( 0.015s elapsed) MUT time 1.562s (153.021s elapsed) GC time 1.109s ( 3.474s elapsed) EXIT time 0.000s ( 0.003s elapsed) Total time 2.672s (156.513s elapsed) Alloc rate 3,591,735,168 bytes per MUT second Productivity 58.5% of total user, 97.8% of total elapsed |
and eventlog2html stack.eventlog
and start stack.eventlog.html
yields a visualization of the heap by type of closure like:
Building ghc-debug-brick
I could build the executable provided by package ghc-debug-brick-0.6.0.0
with a project level configuration file:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
snapshot: lts-22.33 # GHC 9.6.6 extra-deps: - aeson-2.2.3.0@sha256:ef66d29cb5b8d87a144838dfd5745bb3ac6b8fc4b142129fac84814baee13660,6351 - byteunits-0.4.0.3@sha256:69aba5772ba470a1242e545f3ff0fe4432cf271e1decd1bdeafc07b4e64472b5,1378 - character-ps-0.1@sha256:b38ed1c07ae49e7461e44ca1d00c9ca24d1dcb008424ccd919916f92fd48d9fe,1315 - contra-tracer-0.2.0.0@sha256:7e1df39934fb0ecf4533196c819946455ec377fbc169b819be151906db244fc2,905 - dom-lt-0.2.3@sha256:1df9402e21e97de0da74fdf2a9f8c96ab8a710c602eb6d22ac8e9c274db51090,1938 - ghc-debug-client-0.6.0.0@sha256:24e8d7474e918c17ab7789ef201a8f2561b8974b79ab3b41cb6a866478edaa34,2975 - ghc-debug-common-0.6.0.0@sha256:8008bb721ff72923fd1fe0f7042c521c0ef393be24a501ca605b1574d0194f51,1846 - ghc-debug-convention-0.6.0.0@sha256:be9e51bc9096cf966a508b036b2bfe829dc32c166eccc4ce442b56eb01fc2b1f,635 - hashable-1.4.7.0@sha256:573f3ab242f75465a0d67ce9d84202650a1606575e6dbd6d31ffcf4767a9a379,6629 - parsec-3.1.17.0@sha256:8407cbd428d7f640a0fff8891bd2f7aca13cebe70a5e654856f8abec9a648b56,5149 - text-2.1.1@sha256:78c3fb91055d0607a80453327f087b9dc82168d41d0dca3ff410d21033b5e87d,10653 - vty-windows-0.2.0.3@sha256:0c010b1086a725046a8bb08bb1e6bfdfdb3cfe1c72d6fa77c37306ef9ec774d8,2844 |
stack install
built the executable ghc-debug-brick
and put it on the PATH
.
An example debugee
The application to be debugged is known as a debugee. It has to depend on package ghc-debug-stub
and that package, and one of its dependencies, is not included in Stackage snapshots. So, I added to package.yaml
as a dependency and used the following project-level configuration:
1 2 3 4 5 |
snapshot: lts-22.33 # GHC 9.6.6 extra-deps: - ghc-debug-convention-0.6.0.0@sha256:be9e51bc9096cf966a508b036b2bfe829dc32c166eccc4ce442b56eb01fc2b1f,635 - ghc-debug-stub-0.6.0.0@sha256:04d53a8fe507011e30a5ecf21fba97f8e7015c2f59396b191a4b8c0323d53df6,1601 |
However, the building of package ghc-debug-stub-0.6.0.0
failed with:
1 2 3 4 5 6 7 8 9 10 11 |
ghc-debug-stub> [1 of 1] Compiling GHC.Debug.Stub ghc-debug-stub> ghc-debug-stub> cbits\stub.cpp:8:10: error: ghc-debug-stub> fatal error: 'sys/socket.h' file not found ghc-debug-stub> | ghc-debug-stub> 8 | #include <sys/socket.h> ghc-debug-stub> | ^ ghc-debug-stub> #include <sys/socket.h> ghc-debug-stub> ^~~~~~~~~~~~~~ ghc-debug-stub> 1 error generated. ghc-debug-stub> `clang++.exe' failed in phase `C++ Compiler'. (Exit code: 1) |
A StackOverflow question and answer implied that this could be problematic on Windows. Perhaps this was a dead end.
I identified that MSYS2 package msys2-runtime-devel
(MSYS2 header and libraries) provided /usr/include/sys/socket.h
, so I tried stack exec -- pacman -S msys2-runtime-devel
.
Now the failure is (extracts):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
ghc-debug-stub> [1 of 1] Compiling GHC.Debug.Stub ghc-debug-stub> ghc-debug-stub> In file included from cbits\stub.cpp:5:0: error: ghc-debug-stub> In file included from D:\sr\programs\x86_64-windows\ghc-9.6.6\lib\..\mingw\include\c++\v1\iostream:37:0: error: ghc-debug-stub> In file included from D:\sr\programs\x86_64-windows\ghc-9.6.6\lib\..\mingw\include\c++\v1\ios:214:0: error: ghc-debug-stub> In file included from D:\sr\programs\x86_64-windows\ghc-9.6.6\lib\..\mingw\include\c++\v1\__locale:18:0: error: ghc-debug-stub> In file included from D:\sr\programs\x86_64-windows\ghc-9.6.6\lib\..\mingw\include\c++\v1\memory:808:0: error: ghc-debug-stub> In file included from D:\sr\programs\x86_64-windows\ghc-9.6.6\lib\..\mingw\include\c++\v1\__functional_base:23:0: error: ghc-debug-stub> D:\sr\programs\x86_64-windows\ghc-9.6.6\lib\..\mingw\include\c++\v1\new:324:12: error: ghc-debug-stub> error: no member named '_aligned_malloc' in the global namespace; did you mean 'aligned_alloc'? ghc-debug-stub> return ::_aligned_malloc(__size, __alignment); ghc-debug-stub> ~~^ ghc-debug-stub> | ghc-debug-stub> 324 | return ::_aligned_malloc(__size, __alignment); ghc-debug-stub> | ^ ghc-debug-stub> ghc-debug-stub> D:\sr\programs\x86_64-windows\msys2-20230526\usr\include\stdlib.h:334:8: error: ghc-debug-stub> note: 'aligned_alloc' declared here ghc-debug-stub> | ghc-debug-stub> 334 | void * aligned_alloc(size_t, size_t) __malloc_like __alloc_align(1) ghc-debug-stub> | ^ ghc-debug-stub> void * aligned_alloc(size_t, size_t) __malloc_like __alloc_align(1) ghc-debug-stub> ^ |