[Git][ghc/ghc][master] Add a cumulative gc_sync_elapsed_ns counter to GHC.Internal.Stats
Marge Bot pushed to branch master at Glasgow Haskell Compiler / GHC Commits: 02e68a86 by Brandon Simmons at 2026-03-13T15:13:19-04:00 Add a cumulative gc_sync_elapsed_ns counter to GHC.Internal.Stats This makes it possible to get an accurate view of time spent in sync phase when using prometheus-style sampling. Previously this was only available for the most recent GC. This intentionally leaves GHC.Stats API unchanged since it is marked as deprecated, and API changes there require CLC approval. Fixes #26944 - - - - - 7 changed files: - libraries/base/src/GHC/Stats.hs - libraries/ghc-internal/CHANGELOG.md - libraries/ghc-internal/src/GHC/Internal/Stats.hsc - rts/Stats.c - rts/include/RtsAPI.h - testsuite/tests/interface-stability/ghc-experimental-exports.stdout - testsuite/tests/interface-stability/ghc-experimental-exports.stdout-mingw32 Changes: ===================================== libraries/base/src/GHC/Stats.hs ===================================== @@ -26,6 +26,7 @@ -- proposal -- #289](https://github.com/haskell/core-libraries-committee/issues/289). These -- declarations are now instead available from the @ghc-experimental@ package. +-- @ghc-experimental@ contains additional metrics not added to the API here. module GHC.Stats ( -- * Runtime statistics ===================================== libraries/ghc-internal/CHANGELOG.md ===================================== @@ -3,6 +3,7 @@ ## 9.1401.0 -- yyyy-mm-dd * Introduce `dataToCodeQ` and `liftDataTyped`, typed variants of `dataToExpQ` and `liftData` respectively. +* Add new `gc_sync_elapsed_ns` counter to GHC.Internal.Stats ## 9.1001.0 -- 2024-05-01 ===================================== libraries/ghc-internal/src/GHC/Internal/Stats.hsc ===================================== @@ -111,6 +111,8 @@ data RTSStats = RTSStats { , gc_cpu_ns :: RtsTime -- | Total elapsed time used by the GC , gc_elapsed_ns :: RtsTime + -- | Total elapsed time used during GC synchronization + , gc_sync_elapsed_ns :: RtsTime -- | Total CPU time (at the previous GC) , cpu_ns :: RtsTime -- | Total elapsed time (at the previous GC) @@ -234,6 +236,7 @@ getRTSStats = do mutator_elapsed_ns <- (# peek RTSStats, mutator_elapsed_ns) p gc_cpu_ns <- (# peek RTSStats, gc_cpu_ns) p gc_elapsed_ns <- (# peek RTSStats, gc_elapsed_ns) p + gc_sync_elapsed_ns <- (# peek RTSStats, gc_sync_elapsed_ns) p cpu_ns <- (# peek RTSStats, cpu_ns) p elapsed_ns <- (# peek RTSStats, elapsed_ns) p nonmoving_gc_sync_cpu_ns <- (# peek RTSStats, nonmoving_gc_sync_cpu_ns) p ===================================== rts/Stats.c ===================================== @@ -163,6 +163,7 @@ initStats0(void) .mutator_elapsed_ns = 0, .gc_cpu_ns = 0, .gc_elapsed_ns = 0, + .gc_sync_elapsed_ns = 0, .cpu_ns = 0, .elapsed_ns = 0, .nonmoving_gc_cpu_ns = 0, @@ -288,6 +289,8 @@ stat_endExit(void) RELEASE_LOCK(&stats_mutex); } +// This is only called in the threaded RTS. On non-threaded RTS `gc_sync_start_elapsed` +// is conditonally set in `stat_startGC`. void stat_startGCSync (gc_thread *gct) { @@ -433,6 +436,11 @@ stat_startGC (Capability *cap, gc_thread *gct) } gct->gc_start_elapsed = getProcessElapsedTime(); +#if !defined(THREADED_RTS) + // Non-threaded RTS has no sync phase. Initializing in this way makes the + // calculated statistics correctly read zero. + gct->gc_sync_start_elapsed = gct->gc_start_elapsed; +#endif // Post EVENT_GC_START with the same timestamp as used for stats // (though converted from Time=StgInt64 to EventTimestamp=StgWord64). @@ -548,6 +556,7 @@ stat_endGC (Capability *cap, gc_thread *initiating_gct, W_ live, W_ copied, W_ s } stats.gc_cpu_ns += stats.gc.cpu_ns; stats.gc_elapsed_ns += stats.gc.elapsed_ns; + stats.gc_sync_elapsed_ns += stats.gc.sync_elapsed_ns; if (gen == RtsFlags.GcFlags.generations-1) { // major GC? stats.major_gcs++; @@ -915,6 +924,8 @@ static void report_summary(const RTSSummaryStats* sum) statsPrintf(" GC time %7.3fs (%7.3fs elapsed)\n", TimeToSecondsDbl(stats.gc_cpu_ns), TimeToSecondsDbl(stats.gc_elapsed_ns)); + statsPrintf(" GC SYNC time (%7.3fs elapsed)\n", + TimeToSecondsDbl(stats.gc_sync_elapsed_ns)); if (RtsFlags.GcFlags.useNonmoving) { statsPrintf( " CONC GC time %7.3fs (%7.3fs elapsed)\n", @@ -1069,6 +1080,7 @@ static void report_machine_readable (const RTSSummaryStats * sum) TimeToSecondsDbl(stats.mutator_elapsed_ns)); MR_STAT("GC_cpu_seconds", "f", TimeToSecondsDbl(stats.gc_cpu_ns)); MR_STAT("GC_wall_seconds", "f", TimeToSecondsDbl(stats.gc_elapsed_ns)); + MR_STAT("GC_sync_wall_seconds", "f", TimeToSecondsDbl(stats.gc_sync_elapsed_ns)); // end backward compatibility ===================================== rts/include/RtsAPI.h ===================================== @@ -240,6 +240,8 @@ typedef struct _RTSStats { Time gc_cpu_ns; // Total elapsed time used by the GC Time gc_elapsed_ns; + // Total elapsed time used during GC synchronization + Time gc_sync_elapsed_ns; // Total CPU time (at the previous GC) Time cpu_ns; // Total elapsed time (at the previous GC) ===================================== testsuite/tests/interface-stability/ghc-experimental-exports.stdout ===================================== @@ -6587,6 +6587,7 @@ module GHC.Stats.Experimental where mutator_elapsed_ns :: RtsTime, gc_cpu_ns :: RtsTime, gc_elapsed_ns :: RtsTime, + gc_sync_elapsed_ns :: RtsTime, cpu_ns :: RtsTime, elapsed_ns :: RtsTime, nonmoving_gc_sync_cpu_ns :: RtsTime, ===================================== testsuite/tests/interface-stability/ghc-experimental-exports.stdout-mingw32 ===================================== @@ -6590,6 +6590,7 @@ module GHC.Stats.Experimental where mutator_elapsed_ns :: RtsTime, gc_cpu_ns :: RtsTime, gc_elapsed_ns :: RtsTime, + gc_sync_elapsed_ns :: RtsTime, cpu_ns :: RtsTime, elapsed_ns :: RtsTime, nonmoving_gc_sync_cpu_ns :: RtsTime, View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/02e68a86e438edb315ba8622c58733d8... -- View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/02e68a86e438edb315ba8622c58733d8... You're receiving this email because of your account on gitlab.haskell.org.
participants (1)
-
Marge Bot (@marge-bot)