From d89deeba47ce04a5198a71fa4cbc203fe2c90794 Mon Sep 17 00:00:00 2001 From: Matthew Pickering Date: Mon, 7 Dec 2020 13:19:28 +0000 Subject: Profiling: Allow heap profiling to be controlled dynamically. This patch exposes three new functions in `GHC.Profiling` which allow heap profiling to be enabled and disabled dynamically. 1. startHeapProfTimer - Starts heap profiling with the given RTS options 2. stopHeapProfTimer - Stops heap profiling 3. requestHeapCensus - Perform a heap census on the next context switch, regardless of whether the timer is enabled or not. --- rts/Proftimer.c | 45 ++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 40 insertions(+), 5 deletions(-) (limited to 'rts/Proftimer.c') diff --git a/rts/Proftimer.c b/rts/Proftimer.c index 00b92a227d..29abb62a8e 100644 --- a/rts/Proftimer.c +++ b/rts/Proftimer.c @@ -18,7 +18,12 @@ static bool do_prof_ticks = false; // enable profiling ticks #endif -static bool do_heap_prof_ticks = false; // enable heap profiling ticks +static bool do_heap_prof_ticks = false; // Whether the timer is currently ticking down +static bool heap_prof_timer_active = false; // Whether the timer is enabled at all + +/* The heap_prof_timer_active flag controls whether heap profiling is enabled +at all, once it is enabled, the `do_heap_prof_ticks` flag controls whether the +counter is currently counting down. This is paused, for example, in Schedule.c. */ // Sampling of Ticky-Ticky profiler to eventlog #if defined(TICKY_TICKY) && defined(TRACING) @@ -51,18 +56,43 @@ startProfTimer( void ) void stopHeapProfTimer( void ) { - RELAXED_STORE(&do_heap_prof_ticks, false); + if (RtsFlags.ProfFlags.doHeapProfile){ + RELAXED_STORE(&heap_prof_timer_active, false); + pauseHeapProfTimer(); + } } void startHeapProfTimer( void ) { + if (RtsFlags.ProfFlags.doHeapProfile){ + RELAXED_STORE(&heap_prof_timer_active, true); + resumeHeapProfTimer(); + } +} + +void +pauseHeapProfTimer ( void ) { + RELAXED_STORE(&do_heap_prof_ticks, false); +} + + +void +resumeHeapProfTimer ( void ) { if (RtsFlags.ProfFlags.doHeapProfile && RtsFlags.ProfFlags.heapProfileIntervalTicks > 0) { - do_heap_prof_ticks = true; + RELAXED_STORE(&do_heap_prof_ticks, true); } } +void +requestHeapCensus( void ){ + // If no profiling mode is passed then just ignore the call. + if (RtsFlags.ProfFlags.doHeapProfile){ + RELAXED_STORE(&performHeapProfile, true); + } +} + void initProfTimer( void ) { @@ -70,7 +100,12 @@ initProfTimer( void ) ticks_to_heap_profile = RtsFlags.ProfFlags.heapProfileIntervalTicks; - startHeapProfTimer(); + /* This might look a bit strange but the heap profile timer can + be toggled on/off from within Haskell by calling the startHeapProf + function from within Haskell */ + if (RtsFlags.ProfFlags.startHeapProfileAtStartup){ + startHeapProfTimer(); + } } uint32_t total_ticks = 0; @@ -99,7 +134,7 @@ handleProfTick(void) } #endif - if (RELAXED_LOAD(&do_heap_prof_ticks)) { + if (RELAXED_LOAD(&do_heap_prof_ticks) && RELAXED_LOAD(&heap_prof_timer_active)) { ticks_to_heap_profile--; if (ticks_to_heap_profile <= 0) { ticks_to_heap_profile = RtsFlags.ProfFlags.heapProfileIntervalTicks; -- cgit v1.2.1