1
Fork 0
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:
Gareth Rees 2016-03-12 22:08:26 +00:00
parent 66e0d30340
commit 459a9f775d
8 changed files with 53 additions and 34 deletions

View file

@ -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

View file

@ -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;

View file

@ -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;

View file

@ -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 */

View file

@ -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);
}

View file

@ -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

View file

@ -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

View file

@ -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.