mirror of
git://git.sv.gnu.org/emacs.git
synced 2026-04-27 16:51:06 -07:00
Implement pause time control.
Copied from Perforce Change: 189921 ServerID: perforce.ravenbrook.com
This commit is contained in:
parent
66e0d30340
commit
459a9f775d
8 changed files with 53 additions and 34 deletions
|
|
@ -411,10 +411,10 @@
|
|||
* documentation changes. */
|
||||
#define ARENA_DEFAULT_SPARE_COMMIT_LIMIT ((Size)10uL*1024uL*1024uL)
|
||||
|
||||
/* ARENA_DEFAULT_PAUSE_TIME is the maximum time (in seconds) that the
|
||||
* arena that operations within the arena may pause the mutator for. */
|
||||
/* ARENA_DEFAULT_PAUSE_TIME is the maximum time (in seconds) that
|
||||
* operations within the arena may pause the mutator for. */
|
||||
|
||||
#define ARENA_DEFAULT_PAUSE_TIME (0.0)
|
||||
#define ARENA_DEFAULT_PAUSE_TIME (0.1)
|
||||
|
||||
#define ARENA_DEFAULT_ZONED TRUE
|
||||
|
||||
|
|
|
|||
|
|
@ -55,6 +55,7 @@ static size_t arena_size = 256ul * 1024 * 1024; /* arena size */
|
|||
static size_t arena_grain_size = 1; /* arena grain size */
|
||||
static unsigned pinleaf = FALSE; /* are leaf objects pinned at start */
|
||||
static mps_bool_t zoned = TRUE; /* arena allocates using zones */
|
||||
static double pause_time = ARENA_DEFAULT_PAUSE_TIME; /* maximum pause time */
|
||||
|
||||
typedef struct gcthread_s *gcthread_t;
|
||||
|
||||
|
|
@ -235,6 +236,7 @@ static void arena_setup(gcthread_fn_t fn,
|
|||
MPS_ARGS_ADD(args, MPS_KEY_ARENA_SIZE, arena_size);
|
||||
MPS_ARGS_ADD(args, MPS_KEY_ARENA_GRAIN_SIZE, arena_grain_size);
|
||||
MPS_ARGS_ADD(args, MPS_KEY_ARENA_ZONED, zoned);
|
||||
MPS_ARGS_ADD(args, MPS_KEY_PAUSE_TIME, pause_time);
|
||||
RESMUST(mps_arena_create_k(&arena, mps_arena_class_vm(), args));
|
||||
} MPS_ARGS_END(args);
|
||||
RESMUST(dylan_fmt(&format, arena));
|
||||
|
|
@ -278,6 +280,7 @@ static struct option longopts[] = {
|
|||
{"pin-leaf", no_argument, NULL, 'l'},
|
||||
{"seed", required_argument, NULL, 'x'},
|
||||
{"arena-unzoned", no_argument, NULL, 'z'},
|
||||
{"pause-time", required_argument, NULL, 'P'},
|
||||
{NULL, 0, NULL, 0 }
|
||||
};
|
||||
|
||||
|
|
@ -307,7 +310,8 @@ int main(int argc, char *argv[]) {
|
|||
}
|
||||
putchar('\n');
|
||||
|
||||
while ((ch = getopt_long(argc, argv, "ht:i:p:g:m:a:w:d:r:u:lx:z", longopts, NULL)) != -1)
|
||||
while ((ch = getopt_long(argc, argv, "ht:i:p:g:m:a:w:d:r:u:lx:zP:",
|
||||
longopts, NULL)) != -1)
|
||||
switch (ch) {
|
||||
case 't':
|
||||
nthreads = (unsigned)strtoul(optarg, NULL, 10);
|
||||
|
|
@ -396,6 +400,9 @@ int main(int argc, char *argv[]) {
|
|||
case 'z':
|
||||
zoned = FALSE;
|
||||
break;
|
||||
case 'P':
|
||||
pause_time = strtod(optarg, NULL);
|
||||
break;
|
||||
default:
|
||||
/* This is printed in parts to keep within the 509 character
|
||||
limit for string literals in portable standard C. */
|
||||
|
|
@ -441,9 +448,12 @@ int main(int argc, char *argv[]) {
|
|||
fprintf(stderr,
|
||||
" -z, --arena-unzoned\n"
|
||||
" Disable zoned allocation in the arena\n"
|
||||
" -P t, --pause-time\n"
|
||||
" Maximum pause time in seconds (default %f) \n"
|
||||
"Tests:\n"
|
||||
" amc pool class AMC\n"
|
||||
" ams pool class AMS\n");
|
||||
" ams pool class AMS\n",
|
||||
pause_time);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
argc -= optind;
|
||||
|
|
|
|||
|
|
@ -735,15 +735,13 @@ void (ArenaPoll)(Globals globals)
|
|||
if (moreWork) {
|
||||
workWasDone = TRUE;
|
||||
}
|
||||
} while (PolicyPollAgain(arena, moreWork, tracedWork));
|
||||
} while (PolicyPollAgain(arena, start, moreWork, tracedWork));
|
||||
|
||||
/* Don't count time spent checking for work, if there was no work to do. */
|
||||
if (workWasDone) {
|
||||
ArenaAccumulateTime(arena, start);
|
||||
}
|
||||
|
||||
AVER(!PolicyPoll(arena));
|
||||
|
||||
EVENT3(ArenaPoll, arena, start, BOOLOF(workWasDone));
|
||||
|
||||
globals->insidePoll = FALSE;
|
||||
|
|
|
|||
|
|
@ -670,7 +670,7 @@ extern Bool PolicyShouldCollectWorld(Arena arena, double availableTime,
|
|||
Clock now, Clock clocks_per_sec);
|
||||
extern Bool PolicyStartTrace(Trace *traceReturn, Arena arena);
|
||||
extern Bool PolicyPoll(Arena arena);
|
||||
extern Bool PolicyPollAgain(Arena arena, Bool moreWork, Work tracedWork);
|
||||
extern Bool PolicyPollAgain(Arena arena, Clock start, Bool moreWork, Work tracedWork);
|
||||
|
||||
|
||||
/* Locus interface */
|
||||
|
|
|
|||
|
|
@ -367,28 +367,33 @@ Bool PolicyPoll(Arena arena)
|
|||
* moreWork and tracedWork are the results of the last call to TracePoll.
|
||||
*/
|
||||
|
||||
Bool PolicyPollAgain(Arena arena, Bool moreWork, Work tracedWork)
|
||||
Bool PolicyPollAgain(Arena arena, Clock start, Bool moreWork, Work tracedWork)
|
||||
{
|
||||
Globals globals;
|
||||
double nextPollThreshold;
|
||||
|
||||
AVERT(Arena, arena);
|
||||
globals = ArenaGlobals(arena);
|
||||
UNUSED(tracedWork);
|
||||
|
||||
if (!moreWork) {
|
||||
/* No more work to do. Sleep until NOW + a bit. */
|
||||
nextPollThreshold = globals->fillMutatorSize + ArenaPollALLOCTIME;
|
||||
|
||||
/* Is there more work to do and more time to do it in? */
|
||||
if ((moreWork || ArenaEmergency(arena))
|
||||
&& ClockNow() < start + ArenaPauseTime(arena))
|
||||
{
|
||||
return TRUE;
|
||||
} else {
|
||||
/* We did one quantum of work; consume one unit of 'time'. */
|
||||
nextPollThreshold = globals->pollThreshold + ArenaPollALLOCTIME;
|
||||
Globals globals = ArenaGlobals(arena);
|
||||
double nextPollThreshold;
|
||||
|
||||
if (moreWork) {
|
||||
/* We did one quantum of work; consume one unit of 'time'. */
|
||||
nextPollThreshold = globals->pollThreshold + ArenaPollALLOCTIME;
|
||||
} else {
|
||||
/* No more work to do. Sleep until NOW + a bit. */
|
||||
nextPollThreshold = globals->fillMutatorSize + ArenaPollALLOCTIME;
|
||||
}
|
||||
|
||||
/* Advance pollThreshold; check: enough precision? */
|
||||
AVER(nextPollThreshold > globals->pollThreshold);
|
||||
globals->pollThreshold = nextPollThreshold;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Advance pollThreshold; check: enough precision? */
|
||||
AVER(nextPollThreshold > globals->pollThreshold);
|
||||
globals->pollThreshold = nextPollThreshold;
|
||||
|
||||
return ArenaEmergency(arena) || PolicyPoll(arena);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -517,16 +517,18 @@ Trace progress
|
|||
_`.policy.poll`: Return TRUE if the MPS should do some tracing work;
|
||||
FALSE if it should return to the mutator.
|
||||
|
||||
``Bool PolicyPollAgain(Arena arena, Clock start, Size tracedSize)``
|
||||
``Bool PolicyPollAgain(Arena arena, Clock start, Bool moreWork, Work tracedWork)``
|
||||
|
||||
_`.policy.poll.again`: Return TRUE if the MPS should do another unit
|
||||
of work; FALSE if it should return to the mutator. ``start`` is the
|
||||
clock time when the MPS was entered; ``tracedSize`` is the amount of
|
||||
work done by the last call to ``TracePoll()``.
|
||||
clock time when the MPS was entered; ``moreWork`` and ``tracedWork``
|
||||
are the results of the last call to ``TracePoll()``.
|
||||
|
||||
_`.policy.poll.impl`: The implementation balances collection work
|
||||
against mutator allocation so that there is approximately one call to
|
||||
``TracePoll()`` for every ``ArenaPollALLOCTIME`` bytes of allocation.
|
||||
_`.policy.poll.impl`: The implementation keep doing work until either
|
||||
the maximum pause time is exceeded (see design.mps.arena.pause-time_),
|
||||
or there is no more work to do. Then it schedules the next collection
|
||||
so that there is approximately one call to ``TracePoll()`` for every
|
||||
``ArenaPollALLOCTIME`` bytes of allocation.
|
||||
|
||||
|
||||
References
|
||||
|
|
|
|||
|
|
@ -20,6 +20,10 @@ New features
|
|||
current value can be retrieved by the new function
|
||||
:c:func:`mps_arena_pause_time`.
|
||||
|
||||
The maximum pause time defaults to 0.1 seconds. For the old
|
||||
behaviour (whereby the MPS always returned to the :term:`client
|
||||
program` as soon as possible), set it to zero.
|
||||
|
||||
#. When creating an :ref:`pool-amc` pool, :c:func:`mps_pool_create_k`
|
||||
accepts the new keyword argument :c:macro:`MPS_KEY_EXTEND_BY`,
|
||||
specifying the minimum size of the memory segments that the pool
|
||||
|
|
|
|||
|
|
@ -155,7 +155,7 @@ Client arenas
|
|||
:term:`fragmentation` and :term:`retention`.
|
||||
|
||||
* :c:macro:`MPS_KEY_PAUSE_TIME` (type :c:type:`double`, default
|
||||
0.0) is the maximum time, in seconds, that operations within the
|
||||
0.1) is the maximum time, in seconds, that operations within the
|
||||
arena may pause the :term:`client program` for. See
|
||||
:c:func:`mps_arena_pause_time_set` for details.
|
||||
|
||||
|
|
@ -268,7 +268,7 @@ Virtual memory arenas
|
|||
for details.
|
||||
|
||||
* :c:macro:`MPS_KEY_PAUSE_TIME` (type :c:type:`double`, default
|
||||
0.0) is the maximum time, in seconds, that operations within the
|
||||
0.1) is the maximum time, in seconds, that operations within the
|
||||
arena may pause the :term:`client program` for. See
|
||||
:c:func:`mps_arena_pause_time_set` for details.
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue