diff --git a/mps/code/config.h b/mps/code/config.h index 1c1df84f751..cf39d861457 100644 --- a/mps/code/config.h +++ b/mps/code/config.h @@ -422,8 +422,9 @@ #define ARENA_MINIMUM_COLLECTABLE_SIZE ((Size)1000000) /* ARENA_DEFAULT_COLLECTION_RATE is an estimate of the MPS's - * collection rate (in bytes per second), for use in the case where - * there isn't enough data to use a measured value. */ + * collection rate (in work per second; see ), for + * use in the case where there isn't enough data to use a measured + * value. */ #define ARENA_DEFAULT_COLLECTION_RATE (25000000.0) diff --git a/mps/code/eventdef.h b/mps/code/eventdef.h index 081b45de7c2..225c21f5f65 100644 --- a/mps/code/eventdef.h +++ b/mps/code/eventdef.h @@ -36,7 +36,7 @@ */ #define EVENT_VERSION_MAJOR ((unsigned)1) -#define EVENT_VERSION_MEDIAN ((unsigned)4) +#define EVENT_VERSION_MEDIAN ((unsigned)5) #define EVENT_VERSION_MINOR ((unsigned)0) @@ -447,7 +447,7 @@ PARAM(X, 1, W, condemned) \ PARAM(X, 2, W, notCondemned) \ PARAM(X, 3, W, foundation) \ - PARAM(X, 4, W, rate) \ + PARAM(X, 4, W, quantumWork) \ PARAM(X, 5, D, mortality) \ PARAM(X, 6, D, finishingTime) @@ -674,7 +674,7 @@ PARAM(X, 4, W, notCondemned) /* collectible but not condemned bytes */ \ PARAM(X, 5, W, foundation) /* foundation size */ \ PARAM(X, 6, W, white) /* white reference set */ \ - PARAM(X, 7, W, rate) /* segs to scan per increment */ + PARAM(X, 7, W, quantumWork) /* work constituting a quantum */ #define EVENT_VMCompact_PARAMS(PARAM, X) \ PARAM(X, 0, W, vmem0) /* pre-collection reserved size */ \ diff --git a/mps/code/global.c b/mps/code/global.c index d92d9b403a5..d15e5cd0da7 100644 --- a/mps/code/global.c +++ b/mps/code/global.c @@ -189,7 +189,7 @@ Bool GlobalsCheck(Globals arenaGlobals) CHECKD_NOSIG(Ring, &arena->greyRing[rank]); CHECKD_NOSIG(Ring, &arena->chainRing); - CHECKL(arena->tracedSize >= 0.0); + CHECKL(arena->tracedWork >= 0.0); CHECKL(arena->tracedTime >= 0.0); /* no check for arena->lastWorldCollect (Clock) */ @@ -287,7 +287,7 @@ Res GlobalsInit(Globals arenaGlobals) arena->finalPool = NULL; arena->busyTraces = TraceSetEMPTY; /* */ arena->flippedTraces = TraceSetEMPTY; /* */ - arena->tracedSize = 0.0; + arena->tracedWork = 0.0; arena->tracedTime = 0.0; arena->lastWorldCollect = ClockNow(); arena->insideShield = FALSE; /* */ @@ -705,7 +705,7 @@ void (ArenaPoll)(Globals globals) Arena arena; Clock start; Count quanta; - Size tracedSize; + Work tracedWork; AVERT(Globals, globals); @@ -726,11 +726,11 @@ void (ArenaPoll)(Globals globals) EVENT3(ArenaPoll, arena, start, 0); do { - tracedSize = TracePoll(globals); - if (tracedSize > 0) { + tracedWork = TracePoll(globals); + if (tracedWork > 0) { quanta += 1; } - } while (PolicyPollAgain(arena, start, tracedSize)); + } while (PolicyPollAgain(arena, start, tracedWork)); /* Don't count time spent checking for work, if there was no work to do. */ if(quanta > 0) { @@ -779,7 +779,7 @@ static Bool arenaShouldCollectWorld(Arena arena, Bool ArenaStep(Globals globals, double interval, double multiplier) { - Size scanned; + Work work; Bool stepped; Clock start, end, now; Clock clocks_per_sec; @@ -812,12 +812,12 @@ Bool ArenaStep(Globals globals, double interval, double multiplier) /* loop while there is work to do and time on the clock. */ do { - scanned = TracePoll(globals); + work = TracePoll(globals); now = ClockNow(); - if (scanned > 0) { + if (work > 0) { stepped = TRUE; } - } while ((scanned > 0) && (now < end)); + } while ((work > 0) && (now < end)); if (stepped) { ArenaAccumulateTime(arena, start); diff --git a/mps/code/mpm.h b/mps/code/mpm.h index ba7e85f2f65..3e888ad28de 100644 --- a/mps/code/mpm.h +++ b/mps/code/mpm.h @@ -399,7 +399,7 @@ extern void TraceDestroyFinished(Trace trace); extern Res TraceAddWhite(Trace trace, Seg seg); extern Res TraceCondemnZones(Trace trace, ZoneSet condemnedSet); extern Res TraceStart(Trace trace, double mortality, double finishingTime); -extern Size TracePoll(Globals globals); +extern Work TracePoll(Globals globals); extern Rank TraceRankForAccess(Arena arena, Seg seg); extern void TraceSegAccess(Arena arena, Seg seg, AccessSet mode); @@ -667,7 +667,7 @@ extern Res PolicyAlloc(Tract *tractReturn, Arena arena, LocusPref pref, extern Bool PolicyStartTrace(Trace *traceReturn, Arena arena); extern double PolicyCollectionTime(Arena arena); extern Bool PolicyPoll(Arena arena); -extern Bool PolicyPollAgain(Arena arena, Clock start, Size tracedSize); +extern Bool PolicyPollAgain(Arena arena, Clock start, Work tracedWork); /* Locus interface */ diff --git a/mps/code/mpmst.h b/mps/code/mpmst.h index ac5c12c1498..86b6ec94890 100644 --- a/mps/code/mpmst.h +++ b/mps/code/mpmst.h @@ -486,7 +486,7 @@ typedef struct TraceStruct { Size condemned; /* condemned bytes */ Size notCondemned; /* collectable but not condemned */ Size foundation; /* initial grey set size */ - Size rate; /* segs to scan per increment */ + Work quantumWork; /* collection work constituting a quantum */ STATISTIC_DECL(Count greySegCount); /* number of grey segs */ STATISTIC_DECL(Count greySegMax); /* max number of grey segs */ STATISTIC_DECL(Count rootScanCount); /* number of roots scanned */ @@ -777,7 +777,7 @@ typedef struct mps_arena_s { TraceMessage tMessage[TraceLIMIT]; /* */ /* policy fields */ - double tracedSize; + double tracedWork; double tracedTime; Clock lastWorldCollect; diff --git a/mps/code/mpmtypes.h b/mps/code/mpmtypes.h index 3a494760cb6..c744fb41fb6 100644 --- a/mps/code/mpmtypes.h +++ b/mps/code/mpmtypes.h @@ -38,6 +38,7 @@ typedef Word Size; /* */ typedef Word Count; /* */ typedef Word Index; /* */ typedef Word Align; /* */ +typedef Word Work; /* */ typedef unsigned Shift; /* */ typedef unsigned Serial; /* */ typedef Addr Ref; /* */ diff --git a/mps/code/policy.c b/mps/code/policy.c index 1052c67f2dc..ff570e4899b 100644 --- a/mps/code/policy.c +++ b/mps/code/policy.c @@ -280,9 +280,8 @@ double PolicyCollectionTime(Arena arena) collectableSize = ArenaCollectable(arena); /* The condition arena->tracedTime >= 1.0 ensures that the division * can't overflow. */ - if (arena->tracedSize >= ARENA_MINIMUM_COLLECTABLE_SIZE - && arena->tracedTime >= 1.0) - collectionRate = arena->tracedSize / arena->tracedTime; + if (arena->tracedTime >= 1.0) + collectionRate = arena->tracedWork / arena->tracedTime; else collectionRate = ARENA_DEFAULT_COLLECTION_RATE; collectionTime = collectableSize / collectionRate; @@ -313,10 +312,10 @@ Bool PolicyPoll(Arena arena) * 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. + * tracedWork is the amount of work done by the last call to TracePoll. */ -Bool PolicyPollAgain(Arena arena, Clock start, Size tracedSize) +Bool PolicyPollAgain(Arena arena, Clock start, Work tracedWork) { Globals globals; double nextPollThreshold; @@ -325,7 +324,7 @@ Bool PolicyPollAgain(Arena arena, Clock start, Size tracedSize) globals = ArenaGlobals(arena); UNUSED(start); - if (tracedSize == 0) { + if (tracedWork == 0) { /* No work was done. Sleep until NOW + a bit. */ nextPollThreshold = globals->fillMutatorSize + ArenaPollALLOCTIME; } else { diff --git a/mps/code/trace.c b/mps/code/trace.c index 9e7d880f2b6..d34d953bf40 100644 --- a/mps/code/trace.c +++ b/mps/code/trace.c @@ -109,7 +109,7 @@ void ScanStateInit(ScanState ss, TraceSet ts, Arena arena, STATISTIC(ss->preservedInPlaceCount = (Count)0); ss->preservedInPlaceSize = (Size)0; /* see .message.data */ STATISTIC(ss->copiedSize = (Size)0); - ss->scannedSize = (Size)0; /* see .workclock */ + ss->scannedSize = (Size)0; /* see .work */ ss->sig = ScanStateSig; AVERT(ScanState, ss); @@ -277,7 +277,7 @@ static void traceUpdateCounts(Trace trace, ScanState ss, break; } case traceAccountingPhaseSegScan: { - trace->segScanSize += ss->scannedSize; /* see .workclock */ + trace->segScanSize += ss->scannedSize; /* see .work */ trace->segCopiedSize += ss->copiedSize; STATISTIC(++trace->segScanCount); break; @@ -697,14 +697,14 @@ found: trace->condemned = (Size)0; /* nothing condemned yet */ trace->notCondemned = (Size)0; trace->foundation = (Size)0; /* nothing grey yet */ - trace->rate = (Size)0; /* no scanning to be done yet */ + trace->quantumWork = (Work)0; /* no work done yet */ STATISTIC(trace->greySegCount = (Count)0); STATISTIC(trace->greySegMax = (Count)0); STATISTIC(trace->rootScanCount = (Count)0); trace->rootScanSize = (Size)0; trace->rootCopiedSize = (Size)0; STATISTIC(trace->segScanCount = (Count)0); - trace->segScanSize = (Size)0; /* see .workclock */ + trace->segScanSize = (Size)0; /* see .work */ trace->segCopiedSize = (Size)0; STATISTIC(trace->singleScanCount = (Count)0); STATISTIC(trace->singleScanSize = (Size)0); @@ -1713,8 +1713,10 @@ Res TraceStart(Trace trace, double mortality, double finishingTime) /* integer, so try to make sure it fits. */ if(nPolls >= (double)LONG_MAX) nPolls = (double)LONG_MAX; - /* rate equals scanning work per number of polls available */ - trace->rate = (trace->foundation + sSurvivors) / (unsigned long)nPolls + 1; + /* One quantum of work equals scanning work divided by number of + * polls, plus one to ensure it's not zero. */ + trace->quantumWork + = (trace->foundation + sSurvivors) / (unsigned long)nPolls + 1; } /* TODO: compute rate of scanning here. */ @@ -1722,11 +1724,11 @@ Res TraceStart(Trace trace, double mortality, double finishingTime) EVENT8(TraceStart, trace, mortality, finishingTime, trace->condemned, trace->notCondemned, trace->foundation, trace->white, - trace->rate); + trace->quantumWork); STATISTIC_STAT(EVENT7(TraceStatCondemn, trace, trace->condemned, trace->notCondemned, - trace->foundation, trace->rate, + trace->foundation, trace->quantumWork, mortality, finishingTime)); trace->state = TraceUNFLIPPED; @@ -1737,11 +1739,11 @@ Res TraceStart(Trace trace, double mortality, double finishingTime) } -/* traceWorkClock -- a measure of the work done for this trace +/* traceWork -- a measure of the work done for this trace * - * .workclock: Segment and root scanning work is the regulator. */ + * .work: Segment and root scanning work is the measure. */ -#define traceWorkClock(trace) ((trace)->segScanSize + (trace)->rootScanSize) +#define traceWork(trace) ((Work)((trace)->segScanSize + (trace)->rootScanSize)) /* TraceAdvance -- progress a trace by one step */ @@ -1749,11 +1751,11 @@ Res TraceStart(Trace trace, double mortality, double finishingTime) void TraceAdvance(Trace trace) { Arena arena; - Size oldWork, newWork; + Work oldWork, newWork; AVERT(Trace, trace); arena = trace->arena; - oldWork = traceWorkClock(trace); + oldWork = traceWork(trace); switch (trace->state) { case TraceUNFLIPPED: @@ -1783,9 +1785,9 @@ void TraceAdvance(Trace trace) break; } - newWork = traceWorkClock(trace); + newWork = traceWork(trace); AVER(newWork >= oldWork); - arena->tracedSize += newWork - oldWork; + arena->tracedWork += newWork - oldWork; } @@ -1844,11 +1846,11 @@ failCondemn: * trace (if any) by one quantum. Return a measure of the work done. */ -Size TracePoll(Globals globals) +Work TracePoll(Globals globals) { Trace trace; Arena arena; - Size oldScannedSize, scannedSize, pollEnd; + Work oldWork, newWork, work, endWork; AVERT(Globals, globals); arena = GlobalsArena(globals); @@ -1862,20 +1864,22 @@ Size TracePoll(Globals globals) } AVER(arena->busyTraces == TraceSetSingle(trace)); - oldScannedSize = traceWorkClock(trace); - pollEnd = oldScannedSize + trace->rate; + oldWork = traceWork(trace); + endWork = oldWork + trace->quantumWork; do { TraceAdvance(trace); } while (trace->state != TraceFINISHED - && (ArenaEmergency(arena) || traceWorkClock(trace) < pollEnd)); - scannedSize = traceWorkClock(trace) - oldScannedSize; + && (ArenaEmergency(arena) || traceWork(trace) < endWork)); + newWork = traceWork(trace); + AVER(newWork >= oldWork); + work = newWork - oldWork; if (trace->state == TraceFINISHED) { TraceDestroyFinished(trace); /* A trace finished, and hopefully reclaimed some memory, so clear any * emergency. */ ArenaSetEmergency(arena, FALSE); } - return scannedSize; + return work; } @@ -1913,7 +1917,7 @@ Res TraceDescribe(Trace trace, mps_lib_FILE *stream, Count depth) " condemned $U\n", (WriteFU)trace->condemned, " notCondemned $U\n", (WriteFU)trace->notCondemned, " foundation $U\n", (WriteFU)trace->foundation, - " rate $U\n", (WriteFU)trace->rate, + " quantumWork $U\n", (WriteFU)trace->quantumWork, " rootScanSize $U\n", (WriteFU)trace->rootScanSize, " rootCopiedSize $U\n", (WriteFU)trace->rootCopiedSize, " segScanSize $U\n", (WriteFU)trace->segScanSize, diff --git a/mps/design/type.txt b/mps/design/type.txt index 25943f41a4b..dc3c3b8cf99 100644 --- a/mps/design/type.txt +++ b/mps/design/type.txt @@ -664,6 +664,15 @@ _`.word.ops`: ``WordIsAligned()``, ``WordAlignUp()``, ``WordAlignDown()`` and ``WordRoundUp()``. +``typedef MPS_T_WORD Work`` + +_`.work`: ``Work`` is an unsigned integral type representing +accumulated work done by the collector. + +_`.work.impl`: Work is currently implemented as a count of bytes +scanned by the collector. + + ``typedef Word ZoneSet`` _`.zoneset`: ``ZoneSet`` is a conservative approximation to a set of