1
Fork 0
mirror of git://git.sv.gnu.org/emacs.git synced 2025-12-24 14:30:43 -08:00

mps br/vmem: simple-chunk-return:

zcoll.c:
 How to get rid of all the objects, so full collect really collects all automatic objects:
   - Rootdrop() helps, but we can still retain a 1.2MB object;
   - stackwipe() does not help much -- these unwanted ambig refs are being left on the stack by MPS code that runs between mps_arena_collect and the flip!
   - therefore StackScan(0/1) to destroy stack+reg root before full collect: it's the only way to be sure.

 Reproducibility:
   - give Make() a random? switch, acted on by df() = diversity function, to allow bypass of rnd();
   - ZRndStateSet, to set the seed for rnd()

 Output:
   - print_M: switchable Mebibytes or Megabytes (more useful, to be honest);
   - get(): don't report message times, it messes up diffs.

 testlib.c/h:
 Reproducibility:
   - fix rnd_state so a rnd_state getter is possible;
   - testlib.h += rnd_state_t, rnd_state(), rnd_state_set(), rnd_state_set_v2()

 trace.c: traceFindGrey diag: no newline please

Copied from Perforce
 Change: 170093
 ServerID: perforce.ravenbrook.com
This commit is contained in:
Richard Kistruck 2010-03-22 23:00:42 +00:00
parent 968eafea90
commit 1ff022cae1
4 changed files with 255 additions and 47 deletions

View file

@ -221,48 +221,100 @@ mps_addr_t rnd_addr(void)
}
/* randomize -- randomize the generator, or initialize to replay */
/* randomize -- randomize the generator, or initialize to replay
*
* There have been 3 versions of the rnd-states reported by this
* function:
*
* 1. before RHSK got his hands on rnd(). These seed values are not
* currently supported, but it might be easy to add support.
*
* 2. v2 states: the published "seed" (state) value was the seed
* *before* the 10 rnds to churn up and separate nearby values
* from time(). This is unfortunate: you can't write a rnd_state
* getter, because it would have to go 10 steps back in time.
*
* 3. v3 states: when autogenerated from time(), the published
* state is that *after* the 10 rnds. Therefore you can get this
* easily, store it, re-use it, etc.
*/
void randomize(int argc, char **argv)
{
int n;
unsigned long seed0;
int i;
int n;
unsigned long seedt;
unsigned long seed0;
if (argc > 1) {
n = sscanf(argv[1], "%lu", &seed0);
Insist(n == 1);
printf("randomize(): resetting initial seed to: %lu.\n", seed0);
printf("randomize(): resetting initial state (v3) to: %lu.\n", seed0);
rnd_state_set(seed0);
} else {
/* time_t uses an arbitrary encoding, but hopefully the low order */
/* 31 bits will have at least one bit changed from run to run. */
seed0 = 1 + time(NULL) % (R_m - 1);
printf("randomize(): choosing initial seed: %lu.\n", seed0);
}
seedt = 1 + time(NULL) % (R_m - 1);
/* The value returned by time() on some OSs may simply be a
* count of seconds: therefore successive runs may start with
* nearby seeds, possibly differing only by 1. So the first value
* returned by rnd() may differ by only 48271. It is conceivable
* that some tests might be able to 'spot' this pattern (for
* example: by using the first rnd() value, mod 100M and rounded
* to multiple of 1024K, as arena size in bytes).
*
* So to mix it up a bit, we do a few iterations now. How many?
* Very roughly, 48271^2 is of the same order as 2^31, so two
* iterations would make the characteristic difference similar to
* the period. Hey, let's go wild and do 10.
*/
rnd_state_set(seedt);
for(i = 0; i < 10; i += 1) {
(void)rnd();
}
seed0 = rnd_state();
printf("randomize(): choosing initial state (v3): %lu.\n", seed0);
rnd_state_set(seed0);
}
}
unsigned long rnd_state(void)
{
return seed;
}
void rnd_state_set(unsigned long seed0)
{
Insist(seed0 < R_m);
Insist(seed0 != 0);
seed = seed0;
rnd_verify(0);
Insist(seed == seed0);
}
/* The 'random' seed is taken from time(), which may simply be a
* count of seconds: therefore successive runs may start with
* nearby seeds, possibly differing only by 1. So the first value
* returned by rnd() may differ by only 48271. It is conceivable
* that some tests might be able to 'spot' this pattern (for
* example: by using the first rnd() value, mod 100M and rounded
* to multiple of 1024K, as arena size in bytes).
*
* So to mix it up a bit, we do a few iterations now. How many?
* Very roughly, 48271^2 is of the same order as 2^31, so two
* iterations would make the characteristic difference similar to
* the period. Hey, let's go wild and do 10.
*/
/* rnd_state_set_2 -- legacy support for v2 rnd states
*
* In v2, the published "seed" (state) value was the seed *before*
* the 10 rnds to churn up and separate nearby values from time().
*
* Set the seed, then convert it to a v3 state by doing those 10 rnds.
*/
void rnd_state_set_v2(unsigned long seed0_v2)
{
int i;
unsigned long seed0;
rnd_state_set(seed0_v2);
for(i = 0; i < 10; i += 1) {
(void)rnd();
}
seed0 = rnd_state();
printf("rnd_state_set_v2(): seed0_v2 = %lu, converted to state_v3 = %lu.\n", seed0_v2, seed0);
rnd_state_set(seed0);
}

View file

@ -138,10 +138,14 @@ extern void verror(const char *format, va_list args);
/* rnd -- random number generator
*
* rnd() generates a sequence of integers in the range [1, 2^31-1].
* rnd() generates a sequence of integers in the range [1, 2^31-2].
*/
extern unsigned long rnd(void);
typedef unsigned long rnd_state_t;
extern rnd_state_t rnd_state(void);
extern void rnd_state_set(rnd_state_t state_v3);
extern void rnd_state_set_v2(rnd_state_t seed0_v2); /* legacy */
/* rnd_verify() -- checks behaviour of rnd() */

View file

@ -974,7 +974,7 @@ static void traceFindGrey_diag(Bool found, Rank rank)
*report_lim++ = this;
*report_lim++ = '\0';
DIAG_SINGLEF(( "traceFindGrey",
"rank sequence: $S\n",
"rank sequence: $S",
(WriteFS)report_array,
NULL ));
}

View file

@ -87,6 +87,10 @@ static void *myrootAmbig[myrootAmbigCOUNT];
#define myrootExactCOUNT 30000
static void *myrootExact[myrootExactCOUNT];
static mps_root_t root_stackreg;
static void *stack_start;
static mps_thr_t stack_thr;
static unsigned long cols(size_t bytes)
{
@ -125,19 +129,28 @@ static void showStatsAscii(size_t notcon, size_t con, size_t live, size_t alimit
}
/* print_M -- print count of bytes as Mebibytes with decimal fraction
/* print_M -- print count of bytes as Mebibytes or Megabytes
*
* Input: 208896
* Output: 0m199
* Print as a whole number, "m" for the decimal point, and
* then the decimal fraction.
*
* Input: 208896
* Output: (Mebibytes) 0m199
* Output: (Megabytes) 0m209
*/
#if 0
#define bPerM (1UL << 20) /* Mebibytes */
#else
#define bPerM (1000000UL) /* Megabytes */
#endif
static void print_M(size_t bytes)
{
size_t M; /* Mebibytes */
double Mfrac; /* fraction of a Mebibyte */
size_t M; /* M thingies */
double Mfrac; /* fraction of an M thingy */
M = bytes / (1UL<<20);
Mfrac = (double)(bytes % (1UL<<20));
Mfrac = (Mfrac / (1UL<<20));
M = bytes / bPerM;
Mfrac = (double)(bytes % bPerM);
Mfrac = (Mfrac / bPerM);
printf("%1lum%03.f", M, Mfrac * 1000);
}
@ -165,6 +178,7 @@ static void showStatsText(size_t notcon, size_t con, size_t live)
/* get -- get messages
*
*/
#define get_print_times 0
static void get(mps_arena_t arena)
{
mps_message_type_t type;
@ -183,8 +197,10 @@ static void get(mps_arena_t arena)
switch(type) {
case mps_message_type_gc_start(): {
mclockBegin = mps_message_clock(arena, message);
#if get_print_times
printf(" %5lu: (%5lu)",
mclockBegin, mclockBegin - mclockEnd);
#endif
printf(" Coll Begin (%s)\n",
mps_message_gc_start_why(arena, message));
break;
@ -198,8 +214,10 @@ static void get(mps_arena_t arena)
mclockEnd = mps_message_clock(arena, message);
#if get_print_times
printf(" %5lu: (%5lu)",
mclockEnd, mclockEnd - mclockBegin);
#endif
printf(" Coll End ");
showStatsText(notcon, con, live);
if(rnd()==0) showStatsAscii(notcon, con, live, alimit);
@ -444,7 +462,21 @@ static void BigdropSmall(mps_arena_t arena, mps_ap_t ap, size_t big, char small_
}
static void Make(mps_arena_t arena, mps_ap_t ap, unsigned keep1in, unsigned keepTotal, unsigned keepRootspace, unsigned sizemethod)
/* df -- diversity function
*
* Either deterministic based on "number", or 'random' (ie. call rnd).
*/
static unsigned long df(unsigned randm, unsigned number)
{
if(randm == 0) {
return number;
} else {
return rnd();
}
}
static void Make(mps_arena_t arena, mps_ap_t ap, unsigned randm, unsigned keep1in, unsigned keepTotal, unsigned keepRootspace, unsigned sizemethod)
{
unsigned keepCount = 0;
unsigned long objCount = 0;
@ -463,7 +495,15 @@ static void Make(mps_arena_t arena, mps_ap_t ap, unsigned keep1in, unsigned keep
}
case 1: {
slots = 2;
if(rnd() % 10000 == 0) {
if(df(randm, objCount) % 10000 == 0) {
printf("*");
slots = 300000;
}
break;
}
case 2: {
slots = 2;
if(df(randm, objCount) % 6661 == 0) { /* prime */
printf("*");
slots = 300000;
}
@ -479,9 +519,9 @@ static void Make(mps_arena_t arena, mps_ap_t ap, unsigned keep1in, unsigned keep
DYLAN_VECTOR_SLOT(v, 0) = DYLAN_INT(objCount);
DYLAN_VECTOR_SLOT(v, 1) = (mps_word_t)NULL;
objCount++;
if(rnd() % keep1in == 0) {
if(df(randm, objCount) % keep1in == 0) {
/* keep this one */
myrootExact[rnd() % keepRootspace] = (void*)v;
myrootExact[df(randm, keepCount) % keepRootspace] = (void*)v;
keepCount++;
}
get(arena);
@ -494,13 +534,76 @@ static void Make(mps_arena_t arena, mps_ap_t ap, unsigned keep1in, unsigned keep
}
static void Rootdrop(char rank_char)
{
unsigned long i;
if(rank_char == 'A') {
for(i = 0; i < myrootAmbigCOUNT; ++i) {
myrootAmbig[i] = NULL;
}
} else if(rank_char == 'E') {
for(i = 0; i < myrootExactCOUNT; ++i) {
myrootExact[i] = NULL;
}
} else {
cdie(0, "Rootdrop: rank must be 'A' or 'E'.\n");
}
}
#define stackwipedepth 50000
static void stackwipe(void)
{
unsigned iw;
unsigned long aw[stackwipedepth];
/* http://xkcd.com/710/ */
/* I don't want my friends to stop calling; I just want the */
/* compiler to stop optimising away my code. */
/* Do you ever get two even numbers next to each other? Hmmmm :-) */
for(iw = 0; iw < stackwipedepth; iw++) {
if((iw & 1) == 0) {
aw[iw] = 1;
} else {
aw[iw] = 0;
}
}
for(iw = 1; iw < stackwipedepth; iw++) {
if(aw[iw - 1] + aw[iw] != 1) {
printf("Errrr....\n");
break;
}
}
}
static void StackScan(mps_arena_t arena, int on)
{
if(on) {
Insist(root_stackreg == NULL);
die(mps_root_create_reg(&root_stackreg, arena,
mps_rank_ambig(), (mps_rm_t)0, stack_thr,
mps_stack_scan_ambig, stack_start, 0),
"root_stackreg");
Insist(root_stackreg != NULL);
} else {
Insist(root_stackreg != NULL);
mps_root_destroy(root_stackreg);
root_stackreg = NULL;
Insist(root_stackreg == NULL);
}
}
/* checksi -- check count of sscanf items is correct
*/
static void checksi(int si, int si_shouldBe, const char *script, const char *scriptAll)
{
if(si != si_shouldBe) {
printf("bad script command %s (full script %s).\n", script, scriptAll);
printf("bad script command (sscanf found wrong number of params) %s (full script %s).\n", script, scriptAll);
cdie(FALSE, "bad script command!");
}
}
@ -521,6 +624,7 @@ static void testscriptC(mps_arena_t arena, mps_ap_t ap, const char *script)
checksi(si, 0, script, scriptAll);
script += sb;
printf(" Collect\n");
stackwipe();
mps_arena_collect(arena);
mps_arena_release(arena);
break;
@ -546,17 +650,48 @@ static void testscriptC(mps_arena_t arena, mps_ap_t ap, const char *script)
break;
}
case 'M': {
unsigned randm = 0;
unsigned keep1in = 0;
unsigned keepTotal = 0;
unsigned keepRootspace = 0;
unsigned sizemethod = 0;
si = sscanf(script, "Make(keep-1-in %u, keep %u, rootspace %u, sizemethod %u)%n",
&keep1in, &keepTotal, &keepRootspace, &sizemethod, &sb);
checksi(si, 4, script, scriptAll);
si = sscanf(script, "Make(random %u, keep-1-in %u, keep %u, rootspace %u, sizemethod %u)%n",
&randm, &keep1in, &keepTotal, &keepRootspace, &sizemethod, &sb);
checksi(si, 5, script, scriptAll);
script += sb;
printf(" Make(keep-1-in %u, keep %u, rootspace %u, sizemethod %u).\n",
keep1in, keepTotal, keepRootspace, sizemethod);
Make(arena, ap, keep1in, keepTotal, keepRootspace, sizemethod);
printf(" Make(random %u, keep-1-in %u, keep %u, rootspace %u, sizemethod %u).\n",
randm, keep1in, keepTotal, keepRootspace, sizemethod);
Make(arena, ap, randm, keep1in, keepTotal, keepRootspace, sizemethod);
break;
}
case 'R': {
char drop_ref = ' ';
si = sscanf(script, "Rootdrop(rank %c)%n",
&drop_ref, &sb);
checksi(si, 1, script, scriptAll);
script += sb;
printf(" Rootdrop(rank %c)\n", drop_ref);
Rootdrop(drop_ref);
break;
}
case 'S': {
unsigned on = 0;
si = sscanf(script, "StackScan(%u)%n",
&on, &sb);
checksi(si, 1, script, scriptAll);
script += sb;
printf(" StackScan(%u)\n", on);
StackScan(arena, on);
break;
}
case 'Z': {
unsigned long s0;
si = sscanf(script, "ZRndStateSet(%lu)%n",
&s0, &sb);
checksi(si, 1, script, scriptAll);
script += sb;
printf(" ZRndStateSet(%lu)\n", s0);
rnd_state_set(s0);
break;
}
case ' ':
@ -603,7 +738,6 @@ static void *testscriptB(void *arg, size_t s)
mps_root_t root_table_Ambig;
mps_root_t root_table_Exact;
mps_ap_t ap;
mps_root_t root_stackreg;
void *stack_starts_here; /* stack scanning starts here */
Insist(s == sizeof(trampDataStruct));
@ -634,9 +768,11 @@ static void *testscriptB(void *arg, size_t s)
die(mps_ap_create(&ap, amc, MPS_RANK_EXACT), "ap_create");
/* root_stackreg: stack & registers are ambiguous roots = mutator's workspace */
stack_start = &stack_starts_here;
stack_thr = thr;
die(mps_root_create_reg(&root_stackreg, arena,
mps_rank_ambig(), (mps_rm_t)0, thr,
mps_stack_scan_ambig, &stack_starts_here, 0),
mps_rank_ambig(), (mps_rm_t)0, stack_thr,
mps_stack_scan_ambig, stack_start, 0),
"root_stackreg");
@ -701,8 +837,8 @@ static void testscriptA(const char *script)
*/
int main(int argc, char **argv)
{
randomize(argc, argv);
/* 1<<19 == 524288 == 1/2 Mebibyte */
/* 16<<20 == 16777216 == 16 Mebibyte */
@ -710,8 +846,24 @@ int main(int argc, char **argv)
/* This is bogus! sizemethod 1 can make a 300,000-slot dylan vector, ie. 1.2MB. */
/* Try 10MB arena */
/* testscriptA("Arena(size 10485760), Make(keep-1-in 5, keep 50000, rootspace 30000, sizemethod 1), Collect."); */
testscriptA("Arena(size 10485760), Make(keep-1-in 5, keep 50000, rootspace 30000, sizemethod 1), Collect,"
"Make(keep-1-in 5, keep 50000, rootspace 30000, sizemethod 1), Collect.");
if(1) {
testscriptA("Arena(size 10485760), "
"ZRndStateSet(239185672), "
"Make(random 1, keep-1-in 5, keep 50000, rootspace 30000, sizemethod 1), Collect, "
"Rootdrop(rank E), StackScan(0), Collect, Collect, StackScan(1), "
"ZRndStateSet(239185672), "
"Make(random 1, keep-1-in 5, keep 50000, rootspace 30000, sizemethod 1), Collect, "
"Rootdrop(rank E), Collect, Collect.");
}
if(0) {
testscriptA("Arena(size 10485760), "
"Make(random 0, keep-1-in 5, keep 50000, rootspace 30000, sizemethod 2), "
"Collect, "
"Rootdrop(rank E), Collect, Collect, "
"Make(random 0, keep-1-in 5, keep 50000, rootspace 30000, sizemethod 2), "
"Collect, "
"Rootdrop(rank E), Collect, Collect.");
}
/* LSP -- Large Segment Padding (job001811)
*