mirror of
git://git.sv.gnu.org/emacs.git
synced 2026-02-25 06:17:34 +00:00
Documentation and interface for pause time control (no implementation yet).
Copied from Perforce Change: 189915 ServerID: perforce.ravenbrook.com
This commit is contained in:
parent
c1c71ea304
commit
f9041d9a20
12 changed files with 151 additions and 9 deletions
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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> */
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
.....
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
.................
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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`
|
||||
|
|
|
|||
Loading…
Reference in a new issue