mirror of
git://git.sv.gnu.org/emacs.git
synced 2026-02-23 13:27:36 +00:00
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:
parent
0a927608dc
commit
3e84e14f00
1 changed files with 55 additions and 26 deletions
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in a new issue