[new RTS flag: -V to modify the resolution of the RTS timer Ian Lynagh **20060905141545 Fixed version of an old patch by Simon Marlow. His description read: Also, now an arbitrarily short context switch interval may now be specified, as we increase the RTS ticker's resolution to match the requested context switch interval. This also applies to +RTS -i (heap profiling) and +RTS -I (the idle GC timer). +RTS -V is actually only required for increasing the resolution of the profile timer. ] { hunk ./docs/users_guide/runtime_control.xml 87 + + + Miscellaneous RTS options + + + + + RTS + option + + Sets the interval that the RTS clock ticks at. The + runtime uses a single timer signal to count ticks; this timer + signal is used to control the context switch timer () and the heap profiling + timer . Also, the + time profiler uses the RTS timer signal directly to record + time profiling samples. + + Normally, setting the option + directly is not necessary: the resolution of the RTS timer is + adjusted automatically if a short interval is requested with + the or options. + However, setting is required in order to + increase the resolution of the time profiler. + + + + hunk ./docs/users_guide/using.xml 1527 - switches occur every 20ms. Note that GHC's internal timer ticks - every 20ms, and the context switch timer is always a multiple of - this timer, so 20ms is the maximum granularity available for timed - context switches. + switches occur every 20ms. hunk ./includes/Cmm.h 515 - -#define TICK_MILLISECS (1000/TICK_FREQUENCY) /* ms per tick */ hunk ./includes/RtsFlags.h 45 - int idleGCDelayTicks; /* in milliseconds */ + int idleGCDelayTime; /* in milliseconds */ hunk ./includes/RtsFlags.h 115 +struct MISC_FLAGS { + int tickInterval; /* in milliseconds */ +}; + hunk ./includes/RtsFlags.h 307 + struct MISC_FLAGS MiscFlags; hunk ./includes/mkDerivedConstants.c 377 + struct_field_("RtsFlags_MiscFlags_tickInterval", + RTS_FLAGS, MiscFlags.tickInterval); hunk ./rts/PrimOps.cmm 1978 - time = foreign "C" getourtimeofday(); - target = (R1 / (TICK_MILLISECS*1000)) + time; + time = foreign "C" getourtimeofday() [R1]; + target = (R1 / (TO_W_(RtsFlags_MiscFlags_tickInterval(RtsFlags))*1000)) + time; hunk ./rts/Profiling.c 280 - fprintf(prof_file, "\"%d ms\"\n", TICK_MILLISECS); + fprintf(prof_file, "\"%d ms\"\n", RtsFlags.MiscFlags.tickInterval); hunk ./rts/Profiling.c 735 - total_prof_ticks / (StgFloat) TICK_FREQUENCY, - total_prof_ticks, TICK_MILLISECS); + (double) total_prof_ticks * + (double) RtsFlags.MiscFlags.tickInterval / 1000, + (unsigned long) total_prof_ticks, + (int) RtsFlags.MiscFlags.tickInterval); hunk ./rts/Proftimer.c 59 - - RtsFlags.ProfFlags.profileIntervalTicks = - RtsFlags.ProfFlags.profileInterval / TICK_MILLISECS; hunk ./rts/RtsFlags.c 15 -#include "Timer.h" /* CS_MIN_MILLISECS */ hunk ./rts/RtsFlags.c 152 - RtsFlags.GcFlags.idleGCDelayTicks = 300 / TICK_MILLISECS; /* ticks */ + RtsFlags.GcFlags.idleGCDelayTime = 300; /* millisecs */ hunk ./rts/RtsFlags.c 193 - RtsFlags.ConcFlags.ctxtSwitchTime = CS_MIN_MILLISECS; /* In milliseconds */ + RtsFlags.MiscFlags.tickInterval = 50; /* In milliseconds */ + RtsFlags.ConcFlags.ctxtSwitchTime = 50; /* In milliseconds */ hunk ./rts/RtsFlags.c 793 - /* Convert to ticks */ + /* Convert to millisecs */ hunk ./rts/RtsFlags.c 795 - if (cst > 0 && cst < TICK_MILLISECS) { - cst = TICK_MILLISECS; - } else { - cst = cst / TICK_MILLISECS; - } - RtsFlags.GcFlags.idleGCDelayTicks = cst; + RtsFlags.GcFlags.idleGCDelayTime = cst; hunk ./rts/RtsFlags.c 991 - cst = (cst / CS_MIN_MILLISECS) * CS_MIN_MILLISECS; - if (cst != 0 && cst < CS_MIN_MILLISECS) - cst = CS_MIN_MILLISECS; - hunk ./rts/RtsFlags.c 1005 - cst = (cst / CS_MIN_MILLISECS) * CS_MIN_MILLISECS; - if (cst != 0 && cst < CS_MIN_MILLISECS) - cst = CS_MIN_MILLISECS; - hunk ./rts/RtsFlags.c 1009 + case 'V': /* master tick interval */ + if (rts_argv[arg][2] == '\0') { + // turns off ticks completely + RtsFlags.MiscFlags.tickInterval = 0; + } else { + I_ cst; /* tmp */ + + /* Convert to milliseconds */ + cst = (I_) ((atof(rts_argv[arg]+2) * 1000)); + RtsFlags.MiscFlags.tickInterval = cst; + } + break; + hunk ./rts/RtsFlags.c 1156 + + // Determine what tick interval we should use for the RTS timer + // by taking the shortest of the various intervals that we need to + // monitor. + if (RtsFlags.MiscFlags.tickInterval <= 0) { + RtsFlags.MiscFlags.tickInterval = 50; + } + + if (RtsFlags.ConcFlags.ctxtSwitchTime > 0) { + RtsFlags.MiscFlags.tickInterval = + stg_min(RtsFlags.ConcFlags.ctxtSwitchTime, + RtsFlags.MiscFlags.tickInterval); + } + + if (RtsFlags.GcFlags.idleGCDelayTime > 0) { + RtsFlags.MiscFlags.tickInterval = + stg_min(RtsFlags.GcFlags.idleGCDelayTime, + RtsFlags.MiscFlags.tickInterval); + } + +#ifdef PROFILING + if (RtsFlags.ProfFlags.profileInterval > 0) { + RtsFlags.MiscFlags.tickInterval = + stg_min(RtsFlags.ProfFlags.profileInterval, + RtsFlags.MiscFlags.tickInterval); + } +#endif + + if (RtsFlags.ConcFlags.ctxtSwitchTime > 0) { + RtsFlags.ConcFlags.ctxtSwitchTicks = + RtsFlags.ConcFlags.ctxtSwitchTime / + RtsFlags.MiscFlags.tickInterval; + } else { + RtsFlags.ConcFlags.ctxtSwitchTicks = 0; + } + +#ifdef PROFILING + RtsFlags.ProfFlags.profileIntervalTicks = + RtsFlags.ProfFlags.profileInterval / RtsFlags.MiscFlags.tickInterval; +#endif + hunk ./rts/RtsStartup.c 213 - startTimer(TICK_MILLISECS); + startTimer(); hunk ./rts/Schedule.c 2512 - RtsFlags.ConcFlags.ctxtSwitchTicks = - RtsFlags.ConcFlags.ctxtSwitchTime / TICK_MILLISECS; - hunk ./rts/Timer.c 57 - * If we've been inactive for idleGCDelayTicks (set by +RTS + * If we've been inactive for idleGCDelayTime (set by +RTS hunk ./rts/Timer.c 64 - ticks_to_gc = RtsFlags.GcFlags.idleGCDelayTicks; + ticks_to_gc = RtsFlags.GcFlags.idleGCDelayTime / + RtsFlags.MiscFlags.tickInterval; hunk ./rts/Timer.c 71 - ticks_to_gc = RtsFlags.GcFlags.idleGCDelayTicks; + ticks_to_gc = RtsFlags.GcFlags.idleGCDelayTime / + RtsFlags.MiscFlags.tickInterval; hunk ./rts/Timer.c 86 -startTimer(nat ms) +startTimer(void) hunk ./rts/Timer.c 92 - return startTicker(ms, handle_tick); + return startTicker(RtsFlags.MiscFlags.tickInterval, handle_tick); hunk ./rts/Timer.c 96 -stopTimer() +stopTimer(void) hunk ./rts/Timer.h 3 - * (c) The GHC Team, 1995-2005 + * (c) The GHC Team, 1995-2006 hunk ./rts/Timer.h 12 -# define TICK_MILLISECS (1000/TICK_FREQUENCY) /* ms per tick */ - -/* Context switch timing constants. Context switches happen after a - * whole number of ticks, the default being every tick. - */ -#define CS_MIN_MILLISECS TICK_MILLISECS /* milliseconds per slice */ - hunk ./rts/Timer.h 14 -extern int startTimer(nat ms); +extern int startTimer(void); hunk ./rts/posix/Itimer.c 224 - return ((lnat)tv.tv_sec * TICK_FREQUENCY + - (lnat)tv.tv_usec * TICK_FREQUENCY / 1000000); + return ((lnat)tv.tv_sec * 1000 / RtsFlags.MiscFlags.tickInterval + + (lnat)tv.tv_usec / (RtsFlags.MiscFlags.tickInterval * 1000)); hunk ./rts/posix/Select.c 129 - * TICK_MILLISECS * 1000; + * RtsFlags.MiscFlags.tickInterval * 1000; }