From eb0b4af2ef7626cd1db09f0aff994ee2f88f40d5 Mon Sep 17 00:00:00 2001 From: Nick Barnes Date: Wed, 22 May 2002 17:11:13 +0100 Subject: [PATCH] Incremental step function for mps. Copied from Perforce Change: 29402 ServerID: perforce.ravenbrook.com --- mps/src/action.c | 10 +- mps/src/arena.c | 13 ++- mps/src/comm.gmk | 7 +- mps/src/commpost.nmk | 6 +- mps/src/mpm.h | 4 +- mps/src/mps.h | 2 +- mps/src/mpsi.c | 6 +- mps/src/steptest.c | 247 +++++++++++++++++++++++++++++++++++++++++++ 8 files changed, 279 insertions(+), 16 deletions(-) create mode 100644 mps/src/steptest.c diff --git a/mps/src/action.c b/mps/src/action.c index adc60f62186..55bfb47c9db 100644 --- a/mps/src/action.c +++ b/mps/src/action.c @@ -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; } diff --git a/mps/src/arena.c b/mps/src/arena.c index 697d2b8937d..349d1fd8944 100644 --- a/mps/src/arena.c +++ b/mps/src/arena.c @@ -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; } diff --git a/mps/src/comm.gmk b/mps/src/comm.gmk index eb6968e47b2..b8d6b70afee 100644 --- a/mps/src/comm.gmk +++ b/mps/src/comm.gmk @@ -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 diff --git a/mps/src/commpost.nmk b/mps/src/commpost.nmk index 7db1ed8c065..719295cbfaa 100644 --- a/mps/src/commpost.nmk +++ b/mps/src/commpost.nmk @@ -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:$@ $** diff --git a/mps/src/mpm.h b/mps/src/mpm.h index f950ef10187..8dea271d8c0 100644 --- a/mps/src/mpm.h +++ b/mps/src/mpm.h @@ -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); diff --git a/mps/src/mps.h b/mps/src/mps.h index 2813165bc33..783bf1802e7 100644 --- a/mps/src/mps.h +++ b/mps/src/mps.h @@ -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); diff --git a/mps/src/mpsi.c b/mps/src/mpsi.c index 1e5392aa4f9..3bb1a09258a 100644 --- a/mps/src/mpsi.c +++ b/mps/src/mpsi.c @@ -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) diff --git a/mps/src/steptest.c b/mps/src/steptest.c new file mode 100644 index 00000000000..e66781bb159 --- /dev/null +++ b/mps/src/steptest.c @@ -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 +#include +#include +#include + + +#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 +#include +#include + +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 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> 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; +}