Improve design.mps.strategy based on nb's review comments <https://info.ravenbrook.com/mail/2015/09/04/13-56-30/0/>

Copied from Perforce
 Change: 188242
 ServerID: perforce.ravenbrook.com
This commit is contained in:
Gareth Rees 2015-09-04 16:04:42 +01:00
parent 0a927608dc
commit 3e84e14f00

View file

@ -145,23 +145,11 @@ Collections
Collections in the MPS start in one of two ways:
1. A collection of the world starts via ``traceCondemnAll()``. This
simply condemns all segments in all automatic pools.
1. A collection of the world starts via ``TraceStartCollectAll()``.
This simply condemns all segments in all automatic pools.
2. A collection of some set of generations starts via ``TracePoll()``.
This calls ``ChainDeferral()`` for each chain; this function
indicates if the chain needs collecting, and if so, how urgent it
is to collect that chain. The most urgent chain in need of
collection (if any) is then condemned by calling
``policyCondemnChain()``.
This function chooses the set of generations to condemn, computes
the zoneset corresponding to the union those generations, and
condemns those zones by calling ``TraceCondemnZones()``.
Note that the condemnation is of every segment in an automatic pool
in any zone in the zoneset. It is not limited to the segments
actually associated with the condemned generations.
2. A collection of some set of generations starts via
``PolicyStartTrace()``. See `.policy.start`_.
Zones
@ -216,11 +204,11 @@ categories of data allocated in that generation for that pool. This
accounting information is reported via the event system, but also used
in two places:
_`.accounting.poll`: ``ChainDeferral()`` uses the *new size* of each
generation to determine which generations in the chain are over
capacity and so might need to be collected via ``TracePoll()``.
_`.accounting.poll`: ``ChainDeferral()`` uses the *new size* of
each generation to determine which generations in the chain are over
capacity and so might need to be collected by ``PolicyStartTrace()``.
_`.accounting.condemn`: ``policyCondemnChain()`` uses the *new size* of
_`.accounting.condemn`: ``PolicyStartTrace()`` uses the *new size* of
each generation to determine which generations in the chain will be
collected; it also uses the *total size* of the generation to compute
the mortality.
@ -450,11 +438,11 @@ successful, update ``*tractReturn`` to point to the first tract in the
allocated memory and return ``ResOK``. Otherwise, return a result code
describing the problem, for example ``ResCOMMIT_LIMIT``.
_`.policy.alloc.plan`: This tries various plans in succession until
_`.policy.alloc.impl`: This tries various methods in succession until
one succeeds. First, it tries to allocate from the arena's free land
in the requested zones. Second, it tries allocating from free zones.
Third, it tries extending the arena and then trying the first two
plans again. Fourth, it tries allocating from any zone that is not
methods again. Fourth, it tries allocating from any zone that is not
blacklisted. Fifth, it tries allocating from any zone at all.
_`.policy.alloc.issue`: This plan performs poorly under stress. See
@ -464,6 +452,28 @@ for example job003898_.
Deciding whether to collect the world
.....................................
``Bool PolicyShouldCollectWorld(Arena arena, double interval, double multiplier, Clock now, Clock clocks_per_sec)``
_`.policy.world`: Determine whether now is a good time for
``mps_arena_step()`` to start a collection of the world. Return
``TRUE`` if so, ``FALSE`` if not. The ``interval`` and ``multiplier``
arguments are the ones the client program passed to
``mps_arena_step()``, ``now`` is the current time as returned by
``ClockNow()``, and ``clocks_per_sec`` is the result of calling
``ClocksPerSec()``.
_`.policy.world.impl`: There are two conditions: the client program's
estimate of the available time must be enough to complete the
collection, and the last collection of the world must be long enough
in the past that the ``mps_arena_step()`` won't be spending more than
a certain fraction of runtime in collections. (This fraction is given
by the ``ARENA_MAX_COLLECT_FRACTION`` configuration parameter.)
Starting a trace
................
@ -474,10 +484,29 @@ update ``*traceReturn`` to point to the trace and return TRUE.
Otherwise, leave ``*traceReturn`` unchanged and return FALSE.
_`.policy.start.impl`: This uses the "Lisp Machine" strategy, which
tries to schedule collections so that the collector just keeps pace
with the mutator: that is, it starts a collection when the predicted
completion time of the collection is around the time when the mutator
is predicted to reach the current memory limit. See [Pirinen]_.
tries to schedule collections of the world so that the collector just
keeps pace with the mutator: that is, it starts a collection when the
predicted completion time of the collection is around the time when
the mutator is predicted to reach the current memory limit. See
[Pirinen]_.
_`.policy.start.chain`: If it is not yet time to schedule a collection
of the world, ``PolicyStartTrace()`` considers collecting a set of
zones corresponding to a set of generations on a chain.
It picks these generations by calling ``ChainDeferral()`` for each
chain; this function indicates if the chain needs collecting, and if
so, how urgent it is to collect that chain. The most urgent chain in
need of collection (if any) is then condemned by calling
``policyCondemnChain()``, which chooses the set of generations to
condemn, computes the zoneset corresponding to the union those
generations, and condemns those zones by calling
``TraceCondemnZones()``.
Note that the resulting condemned set includes every segment in an
automatic pool in any zone in the zoneset. It is not limited to the
segments actually associated with the condemned generations.
Trace progress