Documentation and interface for pause time control (no implementation yet).

Copied from Perforce
 Change: 189915
 ServerID: perforce.ravenbrook.com
This commit is contained in:
Gareth Rees 2016-03-12 20:25:33 +00:00
parent c1c71ea304
commit f9041d9a20
12 changed files with 151 additions and 9 deletions

View file

@ -149,6 +149,7 @@ Bool ArenaCheck(Arena arena)
*/
CHECKL(arena->committed <= arena->commitLimit);
CHECKL(arena->spareCommitted <= arena->committed);
CHECKL(0.0 <= arena->pauseTime);
CHECKL(ShiftCheck(arena->zoneShift));
CHECKL(ArenaGrainSizeCheck(arena->grainSize));
@ -199,6 +200,7 @@ Res ArenaInit(Arena arena, ArenaClass class, Size grainSize, ArgList args)
Bool zoned = ARENA_DEFAULT_ZONED;
Size commitLimit = ARENA_DEFAULT_COMMIT_LIMIT;
Size spareCommitLimit = ARENA_DEFAULT_SPARE_COMMIT_LIMIT;
double pauseTime = ARENA_DEFAULT_PAUSE_TIME;
mps_arg_s arg;
AVER(arena != NULL);
@ -211,6 +213,8 @@ Res ArenaInit(Arena arena, ArenaClass class, Size grainSize, ArgList args)
commitLimit = arg.val.size;
if (ArgPick(&arg, args, MPS_KEY_SPARE_COMMIT_LIMIT))
spareCommitLimit = arg.val.size;
if (ArgPick(&arg, args, MPS_KEY_PAUSE_TIME))
pauseTime = arg.val.d;
arena->class = class;
@ -219,6 +223,7 @@ Res ArenaInit(Arena arena, ArenaClass class, Size grainSize, ArgList args)
arena->commitLimit = commitLimit;
arena->spareCommitted = (Size)0;
arena->spareCommitLimit = spareCommitLimit;
arena->pauseTime = pauseTime;
arena->grainSize = grainSize;
/* zoneShift is usually overridden by init */
arena->zoneShift = ARENA_ZONESHIFT;
@ -294,6 +299,7 @@ ARG_DEFINE_KEY(ARENA_SIZE, Size);
ARG_DEFINE_KEY(ARENA_ZONED, Bool);
ARG_DEFINE_KEY(COMMIT_LIMIT, Size);
ARG_DEFINE_KEY(SPARE_COMMIT_LIMIT, Size);
ARG_DEFINE_KEY(PAUSE_TIME, double);
static Res arenaFreeLandInit(Arena arena)
{
@ -1242,6 +1248,20 @@ void ArenaSetSpareCommitLimit(Arena arena, Size limit)
EVENT2(SpareCommitLimitSet, arena, limit);
}
double ArenaPauseTime(Arena arena)
{
AVERT(Arena, arena);
return arena->pauseTime;
}
void ArenaSetPauseTime(Arena arena, double pauseTime)
{
AVERT(Arena, arena);
AVER(0.0 <= pauseTime);
arena->pauseTime = pauseTime;
EVENT2(PauseTimeSet, arena, pauseTime);
}
/* Used by arenas which don't use spare committed memory */
Size ArenaNoPurgeSpare(Arena arena, Size size)
{

View file

@ -93,8 +93,8 @@ Bool ArgCheckRank(Arg arg) {
}
Bool ArgCheckdouble(Arg arg) {
/* It would be nice if we could check doubles with C89, but
it doesn't have isfinite() etc. which are in C99. */
/* Don't call isfinite() here because it's not in C89, and because
infinity is a valid value for MPS_KEY_PAUSE_TIME. */
UNUSED(arg);
return TRUE;
}

View file

@ -408,9 +408,14 @@
/* TODO: This should be proportional to the memory usage of the MPS, not
* a constant. That will require design, and then some interface and
* documenation changes. */
* 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. */
#define ARENA_DEFAULT_PAUSE_TIME (0.0)
#define ARENA_DEFAULT_ZONED TRUE
/* ARENA_MINIMUM_COLLECTABLE_SIZE is the minimum size (in bytes) of

View file

@ -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)
@ -67,7 +67,7 @@
*/
#define EventNameMAX ((size_t)19)
#define EventCodeMAX ((EventCode)0x0086)
#define EventCodeMAX ((EventCode)0x0087)
#define EVENT_LIST(EVENT, X) \
/* 0123456789012345678 <- don't exceed without changing EventNameMAX */ \
@ -192,7 +192,8 @@
EVENT(X, TraceCondemnZones , 0x0083, TRUE, Trace) \
EVENT(X, ArenaGenZoneAdd , 0x0084, TRUE, Arena) \
EVENT(X, ArenaUseFreeZone , 0x0085, TRUE, Arena) \
/* EVENT(X, ArenaBlacklistZone , 0x0086, TRUE, Arena) */
/* EVENT(X, ArenaBlacklistZone , 0x0086, TRUE, Arena) */ \
EVENT(X, PauseTimeSet , 0x0087, TRUE, Arena)
/* Remember to update EventNameMAX and EventCodeMAX above!
@ -740,6 +741,10 @@
PARAM(X, 0, P, arena) /* the arena */ \
PARAM(X, 1, W, zoneSet) /* zones that aren't free any longer */
#define EVENT_PauseTimeSet_PARAMS(PARAM, X) \
PARAM(X, 0, P, arena) /* the arena */ \
PARAM(X, 1, D, pauseTime) /* the new maximum pause time, in seconds */
#endif /* eventdef_h */

View file

@ -621,6 +621,8 @@ extern Size ArenaCommitLimit(Arena arena);
extern Res ArenaSetCommitLimit(Arena arena, Size limit);
extern Size ArenaSpareCommitLimit(Arena arena);
extern void ArenaSetSpareCommitLimit(Arena arena, Size limit);
extern double ArenaPauseTime(Arena arena);
extern void ArenaSetPauseTime(Arena arena, double pauseTime);
extern Size ArenaNoPurgeSpare(Arena arena, Size size);
extern Res ArenaNoGrow(Arena arena, LocusPref pref, Size size);

View file

@ -719,6 +719,7 @@ typedef struct mps_arena_s {
Size spareCommitted; /* Amount of memory in hysteresis fund */
Size spareCommitLimit; /* Limit on spareCommitted */
double pauseTime; /* Maximum pause time, in seconds. */
Shift zoneShift; /* see also <code/ref.c> */
Size grainSize; /* <design/arena/#grain> */

View file

@ -189,6 +189,9 @@ extern const struct mps_key_s _mps_key_COMMIT_LIMIT;
extern const struct mps_key_s _mps_key_SPARE_COMMIT_LIMIT;
#define MPS_KEY_SPARE_COMMIT_LIMIT (&_mps_key_SPARE_COMMIT_LIMIT)
#define MPS_KEY_SPARE_COMMIT_LIMIT_FIELD size
extern const struct mps_key_s _mps_key_PAUSE_TIME;
#define MPS_KEY_PAUSE_TIME (&_mps_key_PAUSE_TIME)
#define MPS_KEY_PAUSE_TIME_FIELD d
extern const struct mps_key_s _mps_key_EXTEND_BY;
#define MPS_KEY_EXTEND_BY (&_mps_key_EXTEND_BY)
@ -457,6 +460,9 @@ extern mps_res_t mps_arena_commit_limit_set(mps_arena_t, size_t);
extern void mps_arena_spare_commit_limit_set(mps_arena_t, size_t);
extern size_t mps_arena_spare_commit_limit(mps_arena_t);
extern double mps_arena_pause_time(mps_arena_t);
extern void mps_arena_pause_time_set(mps_arena_t, double);
extern mps_bool_t mps_arena_has_addr(mps_arena_t, mps_addr_t);
extern mps_bool_t mps_addr_pool(mps_pool_t *, mps_arena_t, mps_addr_t);
extern mps_bool_t mps_addr_fmt(mps_fmt_t *, mps_arena_t, mps_addr_t);

View file

@ -217,6 +217,25 @@ size_t mps_arena_spare_commit_limit(mps_arena_t arena)
return limit;
}
double mps_arena_pause_time(mps_arena_t arena)
{
double pause_time;
ArenaEnter(arena);
pause_time = ArenaPauseTime(arena);
ArenaLeave(arena);
return pause_time;
}
void mps_arena_pause_time_set(mps_arena_t arena, double pause_time)
{
ArenaEnter(arena);
ArenaSetPauseTime(arena, pause_time);
ArenaLeave(arena);
}
void mps_arena_clamp(mps_arena_t arena)
{
ArenaEnter(arena);

View file

@ -447,6 +447,17 @@ than the amount of spare committed memory (stored in
``spareCommitExceeded`` is called.
Pause time control
..................
_`.pause-time`: The generic arena structure contains the field
``pauseTime`` for the maximum time any operation in the arena may take
before returning to the mutator. This value is used by
``PolicyPollAgain()`` to decide whether to do another unit of tracing
work. The MPS interface provides getter (``mps_arena_pause_time()``)
and setter (``mps_arena_pause_time_set()``) functions.
Locks
.....

View file

@ -12,6 +12,14 @@ Release 1.115.0
New features
............
#. The MPS now provides control over the maximum time that operations
within an arena may pause the :term:`client program` for. This can
be specified by the new function :c:func:`mps_arena_pause_time_set`
or by passing the new keyword argument
:c:macro:`MPS_KEY_PAUSE_TIME` to :c:func:`mps_arena_create_k`. The
current value can be retrieved by the new function
:c:func:`mps_arena_pause_time`.
#. 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
@ -41,6 +49,7 @@ New features
:c:func:`mps_root_create_area_tagged` for areas of memory
that can be scanned by area scanning functions.
Interface changes
.................

View file

@ -139,7 +139,7 @@ Client arenas
* :c:macro:`MPS_KEY_ARENA_SIZE` (type :c:type:`size_t`) is its
size.
It also accepts two optional keyword arguments:
It also accepts three optional keyword arguments:
* :c:macro:`MPS_KEY_COMMIT_LIMIT` (type :c:type:`size_t`) is
the maximum amount of memory, in :term:`bytes (1)`, that the MPS
@ -154,6 +154,11 @@ Client arenas
granularity reduces overheads, but increases
: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
arena may pause the :term:`client program` for. See
:c:func:`mps_arena_pause_time_set` for details.
For example::
MPS_ARGS_BEGIN(args) {
@ -213,7 +218,7 @@ Virtual memory arenas
more efficient.
When creating a virtual memory arena, :c:func:`mps_arena_create_k`
accepts four optional :term:`keyword arguments` on all platforms:
accepts five optional :term:`keyword arguments` on all platforms:
* :c:macro:`MPS_KEY_ARENA_SIZE` (type :c:type:`size_t`, default
256 :term:`megabytes`) is the initial amount of virtual address
@ -262,7 +267,12 @@ Virtual memory arenas
:term:`bytes (1)`. See :c:func:`mps_arena_spare_commit_limit`
for details.
A fifth optional :term:`keyword argument` may be passed, but it
* :c:macro:`MPS_KEY_PAUSE_TIME` (type :c:type:`double`, default
0.0) 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.
A sixth optional :term:`keyword argument` may be passed, but it
only has any effect on the Windows operating system:
* :c:macro:`MPS_KEY_VMW3_TOP_DOWN` (type :c:type:`mps_bool_t`,
@ -424,6 +434,59 @@ Arena properties
:c:func:`mps_arena_commit_limit`.
.. c:function:: double mps_arena_pause_time(mps_arena_t arena)
Return the maximum time, in seconds, that operations within the
arena may pause the :term:`client program` for.
``arena`` is the arena.
See :c:func:`mps_arena_pause_time_set` for details.
.. c:function:: void mps_arena_pause_time_set(mps_arena_t arena, double pause_time)
Set the maximum time, in seconds, that operations within an arena
may pause the :term:`client program` for.
``arena`` is the arena.
``pause_time`` is the new maximum pause time, in seconds. It must
be non-negative.
The pause time may be set to zero, in which case the MPS returns
as soon as it can do so. The consequence is that the MPS will need
to take more slices of time in order to make :term:`garbage
collection` progress. This value is suitable for interactive
applications where latency needs to be minimized, but where there
is plenty of CPU time available.
The pause time may be set to infinity, in which case the MPS
completes all outstanding :term:`garbage collection` work before
returning from an operation. The consequence is that the MPS will
be able to save on the overheads due to :term:`incremental
collection`, leading to lower total time spent in collection. This
value is suitable for non-interactive applications where total
time is important.
The MPS makes a best effort to return to the :term:`client
program` from any operation on the arena within the maximum pause
time, but does not guarantee to do so. This is for three reasons:
1. many operations in the MPS necessarily take some minimum amount
time that's logarithmic in the amount of :term:`memory (2)`
being managed (so if you set the maximum pause time to zero,
then every operation will exceed it);
2. some operations in the MPS call functions in the :term:`client
program` (for example, the :term:`format methods`), and the MPS
has no control over how long these functions take;
3. none of the operating systems supported by the MPS provide
real-time guarantees (for example, the process may have to wait
for :term:`memory (2)` to be :term:`paged in`).
.. c:function:: size_t mps_arena_reserved(mps_arena_t arena)
Return the total :term:`address space` reserved by an

View file

@ -115,6 +115,7 @@ now :c:macro:`MPS_KEY_ARGS_END`.
:c:macro:`MPS_KEY_MVFF_SLOT_HIGH` :c:type:`mps_bool_t` ``b`` :c:func:`mps_class_mvff`
:c:macro:`MPS_KEY_MVT_FRAG_LIMIT` :c:type:`mps_word_t` ``count`` :c:func:`mps_class_mvt`
:c:macro:`MPS_KEY_MVT_RESERVE_DEPTH` :c:type:`mps_word_t` ``count`` :c:func:`mps_class_mvt`
:c:macro:`MPS_KEY_PAUSE_TIME` :c:type:`double` ``size`` :c:func:`mps_arena_class_vm`, :c:func:`mps_arena_class_cl`
:c:macro:`MPS_KEY_POOL_DEBUG_OPTIONS` :c:type:`mps_pool_debug_option_s` ``*pool_debug_options`` :c:func:`mps_class_ams_debug`, :c:func:`mps_class_mv_debug`, :c:func:`mps_class_mvff_debug`
:c:macro:`MPS_KEY_RANK` :c:type:`mps_rank_t` ``rank`` :c:func:`mps_class_ams`, :c:func:`mps_class_awl`, :c:func:`mps_class_snc`
:c:macro:`MPS_KEY_SPARE` :c:type:`double` ``d`` :c:func:`mps_class_mvff`