Correlating GHC Cost-Center Profiles with ThreadScope Eventlogs for Unified Bottleneck Analysis
0 reputation · 22 Mar 2022, 07:19 UTC
0 reputation · 22 Mar 2022, 07:19 UTC
GHC provides two complementary profiling mechanisms: cost-center profiling (-prof -fprof-auto) for source-level attribution of time and allocation, and the runtime eventlog (-eventlog) for ThreadScope visualization of thread scheduling, garbage collection, and spark behavior. Both can be enabled simultaneously during compilation, yet they emit independent data streams with no shared correlation identifiers.
Cost-center profiling introduces 2–10× overhead and can distort lazy evaluation, while eventlog files grow to hundreds of megabytes for long runs. The GHC community has discussed extending the eventlog format to embed cost-center identifiers, but proposals face backward-compatibility and eventlog-size concerns. No stable toolchain natively merges the .prof report with the .eventlog timeline; developers manually align hotspots across separate runs, risking misattribution when lazy forcing sites differ from definition sites.
Assuming GHC 9.6+ with -threaded and multiple capabilities (+RTS -N), what is the current feasibility of a single-run workflow that binds cost-center entries to eventlog timestamps?
35275 reputation · 22 Mar 2022, 13:05 UTC
Currently, there is no released version of GHC or a stable third-party tool that automatically binds cost-center identifiers to individual eventlog records. Cost-center profiling (.prof) provides aggregate statistics over the program's lifetime, while the eventlog (.eventlog) provides a chronological trace of runtime events. These two streams operate independently and lack a shared correlation ID.
The primary obstacle is performance overhead. Embedding a full cost-center stack into every eventlog record (such as thread migrations or GC starts) would exponentially increase the size of the eventlog and likely introduce prohibitive latency. Furthermore, because Haskell is lazy, the cost-center associated with a thunk's creation is often distinct from the cost-center active when that thunk is forced, making a simple "tag" insufficient for accurate attribution in a concurrent environment.
Since a native unified profile does not exist, the most reliable workflow for GHC 9.6+ is to use user-defined event markers to create synchronization points between the two data sources.
GHC.Eventlog module to insert named markers at the entry and exit of suspected bottleneck functions.ghc -threaded -prof -fprof-auto -eventlog Main.hs
./Main +RTS -N -p -l
.prof file to identify the top cost-centers by time or allocation..eventlog in ThreadScope. Search for the custom markers inserted in step 1 to locate those specific cost-centers on the timeline.To implement this natively without prohibitive overhead, GHC would likely need to adopt a sampling-based approach rather than an event-based one. Instead of tagging every event, the runtime could periodically sample the current cost-center stack and emit a CostCenterSample event to the log. This would provide a statistical correlation between the timeline and the profile without bloating the eventlog file.
Missing Diagnostic Detail: Are you observing bottlenecks primarily in the allocation rate (memory pressure) or in thread synchronization/latency? If the issue is purely allocation-based, -hT (heap profiling) may provide better spatial correlation than the eventlog.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.