mirror of
git://git.sv.gnu.org/emacs.git
synced 2026-03-24 07:41:54 -07:00
Incremental step function for mps.
Copied from Perforce Change: 29402 ServerID: perforce.ravenbrook.com
This commit is contained in:
parent
bf65f05d74
commit
eb0b4af2ef
8 changed files with 279 additions and 16 deletions
|
|
@ -63,14 +63,14 @@ void ActionFinish(Action action)
|
|||
* and takes those which are worthwhile.
|
||||
*/
|
||||
|
||||
void ActionPoll(Arena arena)
|
||||
Bool ActionPoll(Arena arena)
|
||||
{
|
||||
Ring poolNode, nextPoolNode;
|
||||
double bestBenefit;
|
||||
Action bestAction;
|
||||
|
||||
|
||||
AVERT(Arena, arena);
|
||||
|
||||
|
||||
bestBenefit = -DBL_MAX;
|
||||
bestAction = NULL;
|
||||
|
||||
|
|
@ -82,7 +82,7 @@ void ActionPoll(Arena arena)
|
|||
Action action = RING_ELT(Action, poolRing, actionNode);
|
||||
double benefit;
|
||||
AVERT(Action, action);
|
||||
|
||||
|
||||
benefit = PoolBenefit(action->pool, action);
|
||||
if(benefit >= bestBenefit) {
|
||||
bestBenefit = benefit;
|
||||
|
|
@ -95,5 +95,7 @@ void ActionPoll(Arena arena)
|
|||
if(bestBenefit > 0) {
|
||||
AVER(bestAction != NULL);
|
||||
(void)PoolAct(bestAction->pool, bestAction);
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -671,7 +671,7 @@ void ArenaPoll(Arena arena)
|
|||
|
||||
arena->insidePoll = TRUE;
|
||||
|
||||
ArenaStep(arena);
|
||||
ArenaStep(arena, 0.0);
|
||||
|
||||
arena->insidePoll = FALSE;
|
||||
}
|
||||
|
|
@ -713,17 +713,20 @@ void ArenaPark(Arena arena)
|
|||
}
|
||||
|
||||
|
||||
/* Take a single step of any active trace. */
|
||||
/* Take some time to perform actions (e.g. start traces, step active
|
||||
* traces). */
|
||||
|
||||
void ArenaStep(Arena arena)
|
||||
Bool ArenaStep(Arena arena, double interval)
|
||||
{
|
||||
TraceId ti;
|
||||
Bool done;
|
||||
double size;
|
||||
|
||||
AVERT(Arena, arena);
|
||||
UNUSED(interval);
|
||||
|
||||
/* Poll actions to see if any new action is to be taken. */
|
||||
ActionPoll(arena);
|
||||
done = ActionPoll(arena);
|
||||
|
||||
if (arena->busyTraces != TraceSetEMPTY) {
|
||||
/* Find an active trace to poll. */
|
||||
|
|
@ -731,6 +734,7 @@ void ArenaStep(Arena arena)
|
|||
if(TraceSetIsMember(arena->busyTraces, ti)) {
|
||||
Trace trace = ArenaTrace(arena, ti);
|
||||
TracePoll(trace);
|
||||
done = TRUE;
|
||||
if(trace->state == TraceFINISHED)
|
||||
TraceDestroy(trace);
|
||||
}
|
||||
|
|
@ -741,6 +745,7 @@ void ArenaStep(Arena arena)
|
|||
size = arena->fillMutatorSize;
|
||||
arena->pollThreshold = size + ARENA_POLL_MAX;
|
||||
AVER(arena->pollThreshold > size); /* enough precision? */
|
||||
return done;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -289,7 +289,7 @@ swall: mmsw.a epvmss replaysw epdss
|
|||
# mv2test cannot be run because MV2 is broken
|
||||
testrun: mpmss apss sacss amcss amcsshe amsss amssshe segsmss awlut awluthe \
|
||||
mpsicv lockcov poolncv locv qs finalcv arenacv \
|
||||
abqtest cbstest btcv messtest
|
||||
abqtest cbstest btcv messtest steptest
|
||||
$(^:%=date && $(PFM)/$(VARIETY)/% &&) true
|
||||
|
||||
# Runs the automatic tests that are built with CONFIG_PROD_EPCORE
|
||||
|
|
@ -303,7 +303,7 @@ testrunep: epvmss epdss
|
|||
# %%TARGET: Add a pseudo-target for the new target here.
|
||||
|
||||
mpmss apss sacss amcss amcssth amcsshe amsss amssshe segsmss awlut awluthe awlutth mpsicv \
|
||||
lockcov poolncv locv qs finalcv arenacv bttest teletest epvmss \
|
||||
lockcov poolncv locv qs finalcv arenacv bttest teletest epvmss steptest \
|
||||
abqtest cbstest btcv mv2test messtest eventcnv replay replaysw \
|
||||
mps.a lo.a awl.a mmsw.a mpsplan.a mmdw.a: phony
|
||||
ifdef VARIETY
|
||||
|
|
@ -438,6 +438,9 @@ $(PFM)/$(VARIETY)/mv2test: $(PFM)/$(VARIETY)/mv2test.o \
|
|||
$(PFM)/$(VARIETY)/messtest: $(PFM)/$(VARIETY)/messtest.o \
|
||||
$(MPMOBJ) $(PLINTHOBJ) $(TESTLIBOBJ)
|
||||
|
||||
$(PFM)/$(VARIETY)/steptest: $(PFM)/$(VARIETY)/steptest.o \
|
||||
$(FMTDYTSTOBJ) $(MPMOBJ) $(AMCOBJ) $(TESTLIBOBJ)
|
||||
|
||||
$(PFM)/$(VARIETY)/eventcnv: $(PFM)/$(VARIETY)/eventcnv.o \
|
||||
$(PFM)/$(VARIETY)/eventpro.o $(PFM)/$(VARIETY)/table.o
|
||||
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ mpmss.exe amcss.exe amcsshe.exe amsss.exe amssshe.exe segsmss.exe awlut.exe awlu
|
|||
mpsicv.exe lockutw3.exe lockcov.exe poolncv.exe locv.exe qs.exe apss.exe \
|
||||
finalcv.exe arenacv.exe bttest.exe teletest.exe protcv.exe \
|
||||
thw3susp.exe abqtest.exe cbstest.exe btcv.exe \
|
||||
mv2test.exe epvmss.exe messtest.exe eventcnv.exe replay.exe replaysw.exe \
|
||||
mv2test.exe epvmss.exe messtest.exe eventcnv.exe replay.exe replaysw.exe steptest.exe \
|
||||
mmdw.lib mmsw.lib mps_conf.lib mpsplan.lib:
|
||||
!IFDEF VARIETY
|
||||
$(MAKE) /nologo /f $(PFM).nmk TARGET=$@ variety
|
||||
|
|
@ -209,6 +209,10 @@ $(PFM)\$(VARIETY)\epvmss.exe: $(PFM)\$(VARIETY)\epvmss.obj \
|
|||
$(PFM)\$(VARIETY)\messtest.exe: $(PFM)\$(VARIETY)\messtest.obj \
|
||||
$(MPMOBJ) $(PLINTHOBJ) $(TESTLIBOBJ)
|
||||
|
||||
$(PFM)\$(VARIETY)\steptest.exe: $(PFM)\$(VARIETY)\steptest.obj \
|
||||
$(MPMOBJ) $(AMCOBJ) $(PLINTHOBJ) $(DWOBJ) $(DWTESTOBJ) \
|
||||
$(TESTLIBOBJ)
|
||||
|
||||
$(PFM)\$(VARIETY)\mmsw.lib: $(SWOBJ)
|
||||
$(ECHO) $@
|
||||
$(LIBMAN) $(LIBFLAGS) /OUT:$@ $**
|
||||
|
|
|
|||
|
|
@ -609,7 +609,7 @@ extern void TraceScanSingleRef(TraceSet ts, Rank rank, Arena arena,
|
|||
extern Bool ActionCheck(Action action);
|
||||
extern void ActionInit(Action action, Pool pool);
|
||||
extern void ActionFinish(Action action);
|
||||
extern void ActionPoll(Arena arena);
|
||||
extern Bool ActionPoll(Arena arena);
|
||||
|
||||
|
||||
/* Arena Interface -- see impl.c.arena */
|
||||
|
|
@ -653,7 +653,7 @@ extern void (ArenaPoll)(Arena arena);
|
|||
/* .nogc.why: ScriptWorks doesn't use MM-provided incremental GC, so */
|
||||
/* doesn't need to poll when allocating. */
|
||||
|
||||
extern void ArenaStep(Arena arena);
|
||||
extern Bool ArenaStep(Arena arena, double interval);
|
||||
extern void ArenaClamp(Arena arena);
|
||||
extern void ArenaRelease(Arena arena);
|
||||
extern void ArenaPark(Arena arena);
|
||||
|
|
|
|||
|
|
@ -238,7 +238,7 @@ extern void mps_arena_clamp(mps_arena_t);
|
|||
extern void mps_arena_release(mps_arena_t);
|
||||
extern void mps_arena_park(mps_arena_t);
|
||||
extern mps_res_t mps_arena_collect(mps_arena_t);
|
||||
extern void mps_arena_step(mps_arena_t);
|
||||
extern mps_bool_t mps_arena_step(mps_arena_t, double);
|
||||
extern void mps_space_clamp(mps_space_t);
|
||||
extern void mps_space_release(mps_space_t);
|
||||
extern void mps_space_park(mps_space_t);
|
||||
|
|
|
|||
|
|
@ -309,12 +309,14 @@ size_t mps_arena_spare_commit_limit(mps_arena_t mps_arena)
|
|||
return limit;
|
||||
}
|
||||
|
||||
void mps_arena_step(mps_arena_t mps_arena)
|
||||
mps_bool_t mps_arena_step(mps_arena_t mps_arena, double time)
|
||||
{
|
||||
Bool b;
|
||||
Arena arena = (Arena)mps_arena;
|
||||
ArenaEnter(arena);
|
||||
ArenaStep(arena);
|
||||
b = ArenaStep(arena, time);
|
||||
ArenaLeave(arena);
|
||||
return b;
|
||||
}
|
||||
|
||||
void mps_arena_clamp(mps_arena_t mps_arena)
|
||||
|
|
|
|||
247
mps/src/steptest.c
Normal file
247
mps/src/steptest.c
Normal file
|
|
@ -0,0 +1,247 @@
|
|||
/* impl.c.steptest: TEST FOR ARENA CLAMPING AND STEPPING
|
||||
*
|
||||
* $HopeName: !amcss.c(trunk.31) $
|
||||
* Copyright (C) 1998 Harlequin Limited. All rights reserved.
|
||||
*
|
||||
* Based on impl.c.amcss.
|
||||
*/
|
||||
|
||||
#include "fmtdy.h"
|
||||
#include "testlib.h"
|
||||
#include "mpscamc.h"
|
||||
#include "mpsavm.h"
|
||||
#include "mpstd.h"
|
||||
#ifdef MPS_OS_W3
|
||||
#include "mpsw3.h"
|
||||
#endif
|
||||
#include "mps.h"
|
||||
#ifdef MPS_OS_SU
|
||||
#include "ossu.h"
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
|
||||
#define testArenaSIZE ((size_t)64<<20)
|
||||
#define avLEN 3
|
||||
#define exactRootsCOUNT 300
|
||||
#define ambigRootsCOUNT 50
|
||||
#define objCOUNT 1000000
|
||||
/* objNULL needs to be odd so that it's ignored in exactRoots. */
|
||||
#define objNULL ((mps_addr_t)0xDECEA5ED)
|
||||
|
||||
static mps_pool_t pool;
|
||||
static mps_ap_t ap;
|
||||
static mps_addr_t exactRoots[exactRootsCOUNT];
|
||||
static mps_addr_t ambigRoots[ambigRootsCOUNT];
|
||||
|
||||
/* timings */
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/resource.h>
|
||||
|
||||
static double myclock(void)
|
||||
{
|
||||
struct rusage ru;
|
||||
getrusage(RUSAGE_SELF, &ru);
|
||||
return ((ru.ru_utime.tv_sec +
|
||||
ru.ru_stime.tv_sec) * 1000000.0 +
|
||||
(ru.ru_utime.tv_usec) +
|
||||
(ru.ru_stime.tv_usec));
|
||||
}
|
||||
|
||||
double alloc_time, step_time, no_step_time, max_step_time, max_no_step_time, max_alloc_time;
|
||||
|
||||
long steps, no_steps;
|
||||
|
||||
long alloc_bytes;
|
||||
long commit_failures;
|
||||
|
||||
#define CLOCK_TESTS 100000
|
||||
|
||||
static double clock_timing(void)
|
||||
{
|
||||
long i;
|
||||
double t1, t2;
|
||||
|
||||
t2 = 0.0;
|
||||
for (i=0; i<CLOCK_TESTS; ++i) {
|
||||
t1 = myclock();
|
||||
t2 += myclock()-t1;
|
||||
}
|
||||
return t2/CLOCK_TESTS;
|
||||
}
|
||||
|
||||
static mps_addr_t make(void)
|
||||
{
|
||||
size_t length = rnd() % (2*avLEN);
|
||||
size_t size = (length+2) * sizeof(mps_word_t);
|
||||
mps_addr_t p;
|
||||
mps_res_t res;
|
||||
|
||||
alloc_bytes += size;
|
||||
|
||||
for(;;) {
|
||||
int commit_res;
|
||||
double t1 = myclock();
|
||||
MPS_RESERVE_BLOCK(res, p, ap, size);
|
||||
t1 = myclock() - t1;
|
||||
alloc_time += t1;
|
||||
if (t1 > max_alloc_time)
|
||||
max_alloc_time = t1;
|
||||
if(res)
|
||||
die(res, "MPS_RESERVE_BLOCK");
|
||||
res = dylan_init(p, size, exactRoots, exactRootsCOUNT);
|
||||
if(res)
|
||||
die(res, "dylan_init");
|
||||
t1 = myclock();
|
||||
commit_res = mps_commit(ap,p,size);
|
||||
t1 = myclock() - t1;
|
||||
alloc_time += t1;
|
||||
if (t1 > max_alloc_time)
|
||||
max_alloc_time = t1;
|
||||
if (commit_res)
|
||||
break;
|
||||
else
|
||||
++ commit_failures;
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
static void test_step(mps_arena_t arena)
|
||||
{
|
||||
mps_bool_t res;
|
||||
double t1 = myclock();
|
||||
res = mps_arena_step(arena, 0.1);
|
||||
t1 = myclock() - t1;
|
||||
if (res) {
|
||||
if (t1 > max_step_time)
|
||||
max_step_time = t1;
|
||||
step_time += t1;
|
||||
++ steps;
|
||||
} else {
|
||||
if (t1 > max_no_step_time)
|
||||
max_no_step_time = t1;
|
||||
no_step_time += t1;
|
||||
++ no_steps;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void *test(void *arg, size_t s)
|
||||
{
|
||||
mps_arena_t arena;
|
||||
mps_fmt_t format;
|
||||
mps_root_t exactRoot, ambigRoot;
|
||||
unsigned long objs; size_t i;
|
||||
mps_ap_t busy_ap;
|
||||
mps_addr_t busy_init;
|
||||
|
||||
arena = (mps_arena_t)arg;
|
||||
(void)s; /* unused */
|
||||
|
||||
die(dylan_fmt(&format, arena), "fmt_create");
|
||||
|
||||
die(mps_pool_create(&pool, arena, mps_class_amc(), format),
|
||||
"pool_create(amc)");
|
||||
|
||||
die(mps_ap_create(&ap, pool, MPS_RANK_EXACT), "BufferCreate");
|
||||
die(mps_ap_create(&busy_ap, pool, MPS_RANK_EXACT), "BufferCreate");
|
||||
|
||||
for(i=0; i<exactRootsCOUNT; ++i)
|
||||
exactRoots[i] = objNULL;
|
||||
for(i=0; i<ambigRootsCOUNT; ++i)
|
||||
ambigRoots[i] = (mps_addr_t)rnd();
|
||||
|
||||
die(mps_root_create_table_masked(&exactRoot, arena,
|
||||
MPS_RANK_EXACT, (mps_rm_t)0,
|
||||
&exactRoots[0], exactRootsCOUNT,
|
||||
(mps_word_t)1),
|
||||
"root_create_table(exact)");
|
||||
die(mps_root_create_table(&ambigRoot, arena,
|
||||
MPS_RANK_AMBIG, (mps_rm_t)0,
|
||||
&ambigRoots[0], ambigRootsCOUNT),
|
||||
"root_create_table(ambig)");
|
||||
|
||||
/* create an ap, and leave it busy */
|
||||
die(mps_reserve(&busy_init, busy_ap, 64), "mps_reserve busy");
|
||||
|
||||
objs = 0;
|
||||
steps = no_steps = 0;
|
||||
alloc_bytes = 0;
|
||||
commit_failures = 0;
|
||||
alloc_time = step_time = no_step_time = 0.0;
|
||||
max_alloc_time = max_step_time = max_no_step_time = 0.0;
|
||||
|
||||
while(objs < objCOUNT) {
|
||||
size_t r;
|
||||
|
||||
r = rnd();
|
||||
if(r & 1) {
|
||||
i = (r >> 1) % exactRootsCOUNT;
|
||||
if(exactRoots[i] != objNULL)
|
||||
assert(dylan_check(exactRoots[i]));
|
||||
exactRoots[i] = make();
|
||||
if(exactRoots[(exactRootsCOUNT-1) - i] != objNULL)
|
||||
dylan_write(exactRoots[(exactRootsCOUNT-1) - i],
|
||||
exactRoots, exactRootsCOUNT);
|
||||
} else {
|
||||
i = (r >> 1) % ambigRootsCOUNT;
|
||||
ambigRoots[(ambigRootsCOUNT-1) - i] = make();
|
||||
/* Create random interior pointers */
|
||||
ambigRoots[i] = (mps_addr_t)((char *)(ambigRoots[i/2]) + 1);
|
||||
}
|
||||
|
||||
if(objs % 1000 == 0)
|
||||
test_step(arena);
|
||||
|
||||
++objs;
|
||||
}
|
||||
|
||||
printf("%ld objects (%ld bytes) allocated\n", objs, alloc_bytes);
|
||||
printf("commit failed %ld times\n", commit_failures);
|
||||
printf("allocation took %.0f us, mean %.2f us, max %.0f us\n",
|
||||
alloc_time, alloc_time / objs, max_alloc_time);
|
||||
printf("%ld steps took %.0f us, mean %.2f us, max %.0f us\n",
|
||||
steps, step_time, step_time / steps, max_step_time);
|
||||
printf("%ld non-steps took %.0f us, mean %.2f us, max %.0f us\n",
|
||||
no_steps, no_step_time, no_step_time / no_steps, max_no_step_time);
|
||||
|
||||
printf("clock timing %.2f us\n", clock_timing());
|
||||
|
||||
(void)mps_commit(busy_ap, busy_init, 64);
|
||||
mps_ap_destroy(busy_ap);
|
||||
mps_ap_destroy(ap);
|
||||
mps_root_destroy(exactRoot);
|
||||
mps_root_destroy(ambigRoot);
|
||||
mps_pool_destroy(pool);
|
||||
mps_fmt_destroy(format);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
mps_arena_t arena;
|
||||
mps_thr_t thread;
|
||||
void *r;
|
||||
|
||||
randomize(argc, argv);
|
||||
|
||||
die(mps_arena_create(&arena, mps_arena_class_vm(), testArenaSIZE),
|
||||
"arena_create\n");
|
||||
adjust_collection_freq(0.2);
|
||||
die(mps_thread_reg(&thread, arena), "thread_reg");
|
||||
mps_tramp(&r, test, arena, 0);
|
||||
mps_thread_dereg(thread);
|
||||
mps_arena_destroy(arena);
|
||||
|
||||
fflush(stdout); /* synchronize */
|
||||
fprintf(stderr, "\nConclusion: Failed to find any defects.\n");
|
||||
return 0;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue