1
Fork 0
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:
Nick Barnes 2002-05-22 17:11:13 +01:00
parent bf65f05d74
commit eb0b4af2ef
8 changed files with 279 additions and 16 deletions

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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

View file

@ -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:$@ $**

View file

@ -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);

View file

@ -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);

View file

@ -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
View 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;
}