From de8abeac69ec7b8f62645e66392fe8756ec4f0fc Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Tue, 29 Jan 2019 15:04:00 -0500 Subject: [PATCH 01/12] refactors libnoun memory marking, adds optional printfs --- include/noun/allocate.h | 12 +++++++++++- include/noun/jets.h | 2 +- include/noun/manage.h | 2 +- include/noun/nock.h | 2 +- include/noun/vortex.h | 2 +- noun/allocate.c | 40 +++++++++++++++++++++++++++++++++------- noun/jets.c | 26 +++++++++++++++++--------- noun/manage.c | 18 ++++++------------ noun/nock.c | 9 ++++++--- noun/vortex.c | 29 ++++++++++++----------------- vere/raft.c | 2 +- 11 files changed, 90 insertions(+), 54 deletions(-) diff --git a/include/noun/allocate.h b/include/noun/allocate.h index 32a8e8d37..19c2c7d1a 100644 --- a/include/noun/allocate.h +++ b/include/noun/allocate.h @@ -402,6 +402,11 @@ c3_w u3a_mark_noun(u3_noun som); + /* u3a_mark_road(): mark ad-hoc persistent road structures. + */ + c3_w + u3a_mark_road(c3_o pri_o); + /* u3a_sweep(): sweep a fully marked road. */ c3_w @@ -422,11 +427,16 @@ void u3a_lop(c3_w lab_w); - /* u3a_print_memory: print memory amount. + /* u3a_print_memory(): print memory amount. */ void u3a_print_memory(c3_c* cap_c, c3_w wor_w); + /* u3a_maid(): maybe print memory. + */ + c3_w + u3a_maid(c3_o pri_o, c3_c* cap_c, c3_w wor_w); + /* u3a_deadbeef(): write 0xdeadbeef from hat to cap. */ void diff --git a/include/noun/jets.h b/include/noun/jets.h index 16c318c29..fcfd34586 100644 --- a/include/noun/jets.h +++ b/include/noun/jets.h @@ -260,7 +260,7 @@ /* u3j_mark(): mark jet state for gc. */ c3_w - u3j_mark(void); + u3j_mark(c3_o pri_o); /* u3j_free(): free jet state. */ diff --git a/include/noun/manage.h b/include/noun/manage.h index eb11e9401..14619f2bd 100644 --- a/include/noun/manage.h +++ b/include/noun/manage.h @@ -94,7 +94,7 @@ /* u3m_mark(): mark all nouns in the road. */ c3_w - u3m_mark(void); + u3m_mark(c3_o pri_o); /* u3m_grab(): garbage-collect the world, plus extra roots. */ diff --git a/include/noun/nock.h b/include/noun/nock.h index ff376a875..087ef802f 100644 --- a/include/noun/nock.h +++ b/include/noun/nock.h @@ -110,7 +110,7 @@ /* u3n_mark(): mark bytecode cache. */ c3_w - u3n_mark(void); + u3n_mark(c3_o pri_o); /* u3n_free(): free bytecode cache. */ diff --git a/include/noun/vortex.h b/include/noun/vortex.h index dfb7e8bae..bcee4b636 100644 --- a/include/noun/vortex.h +++ b/include/noun/vortex.h @@ -147,4 +147,4 @@ /* u3v_mark(): mark arvo kernel. */ c3_w - u3v_mark(void); + u3v_mark(c3_o pri_o); diff --git a/noun/allocate.c b/noun/allocate.c index 7f2272439..fabc3bf3f 100644 --- a/noun/allocate.c +++ b/noun/allocate.c @@ -1614,12 +1614,12 @@ u3a_mark_noun(u3_noun som) } /* u3a_print_memory: print memory amount. +** +** Must print to stderr -- not uH/uL (because loja allocates). */ void u3a_print_memory(c3_c* cap_c, c3_w wor_w) { - FILE *fil_f = u3_term_io_hija(); - c3_w byt_w = (wor_w * 4); c3_w gib_w = (byt_w / 1000000000); c3_w mib_w = (byt_w % 1000000000) / 1000000; @@ -1628,20 +1628,46 @@ u3a_print_memory(c3_c* cap_c, c3_w wor_w) if ( byt_w ) { if ( gib_w ) { - fprintf(fil_f, "%s: GB/%d.%03d.%03d.%03d\r\n", + fprintf(stderr, "%s: GB/%d.%03d.%03d.%03d\r\n", cap_c, gib_w, mib_w, kib_w, bib_w); } else if ( mib_w ) { - fprintf(fil_f, "%s: MB/%d.%03d.%03d\r\n", cap_c, mib_w, kib_w, bib_w); + fprintf(stderr, "%s: MB/%d.%03d.%03d\r\n", cap_c, mib_w, kib_w, bib_w); } else if ( kib_w ) { - fprintf(fil_f, "%s: KB/%d.%03d\r\n", cap_c, kib_w, bib_w); + fprintf(stderr, "%s: KB/%d.%03d\r\n", cap_c, kib_w, bib_w); } else if ( bib_w ) { - fprintf(fil_f, "%s: B/%d\r\n", cap_c, bib_w); + fprintf(stderr, "%s: B/%d\r\n", cap_c, bib_w); } } - u3_term_io_loja(0); +} + +/* u3a_maid(): maybe print memory. +*/ +c3_w +u3a_maid(c3_o pri_o, c3_c* cap_c, c3_w wor_w) +{ + if ( c3y == pri_o ) { + u3a_print_memory(cap_c, wor_w); + } + return wor_w; +} + +/* u3a_mark_road(): mark ad-hoc persistent road structures. +*/ +c3_w +u3a_mark_road(c3_o pri_o) +{ + c3_w tot_w = 0; + tot_w += u3a_maid(pri_o, " namespace", u3a_mark_noun(u3R->ski.gul)); + tot_w += u3a_maid(pri_o, " trace stack", u3a_mark_noun(u3R->bug.tax)); + tot_w += u3a_maid(pri_o, " trace buffer", u3a_mark_noun(u3R->bug.mer)); + tot_w += u3a_maid(pri_o, " profile batteries", u3a_mark_noun(u3R->pro.don)); + tot_w += u3a_maid(pri_o, " profile doss", u3a_mark_noun(u3R->pro.day)); + tot_w += u3a_maid(pri_o, " new profile trace", u3a_mark_noun(u3R->pro.trace)); + tot_w += u3a_maid(pri_o, " memoization cache", u3h_mark(u3R->cax.har_p)); + return u3a_maid(pri_o, "total road stuff", tot_w); } /* u3a_sweep(): sweep a fully marked road. diff --git a/noun/jets.c b/noun/jets.c index 67b15dccb..8f887067e 100644 --- a/noun/jets.c +++ b/noun/jets.c @@ -2250,18 +2250,26 @@ _cj_mark_hank(u3_noun kev, void* dat) /* u3j_mark(): mark jet state for gc. */ c3_w -u3j_mark(void) +u3j_mark(c3_o pri_o) { c3_w tot_w = 0; - tot_w += u3h_mark(u3R->jed.war_p); - tot_w += u3h_mark(u3R->jed.cod_p); - tot_w += u3h_mark(u3R->jed.han_p); - tot_w += u3h_mark(u3R->jed.bas_p); - u3h_walk_with(u3R->jed.han_p, _cj_mark_hank, &tot_w); - if ( u3R == &(u3H->rod_u) ) { - tot_w += u3h_mark(u3R->jed.hot_p); + + tot_w += u3a_maid(pri_o, " warm jet state", u3h_mark(u3R->jed.war_p)); + tot_w += u3a_maid(pri_o, " cold jet state", u3h_mark(u3R->jed.cod_p)); + tot_w += u3a_maid(pri_o, " hank cache", u3h_mark(u3R->jed.han_p)); + tot_w += u3a_maid(pri_o, " battery hash cache", u3h_mark(u3R->jed.bas_p)); + + { + c3_w han_w = 0; + u3h_walk_with(u3R->jed.han_p, _cj_mark_hank, &han_w); + tot_w += u3a_maid(pri_o, " call site cache", han_w); } - return tot_w; + + if ( u3R == &(u3H->rod_u) ) { + tot_w += u3a_maid(pri_o, " hot jet state", u3h_mark(u3R->jed.hot_p)); + } + + return u3a_maid(pri_o, "total jet stuff", tot_w); } /* _cj_free_hank(): free hank cache. diff --git a/noun/manage.c b/noun/manage.c index 7d3517da3..2a1d2576c 100644 --- a/noun/manage.c +++ b/noun/manage.c @@ -491,18 +491,13 @@ _pave_parts(void) /* u3m_mark(): mark all nouns in the road. */ c3_w -u3m_mark(void) +u3m_mark(c3_o pri_o) { c3_w tot_w = 0; - tot_w += u3j_mark(); - tot_w += u3n_mark(); - tot_w += u3a_mark_noun(u3R->ski.gul); - tot_w += u3a_mark_noun(u3R->bug.tax); - tot_w += u3a_mark_noun(u3R->bug.mer); - tot_w += u3a_mark_noun(u3R->pro.don); - tot_w += u3a_mark_noun(u3R->pro.trace); - tot_w += u3a_mark_noun(u3R->pro.day); - tot_w += u3h_mark(u3R->cax.har_p); + tot_w += u3v_mark(pri_o); + tot_w += u3j_mark(pri_o); + tot_w += u3n_mark(pri_o); + tot_w += u3a_mark_road(pri_o); return tot_w; } @@ -1151,8 +1146,7 @@ u3m_grab(u3_noun som, ...) // terminate with u3_none // u3h_free(u3R->cax.har_p); // u3R->cax.har_p = u3h_new(); - u3v_mark(); - u3m_mark(); + u3m_mark(c3n); { va_list vap; u3_noun tur; diff --git a/noun/nock.c b/noun/nock.c index a0affa029..aa7472d0d 100644 --- a/noun/nock.c +++ b/noun/nock.c @@ -2556,12 +2556,15 @@ _n_bam(u3_noun kev, void* dat) /* u3n_mark(): mark the bytecode cache for gc. */ c3_w -u3n_mark() +u3n_mark(c3_o pri_o) { - c3_w bam_w = 0; + c3_w bam_w = 0, har_w = 0; u3p(u3h_root) har_p = u3R->byc.har_p; u3h_walk_with(har_p, _n_bam, &bam_w); - return bam_w + u3h_mark(har_p); + + bam_w = u3a_maid(pri_o, " bytecode programs", bam_w); + har_w = u3a_maid(pri_o, " bytecode cache", u3h_mark(har_p)); + return u3a_maid(pri_o, "total nock stuff", bam_w + har_w); } /* _n_feb(): u3h_walk helper for u3n_bree diff --git a/noun/vortex.c b/noun/vortex.c index b9a1cc5d4..b1aee1f7e 100644 --- a/noun/vortex.c +++ b/noun/vortex.c @@ -405,24 +405,19 @@ _cv_mark_ova(u3p(u3v_cart) egg_p) /* u3v_mark(): mark arvo kernel. */ c3_w -u3v_mark(void) +u3v_mark(c3_o pri_o) { + u3v_arvo* arv_u = &(u3H->arv_u); c3_w tot_w = 0; - u3v_arvo* arv_u = &(u3H->arv_u); - - tot_w += u3a_mark_noun(arv_u->yot); - tot_w += u3a_mark_noun(arv_u->now); - tot_w += u3a_mark_noun(arv_u->wen); - tot_w += u3a_mark_noun(arv_u->sen); - tot_w += u3a_mark_noun(arv_u->own); - - tot_w += u3a_mark_noun(arv_u->roe); - tot_w += u3a_mark_noun(arv_u->key); - - tot_w += u3a_mark_noun(arv_u->roc); - - tot_w += _cv_mark_ova(arv_u->ova.egg_p); - - return tot_w; + tot_w += u3a_maid(pri_o, " wish cache", u3a_mark_noun(arv_u->yot)); + tot_w += u3a_maid(pri_o, " date", u3a_mark_noun(arv_u->now)); + tot_w += u3a_maid(pri_o, " formatted date", u3a_mark_noun(arv_u->wen)); + tot_w += u3a_maid(pri_o, " instance string", u3a_mark_noun(arv_u->sen)); + tot_w += u3a_maid(pri_o, " identity", u3a_mark_noun(arv_u->own)); + tot_w += u3a_maid(pri_o, " pending events", u3a_mark_noun(arv_u->roe)); + tot_w += u3a_maid(pri_o, " event-log key", u3a_mark_noun(arv_u->key)); + tot_w += u3a_maid(pri_o, " kernel", u3a_mark_noun(arv_u->roc)); + tot_w += u3a_maid(pri_o, " egg basket", _cv_mark_ova(arv_u->ova.egg_p)); + return u3a_maid(pri_o, "total arvo stuff", tot_w); } diff --git a/vere/raft.c b/vere/raft.c index e86c90151..1f6830aae 100644 --- a/vere/raft.c +++ b/vere/raft.c @@ -1865,7 +1865,7 @@ _raft_grab(u3_noun ova) fprintf(stderr, "space profile: "); _raft_print_memory(sac_w); - utv_w = u3v_mark(); + utv_w = u3v_mark(c3n); fprintf(stderr, "arvo stuff: "); _raft_print_memory(utv_w); From 74787c5eb84aefb97920be5c0f820a3790bb523b Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Tue, 29 Jan 2019 16:42:34 -0500 Subject: [PATCH 02/12] refactors memory leak printfs in u3a_sweep() --- noun/allocate.c | 128 +++++++++++++++++++++++++++++++++--------------- 1 file changed, 88 insertions(+), 40 deletions(-) diff --git a/noun/allocate.c b/noun/allocate.c index fabc3bf3f..0c4db4804 100644 --- a/noun/allocate.c +++ b/noun/allocate.c @@ -1670,6 +1670,86 @@ u3a_mark_road(c3_o pri_o) return u3a_maid(pri_o, "total road stuff", tot_w); } +static c3_c* +_ca_print_box(u3a_box* box_u) +{ + if ( u3a_minimum < box_u->siz_w ) { + // fprintf(stderr, "print box 1\r\n"); + return u3m_pretty(u3a_to_pug(u3a_outa(u3a_boxto(box_u)))); + } + else { + // this might not be a cell, but we can use the struct to inspect further + // + u3a_cell* cel_u = (u3a_cell*)box_u; + + // this condition potentially corresponds to an indirect atom of only one word + // + if ( (1 == (c3_w)cel_u->hed) && + (0x80000000 & (c3_w)cel_u->tel) ) + { + // this might not be right, but we know it's safe + // + // fprintf(stderr, "print box 2\r\n"); + return u3m_pretty(u3a_to_pug(u3a_outa(u3a_boxto(box_u)))); + } + + // fprintf(stderr, "print box 3 %x [%u %u]\r\n", u3a_to_pom(u3a_outa(u3a_boxto(box_u))), cel_u->hed, cel_u->tel); + return u3m_pretty(u3a_to_pom(u3a_outa(u3a_boxto(box_u)))); + } +} + +#ifdef U3_MEMORY_DEBUG + +static void +_ca_print_leak(c3_c* cap_c, u3a_box* box_u, c3_w eus_w, c3_w use_w) +{ + c3_c* dat_c = _ca_print_box(box_u); + + fprintf(stderr, "%s: %p mug=%x (marked=%u swept=%u)\r\n", + cap_c, box_u, ((u3a_noun *)(u3a_boxto(box_u)))->mug_w, + eus_w, use_w); + + if ( box_u->cod_w ) { + u3m_p(" code", box_u->cod_w); + } + + u3a_print_memory(" size", box_u->siz_w); + fprintf(stderr, " data: %s\r\n", dat_c); + + free(dat_c); +} + +#else + +static void +_ca_print_leak(c3_c* cap_c, u3a_box* box_u, c3_ws use_ws) +{ + c3_c* dat_c = _ca_print_box(box_u); + + fprintf(stderr, "%s: %p mug=%x swept=%d\r\n", + cap_c, box_u, ((u3a_noun *)(u3a_boxto(box_u)))->mug_w, use_ws); + + u3a_print_memory(" size", box_u->siz_w); + fprintf(stderr, " data: %s\r\n", dat_c); + +#if 0 + /* For those times when you've really just got to crack open + * the box and see what's inside + */ + { + int i; + for ( i = 0; i < box_u->siz_w; i++ ) { + printf("%08x ", (unsigned int)(((c3_w*)box_u)[i])); + } + printf("\r\n"); + } +#endif + + free(dat_c); +} + +#endif + /* u3a_sweep(): sweep a fully marked road. */ c3_w @@ -1726,7 +1806,7 @@ u3a_sweep(void) /* I suspect these printfs fail hilariously in the case * of non-direct atoms. We shouldn't unconditionally run * u3a_to_pom(). In general, the condition - * box_u->siz_w > u3a_mimimum is sufficient, but not necessary, + * box_u->siz_w > u3a_minimum is sufficient, but not necessary, * for the box to represent an atom. The atoms between * 2^31 and 2^32 are the exceptions. * @@ -1737,34 +1817,20 @@ u3a_sweep(void) if ( box_u->use_w != box_u->eus_w ) { if ( box_u->eus_w != 0 ) { if ( box_u->use_w == 0 ) { - printf("dank %p (%d, %d)\r\n", box_u, box_u->use_w, box_u->eus_w); + _ca_print_leak("dank", box_u, box_u->eus_w, box_u->use_w); } else { - printf("weak %p %x (cell) %x (%d, %d)\r\n", - box_u, - (u3_noun)u3a_to_pom(u3a_outa(u3a_boxto(box_w))), - ((u3a_noun *)(u3a_boxto(box_w)))->mug_w, - box_u->use_w, box_u->eus_w); - u3a_print_memory("weak (minimum)", box_u->siz_w); - // u3m_p("weak", u3a_to_pom(u3a_outa(u3a_boxto(box_w)))); + _ca_print_leak("weak", box_u, box_u->eus_w, box_u->use_w); } + weq_w += box_u->siz_w; } else { - printf("leak %p %x (cell)/%x (%d)\r\n", - box_u, - (u3_noun)u3a_to_pom(u3a_outa(u3a_boxto(box_w))), - ((u3a_noun *)(u3a_boxto(box_w)))->mug_w - ? ((u3a_noun *)(u3a_boxto(box_w)))->mug_w - : u3r_mug(u3a_to_pom(u3a_outa(u3a_boxto(box_w)))), - box_u->use_w); - u3a_print_memory("leak (minimum)", box_u->siz_w); - // u3m_p("leak", u3a_to_pom(u3a_outa(u3a_boxto(box_w)))); + _ca_print_leak("weak", box_u, box_u->eus_w, box_u->use_w); + leq_w += box_u->siz_w; } - if ( box_u->cod_w ) { - u3m_p(" code", box_u->cod_w); - } + box_u->use_w = box_u->eus_w; } else { @@ -1777,25 +1843,7 @@ u3a_sweep(void) c3_ws use_ws = (c3_ws)box_u->use_w; if ( use_ws > 0 ) { - printf("leak %p %x\r\n", - box_u, - ((u3a_noun *)(u3a_boxto(box_w)))->mug_w - ? ((u3a_noun *)(u3a_boxto(box_w)))->mug_w - : u3r_mug(u3a_to_pom(u3a_outa(u3a_boxto(box_w))))); - // u3a_print_memory("leak (minimum)", box_u->siz_w); - -#if 0 - /* For those times when you've really just got to crack open - * the box and see what's inside - */ - { - int i; - for ( i = 0; i < box_u->siz_w; i++ ) { - printf("%08x ", (unsigned int)(((c3_w*)box_u)[i])); - } - printf("\r\n"); - } -#endif + _ca_print_leak("leak", box_u, use_ws); leq_w += box_u->siz_w; box_u->use_w = 0; From b99598490992cd58167d4b41feb1924888de2b07 Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Tue, 29 Jan 2019 16:46:09 -0500 Subject: [PATCH 03/12] adds comment explaining u3a_minimum --- include/noun/allocate.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/noun/allocate.h b/include/noun/allocate.h index 19c2c7d1a..0259ee5ec 100644 --- a/include/noun/allocate.h +++ b/include/noun/allocate.h @@ -25,6 +25,8 @@ # define u3a_bytes (c3_w)((1 << (2 + u3a_bits))) /* u3a_minimum: minimum number of words in a box. + ** + ** wiseof(u3a_cell) + wiseof(u3a_box) + 1 (trailing siz_w) */ #ifdef U3_MEMORY_DEBUG # define u3a_minimum 8 From f544db84e715e497588bd93c0ce304563946b3c9 Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Tue, 29 Jan 2019 17:47:49 -0500 Subject: [PATCH 04/12] refactors and clarifies heuristic printing of an allocation box --- noun/allocate.c | 109 +++++++++++++++++++++++++++++------------------- 1 file changed, 67 insertions(+), 42 deletions(-) diff --git a/noun/allocate.c b/noun/allocate.c index 0c4db4804..43b05e06e 100644 --- a/noun/allocate.c +++ b/noun/allocate.c @@ -1670,53 +1670,87 @@ u3a_mark_road(c3_o pri_o) return u3a_maid(pri_o, "total road stuff", tot_w); } +/* _ca_print_box(): heuristically print the contents of an allocation box. +*/ static c3_c* _ca_print_box(u3a_box* box_u) { - if ( u3a_minimum < box_u->siz_w ) { - // fprintf(stderr, "print box 1\r\n"); - return u3m_pretty(u3a_to_pug(u3a_outa(u3a_boxto(box_u)))); - } - else { - // this might not be a cell, but we can use the struct to inspect further - // - u3a_cell* cel_u = (u3a_cell*)box_u; + // the loom offset pointing to the contents of box_u + // + c3_w box_w = u3a_outa(u3a_boxto(box_u)); + // box_u might not be a cell, we use the struct to inspect further + // + u3a_cell* cel_u = (u3a_cell*)box_u; - // this condition potentially corresponds to an indirect atom of only one word + if ( // a cell will never be bigger than the minimum allocation size + // + (u3a_minimum < box_u->siz_w) || + // this condition being true potentially corresponds to + // box_u containing an indirect atom of only one word. + // if the condition is false, we know box_u contains a cell. + // + ( (1 == (c3_w)cel_u->hed) && + (0x80000000 & (c3_w)cel_u->tel) ) ) + { + // box_u might not be an indirect atom, + // but it's always safe to print it as if it is one // - if ( (1 == (c3_w)cel_u->hed) && - (0x80000000 & (c3_w)cel_u->tel) ) - { - // this might not be right, but we know it's safe - // - // fprintf(stderr, "print box 2\r\n"); - return u3m_pretty(u3a_to_pug(u3a_outa(u3a_boxto(box_u)))); + u3a_atom* vat_u = (u3a_atom*)box_u; + u3_atom veb = u3a_to_pug(box_w); + + // skip atoms larger than 10 words + // XX print mugs or something + // + if ( 10 > vat_u->len_w ) { +#if 0 + /* For those times when you've really just got to crack open + * the box and see what's inside + */ + { + int i; + for ( i = 0; i < box_u->siz_w; i++ ) { + printf("%08x ", (unsigned int)(((c3_w*)box_u)[i])); + } + printf("\r\n"); + } +#endif + return 0; } - // fprintf(stderr, "print box 3 %x [%u %u]\r\n", u3a_to_pom(u3a_outa(u3a_boxto(box_u))), cel_u->hed, cel_u->tel); - return u3m_pretty(u3a_to_pom(u3a_outa(u3a_boxto(box_u)))); + return u3m_pretty(veb); + } + else { + // box_u is definitely a cell + // + return u3m_pretty(u3a_to_pom(box_w)); } } +/* _ca_print_leak(): print the details of a leaked allocation box. +*/ #ifdef U3_MEMORY_DEBUG static void _ca_print_leak(c3_c* cap_c, u3a_box* box_u, c3_w eus_w, c3_w use_w) { - c3_c* dat_c = _ca_print_box(box_u); - fprintf(stderr, "%s: %p mug=%x (marked=%u swept=%u)\r\n", - cap_c, box_u, ((u3a_noun *)(u3a_boxto(box_u)))->mug_w, - eus_w, use_w); + cap_c, + box_u, + ((u3a_noun *)(u3a_boxto(box_u)))->mug_w, + eus_w, + use_w); if ( box_u->cod_w ) { u3m_p(" code", box_u->cod_w); } u3a_print_memory(" size", box_u->siz_w); - fprintf(stderr, " data: %s\r\n", dat_c); - free(dat_c); + { + c3_c* dat_c = _ca_print_box(box_u); + fprintf(stderr, " data: %s\r\n", dat_c); + free(dat_c); + } } #else @@ -1724,28 +1758,19 @@ _ca_print_leak(c3_c* cap_c, u3a_box* box_u, c3_w eus_w, c3_w use_w) static void _ca_print_leak(c3_c* cap_c, u3a_box* box_u, c3_ws use_ws) { - c3_c* dat_c = _ca_print_box(box_u); - fprintf(stderr, "%s: %p mug=%x swept=%d\r\n", - cap_c, box_u, ((u3a_noun *)(u3a_boxto(box_u)))->mug_w, use_ws); + cap_c, + box_u, + ((u3a_noun *)(u3a_boxto(box_u)))->mug_w, + use_ws); u3a_print_memory(" size", box_u->siz_w); - fprintf(stderr, " data: %s\r\n", dat_c); -#if 0 - /* For those times when you've really just got to crack open - * the box and see what's inside - */ - { - int i; - for ( i = 0; i < box_u->siz_w; i++ ) { - printf("%08x ", (unsigned int)(((c3_w*)box_u)[i])); - } - printf("\r\n"); - } -#endif - - free(dat_c); + { + c3_c* dat_c = _ca_print_box(box_u); + fprintf(stderr, " data: %s\r\n", dat_c); + free(dat_c); + } } #endif From e98be79bdc51e3abcb9a1a41057a7396d01e0ef5 Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Tue, 29 Jan 2019 16:37:32 -0500 Subject: [PATCH 05/12] fixes |mass, unifying the implementation with u3m_grab() --- vere/raft.c | 80 ++++++++++++----------------------------------------- 1 file changed, 18 insertions(+), 62 deletions(-) diff --git a/vere/raft.c b/vere/raft.c index 1f6830aae..28565c528 100644 --- a/vere/raft.c +++ b/vere/raft.c @@ -1690,7 +1690,9 @@ void _raft_spac(c3_w n) (fprintf(stderr," ")); } -/* _raft_print_memory: print memory amount. cf u3a_print_memory(). +/* _raft_print_memory: print memory amount. +** +** Helper for _raft_prof(), just an un-captioned u3a_print_memory(). */ void _raft_print_memory(c3_w wor_w) @@ -1843,85 +1845,39 @@ _raft_prof(u3p(u3h_root) hax, c3_w den, u3_noun mas) /* _raft_grab(): garbage collect, checking for profiling. RETAIN. */ static void -_raft_grab(u3_noun ova) +_raft_grab(u3_noun rus) { if ( u3_nul != u3A->sac ) { - c3_w usr_w = 0, ova_w = 0, sac_w = 0, utv_w = 0, utm_w = 0, wep_w = 0, - har_w = 0, das_w = 0, gul_w = 0, tax_w = 0, mer_w = 0, don_w = 0, - day_w = 0, car_w = 0; + c3_w usr_w = 0, man_w = 0, ova_w = 0, sac_w = 0; c3_assert( u3R == &(u3H->rod_u) ); fprintf(stderr, "\r\n"); usr_w = _raft_prof(u3_nul, 0, u3A->sac); - fprintf(stderr, "total userspace: "); - _raft_print_memory(usr_w); + u3a_print_memory("total userspace", usr_w); - ova_w = u3a_mark_noun(ova); - fprintf(stderr, "effects list: "); - _raft_print_memory(ova_w); + man_w = u3m_mark(c3y); + + ova_w = u3a_mark_noun(rus); + u3a_print_memory("event & effects", ova_w); sac_w = u3a_mark_noun(u3A->sac); - fprintf(stderr, "space profile: "); - _raft_print_memory(sac_w); + u3a_print_memory("space profile", sac_w); - utv_w = u3v_mark(c3n); - fprintf(stderr, "arvo stuff: "); - _raft_print_memory(utv_w); + u3a_print_memory("total marked", usr_w + man_w + ova_w + sac_w); - har_w = u3h_mark(u3R->jed.war_p); - fprintf(stderr, " warm jet state: "); - _raft_print_memory(har_w); + u3a_print_memory("sweep", u3a_sweep()); - das_w = u3h_mark(u3R->jed.cod_p); - fprintf(stderr, " cold jet state: "); - _raft_print_memory(das_w); - - gul_w = u3a_mark_noun(u3R->ski.gul); - fprintf(stderr, " namespace: "); - _raft_print_memory(gul_w); - - tax_w = u3a_mark_noun(u3R->bug.tax); - fprintf(stderr, " trace stack list: "); - _raft_print_memory(tax_w); - - mer_w = u3a_mark_noun(u3R->bug.mer); - fprintf(stderr, " trace stack buffer: "); - _raft_print_memory(mer_w); - - don_w = u3a_mark_noun(u3R->pro.don); - fprintf(stderr, " profile battery list: "); - _raft_print_memory(don_w); - - day_w = u3a_mark_noun(u3R->pro.day); - fprintf(stderr, " profile doss: "); - _raft_print_memory(day_w); - - car_w = u3h_mark(u3R->cax.har_p); - fprintf(stderr, " memoization: "); - _raft_print_memory(car_w); - - utm_w = har_w + das_w + gul_w + tax_w + mer_w + don_w + day_w + car_w; - fprintf(stderr, "total road stuff: "); - _raft_print_memory(utm_w); - - fprintf(stderr, "total marked: "); - _raft_print_memory(usr_w + ova_w + sac_w + utv_w + utm_w); - - wep_w = u3a_sweep(); - fprintf(stderr, "sweep: "); - _raft_print_memory(wep_w); - - u3h_free(u3R->cax.har_p); - u3R->cax.har_p = u3h_new(); + // u3h_free(u3R->cax.har_p); + // u3R->cax.har_p = u3h_new(); u3z(u3A->sac); u3A->sac = u3_nul; + + uL(fprintf(uH, "\n")); } } -int FOO; - /* _raft_crop(): Delete finished events. */ static void @@ -2062,7 +2018,7 @@ u3_raft_chip(void) } _raft_kick(u3k(vir)); - _raft_grab(vir); + _raft_grab(rus); u3z(rus); } From 348fc093a89ae4cb85f2ae515323f3f61694e995 Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Tue, 29 Jan 2019 17:33:53 -0500 Subject: [PATCH 06/12] [CI] run |mass after +test --- .travis/test.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.travis/test.js b/.travis/test.js index 987cc42d3..b4c443f64 100644 --- a/.travis/test.js +++ b/.travis/test.js @@ -38,6 +38,13 @@ Promise.resolve(urbit) }) .then(actions.safeBoot) .then(actions.test) +.then(function(){ + return urbit.line("|mass") + .then(function(){ + return urbit.expectEcho("%ran-mass") + .then(function(){ return urbit.resetListeners(); }) + }) +}) .then(exit) .catch(function(err){ // we still exit 0, Arvo errors are not our fault ... From 7ce31c1a59852efa2d6ddc1f32bf7e1a90472297 Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Tue, 29 Jan 2019 21:48:20 -0500 Subject: [PATCH 07/12] threads output file pointer through memory marking and printing --- include/noun/allocate.h | 6 ++-- include/noun/jets.h | 2 +- include/noun/manage.h | 2 +- include/noun/nock.h | 2 +- include/noun/vortex.h | 2 +- noun/allocate.c | 60 +++++++++++++++---------------- noun/events.c | 4 +-- noun/jets.c | 16 ++++----- noun/manage.c | 16 ++++----- noun/nock.c | 8 ++--- noun/vortex.c | 22 ++++++------ vere/raft.c | 78 +++++++++++++++++++++++------------------ 12 files changed, 114 insertions(+), 104 deletions(-) diff --git a/include/noun/allocate.h b/include/noun/allocate.h index 0259ee5ec..dcd3a0f81 100644 --- a/include/noun/allocate.h +++ b/include/noun/allocate.h @@ -407,7 +407,7 @@ /* u3a_mark_road(): mark ad-hoc persistent road structures. */ c3_w - u3a_mark_road(c3_o pri_o); + u3a_mark_road(FILE* fil_u); /* u3a_sweep(): sweep a fully marked road. */ @@ -432,12 +432,12 @@ /* u3a_print_memory(): print memory amount. */ void - u3a_print_memory(c3_c* cap_c, c3_w wor_w); + u3a_print_memory(FILE* fil_u, c3_c* cap_c, c3_w wor_w); /* u3a_maid(): maybe print memory. */ c3_w - u3a_maid(c3_o pri_o, c3_c* cap_c, c3_w wor_w); + u3a_maid(FILE* fil_u, c3_c* cap_c, c3_w wor_w); /* u3a_deadbeef(): write 0xdeadbeef from hat to cap. */ diff --git a/include/noun/jets.h b/include/noun/jets.h index fcfd34586..3abc5026f 100644 --- a/include/noun/jets.h +++ b/include/noun/jets.h @@ -260,7 +260,7 @@ /* u3j_mark(): mark jet state for gc. */ c3_w - u3j_mark(c3_o pri_o); + u3j_mark(FILE* fil_u); /* u3j_free(): free jet state. */ diff --git a/include/noun/manage.h b/include/noun/manage.h index 14619f2bd..16fa82847 100644 --- a/include/noun/manage.h +++ b/include/noun/manage.h @@ -94,7 +94,7 @@ /* u3m_mark(): mark all nouns in the road. */ c3_w - u3m_mark(c3_o pri_o); + u3m_mark(FILE* fil_u); /* u3m_grab(): garbage-collect the world, plus extra roots. */ diff --git a/include/noun/nock.h b/include/noun/nock.h index 087ef802f..bd0ca7e47 100644 --- a/include/noun/nock.h +++ b/include/noun/nock.h @@ -110,7 +110,7 @@ /* u3n_mark(): mark bytecode cache. */ c3_w - u3n_mark(c3_o pri_o); + u3n_mark(FILE* fil_u); /* u3n_free(): free bytecode cache. */ diff --git a/include/noun/vortex.h b/include/noun/vortex.h index bcee4b636..a7aaf2e28 100644 --- a/include/noun/vortex.h +++ b/include/noun/vortex.h @@ -147,4 +147,4 @@ /* u3v_mark(): mark arvo kernel. */ c3_w - u3v_mark(c3_o pri_o); + u3v_mark(FILE* fil_u); diff --git a/noun/allocate.c b/noun/allocate.c index 43b05e06e..94515d47d 100644 --- a/noun/allocate.c +++ b/noun/allocate.c @@ -1614,12 +1614,12 @@ u3a_mark_noun(u3_noun som) } /* u3a_print_memory: print memory amount. -** -** Must print to stderr -- not uH/uL (because loja allocates). */ void -u3a_print_memory(c3_c* cap_c, c3_w wor_w) +u3a_print_memory(FILE* fil_u, c3_c* cap_c, c3_w wor_w) { + c3_assert( 0 != fil_u ); + c3_w byt_w = (wor_w * 4); c3_w gib_w = (byt_w / 1000000000); c3_w mib_w = (byt_w % 1000000000) / 1000000; @@ -1628,17 +1628,17 @@ u3a_print_memory(c3_c* cap_c, c3_w wor_w) if ( byt_w ) { if ( gib_w ) { - fprintf(stderr, "%s: GB/%d.%03d.%03d.%03d\r\n", + fprintf(fil_u, "%s: GB/%d.%03d.%03d.%03d\r\n", cap_c, gib_w, mib_w, kib_w, bib_w); } else if ( mib_w ) { - fprintf(stderr, "%s: MB/%d.%03d.%03d\r\n", cap_c, mib_w, kib_w, bib_w); + fprintf(fil_u, "%s: MB/%d.%03d.%03d\r\n", cap_c, mib_w, kib_w, bib_w); } else if ( kib_w ) { - fprintf(stderr, "%s: KB/%d.%03d\r\n", cap_c, kib_w, bib_w); + fprintf(fil_u, "%s: KB/%d.%03d\r\n", cap_c, kib_w, bib_w); } else if ( bib_w ) { - fprintf(stderr, "%s: B/%d\r\n", cap_c, bib_w); + fprintf(fil_u, "%s: B/%d\r\n", cap_c, bib_w); } } } @@ -1646,10 +1646,10 @@ u3a_print_memory(c3_c* cap_c, c3_w wor_w) /* u3a_maid(): maybe print memory. */ c3_w -u3a_maid(c3_o pri_o, c3_c* cap_c, c3_w wor_w) +u3a_maid(FILE* fil_u, c3_c* cap_c, c3_w wor_w) { - if ( c3y == pri_o ) { - u3a_print_memory(cap_c, wor_w); + if ( 0 != fil_u ) { + u3a_print_memory(fil_u, cap_c, wor_w); } return wor_w; } @@ -1657,17 +1657,17 @@ u3a_maid(c3_o pri_o, c3_c* cap_c, c3_w wor_w) /* u3a_mark_road(): mark ad-hoc persistent road structures. */ c3_w -u3a_mark_road(c3_o pri_o) +u3a_mark_road(FILE* fil_u) { c3_w tot_w = 0; - tot_w += u3a_maid(pri_o, " namespace", u3a_mark_noun(u3R->ski.gul)); - tot_w += u3a_maid(pri_o, " trace stack", u3a_mark_noun(u3R->bug.tax)); - tot_w += u3a_maid(pri_o, " trace buffer", u3a_mark_noun(u3R->bug.mer)); - tot_w += u3a_maid(pri_o, " profile batteries", u3a_mark_noun(u3R->pro.don)); - tot_w += u3a_maid(pri_o, " profile doss", u3a_mark_noun(u3R->pro.day)); - tot_w += u3a_maid(pri_o, " new profile trace", u3a_mark_noun(u3R->pro.trace)); - tot_w += u3a_maid(pri_o, " memoization cache", u3h_mark(u3R->cax.har_p)); - return u3a_maid(pri_o, "total road stuff", tot_w); + tot_w += u3a_maid(fil_u, " namespace", u3a_mark_noun(u3R->ski.gul)); + tot_w += u3a_maid(fil_u, " trace stack", u3a_mark_noun(u3R->bug.tax)); + tot_w += u3a_maid(fil_u, " trace buffer", u3a_mark_noun(u3R->bug.mer)); + tot_w += u3a_maid(fil_u, " profile batteries", u3a_mark_noun(u3R->pro.don)); + tot_w += u3a_maid(fil_u, " profile doss", u3a_mark_noun(u3R->pro.day)); + tot_w += u3a_maid(fil_u, " new profile trace", u3a_mark_noun(u3R->pro.trace)); + tot_w += u3a_maid(fil_u, " memoization cache", u3h_mark(u3R->cax.har_p)); + return u3a_maid(fil_u, "total road stuff", tot_w); } /* _ca_print_box(): heuristically print the contents of an allocation box. @@ -1744,7 +1744,7 @@ _ca_print_leak(c3_c* cap_c, u3a_box* box_u, c3_w eus_w, c3_w use_w) u3m_p(" code", box_u->cod_w); } - u3a_print_memory(" size", box_u->siz_w); + u3a_print_memory(stderr, " size", box_u->siz_w); { c3_c* dat_c = _ca_print_box(box_u); @@ -1764,7 +1764,7 @@ _ca_print_leak(c3_c* cap_c, u3a_box* box_u, c3_ws use_ws) ((u3a_noun *)(u3a_boxto(box_u)))->mug_w, use_ws); - u3a_print_memory(" size", box_u->siz_w); + u3a_print_memory(stderr, " size", box_u->siz_w); { c3_c* dat_c = _ca_print_box(box_u); @@ -1894,22 +1894,22 @@ u3a_sweep(void) #ifdef U3_CPU_DEBUG if ( (0 != u3R->par_p) && (u3R->all.max_w > 1000000) ) { - u3a_print_memory("available", (tot_w - pos_w)); - u3a_print_memory("allocated", pos_w); - u3a_print_memory("volatile", caf_w); + u3a_print_memory(stderr, "available", (tot_w - pos_w)); + u3a_print_memory(stderr, "allocated", pos_w); + u3a_print_memory(stderr, "volatile", caf_w); - u3a_print_memory("maximum", u3R->all.max_w); + u3a_print_memory(stderr, "maximum", u3R->all.max_w); } #else #if 0 - u3a_print_memory("available", (tot_w - pos_w)); - u3a_print_memory("allocated", pos_w); - u3a_print_memory("volatile", caf_w); + u3a_print_memory(stderr, "available", (tot_w - pos_w)); + u3a_print_memory(stderr, "allocated", pos_w); + u3a_print_memory(stderr, "volatile", caf_w); #endif #endif #endif - u3a_print_memory("leaked", leq_w); - u3a_print_memory("weaked", weq_w); + u3a_print_memory(stderr, "leaked", leq_w); + u3a_print_memory(stderr, "weaked", weq_w); c3_assert((pos_w + leq_w + weq_w) == neg_w); diff --git a/noun/events.c b/noun/events.c index 89201e0c0..2157017d3 100644 --- a/noun/events.c +++ b/noun/events.c @@ -775,7 +775,7 @@ u3e_save(void) // Sync the patch files. // - // u3a_print_memory("sync: save", 4096 * pat_u->con_u->pgs_w); + // u3a_print_memory(stderr, "sync: save", 4096 * pat_u->con_u->pgs_w); _ce_patch_sync(pat_u); // Verify the patch - because why not? @@ -896,7 +896,7 @@ u3e_live(c3_o nuu_o, c3_c* dir_c) nuu_o = c3y; } else { - u3a_print_memory("live: loaded", + u3a_print_memory(stderr, "live: loaded", (u3P.nor_u.pgs_w + u3P.sou_u.pgs_w) << u3a_page); } } diff --git a/noun/jets.c b/noun/jets.c index 8f887067e..c76b7090e 100644 --- a/noun/jets.c +++ b/noun/jets.c @@ -2250,26 +2250,26 @@ _cj_mark_hank(u3_noun kev, void* dat) /* u3j_mark(): mark jet state for gc. */ c3_w -u3j_mark(c3_o pri_o) +u3j_mark(FILE* fil_u) { c3_w tot_w = 0; - tot_w += u3a_maid(pri_o, " warm jet state", u3h_mark(u3R->jed.war_p)); - tot_w += u3a_maid(pri_o, " cold jet state", u3h_mark(u3R->jed.cod_p)); - tot_w += u3a_maid(pri_o, " hank cache", u3h_mark(u3R->jed.han_p)); - tot_w += u3a_maid(pri_o, " battery hash cache", u3h_mark(u3R->jed.bas_p)); + tot_w += u3a_maid(fil_u, " warm jet state", u3h_mark(u3R->jed.war_p)); + tot_w += u3a_maid(fil_u, " cold jet state", u3h_mark(u3R->jed.cod_p)); + tot_w += u3a_maid(fil_u, " hank cache", u3h_mark(u3R->jed.han_p)); + tot_w += u3a_maid(fil_u, " battery hash cache", u3h_mark(u3R->jed.bas_p)); { c3_w han_w = 0; u3h_walk_with(u3R->jed.han_p, _cj_mark_hank, &han_w); - tot_w += u3a_maid(pri_o, " call site cache", han_w); + tot_w += u3a_maid(fil_u, " call site cache", han_w); } if ( u3R == &(u3H->rod_u) ) { - tot_w += u3a_maid(pri_o, " hot jet state", u3h_mark(u3R->jed.hot_p)); + tot_w += u3a_maid(fil_u, " hot jet state", u3h_mark(u3R->jed.hot_p)); } - return u3a_maid(pri_o, "total jet stuff", tot_w); + return u3a_maid(fil_u, "total jet stuff", tot_w); } /* _cj_free_hank(): free hank cache. diff --git a/noun/manage.c b/noun/manage.c index 2a1d2576c..9cc10773d 100644 --- a/noun/manage.c +++ b/noun/manage.c @@ -491,13 +491,13 @@ _pave_parts(void) /* u3m_mark(): mark all nouns in the road. */ c3_w -u3m_mark(c3_o pri_o) +u3m_mark(FILE* fil_u) { c3_w tot_w = 0; - tot_w += u3v_mark(pri_o); - tot_w += u3j_mark(pri_o); - tot_w += u3n_mark(pri_o); - tot_w += u3a_mark_road(pri_o); + tot_w += u3v_mark(fil_u); + tot_w += u3j_mark(fil_u); + tot_w += u3n_mark(fil_u); + tot_w += u3a_mark_road(fil_u); return tot_w; } @@ -927,7 +927,7 @@ u3m_soft_top(c3_w sec_w, // timer seconds if ( u3C.wag_w & u3o_debug_ram ) { #ifdef U3_CPU_DEBUG if ( u3R->all.max_w > 1000000 ) { - u3a_print_memory("execute: top", u3R->all.max_w); + u3a_print_memory(stderr, "execute: top", u3R->all.max_w); } #endif u3m_grab(pro, u3_none); @@ -1024,7 +1024,7 @@ u3m_soft_run(u3_noun gul, #ifdef U3_CPU_DEBUG if ( u3R->all.max_w > 1000000 ) { - u3a_print_memory("execute: run", u3R->all.max_w); + u3a_print_memory(stderr, "execute: run", u3R->all.max_w); } #endif /* Produce success, on the old road. @@ -1146,7 +1146,7 @@ u3m_grab(u3_noun som, ...) // terminate with u3_none // u3h_free(u3R->cax.har_p); // u3R->cax.har_p = u3h_new(); - u3m_mark(c3n); + u3m_mark(0); { va_list vap; u3_noun tur; diff --git a/noun/nock.c b/noun/nock.c index aa7472d0d..f235258cb 100644 --- a/noun/nock.c +++ b/noun/nock.c @@ -2556,15 +2556,15 @@ _n_bam(u3_noun kev, void* dat) /* u3n_mark(): mark the bytecode cache for gc. */ c3_w -u3n_mark(c3_o pri_o) +u3n_mark(FILE* fil_u) { c3_w bam_w = 0, har_w = 0; u3p(u3h_root) har_p = u3R->byc.har_p; u3h_walk_with(har_p, _n_bam, &bam_w); - bam_w = u3a_maid(pri_o, " bytecode programs", bam_w); - har_w = u3a_maid(pri_o, " bytecode cache", u3h_mark(har_p)); - return u3a_maid(pri_o, "total nock stuff", bam_w + har_w); + bam_w = u3a_maid(fil_u, " bytecode programs", bam_w); + har_w = u3a_maid(fil_u, " bytecode cache", u3h_mark(har_p)); + return u3a_maid(fil_u, "total nock stuff", bam_w + har_w); } /* _n_feb(): u3h_walk helper for u3n_bree diff --git a/noun/vortex.c b/noun/vortex.c index b1aee1f7e..b3bbd77b1 100644 --- a/noun/vortex.c +++ b/noun/vortex.c @@ -405,19 +405,19 @@ _cv_mark_ova(u3p(u3v_cart) egg_p) /* u3v_mark(): mark arvo kernel. */ c3_w -u3v_mark(c3_o pri_o) +u3v_mark(FILE* fil_u) { u3v_arvo* arv_u = &(u3H->arv_u); c3_w tot_w = 0; - tot_w += u3a_maid(pri_o, " wish cache", u3a_mark_noun(arv_u->yot)); - tot_w += u3a_maid(pri_o, " date", u3a_mark_noun(arv_u->now)); - tot_w += u3a_maid(pri_o, " formatted date", u3a_mark_noun(arv_u->wen)); - tot_w += u3a_maid(pri_o, " instance string", u3a_mark_noun(arv_u->sen)); - tot_w += u3a_maid(pri_o, " identity", u3a_mark_noun(arv_u->own)); - tot_w += u3a_maid(pri_o, " pending events", u3a_mark_noun(arv_u->roe)); - tot_w += u3a_maid(pri_o, " event-log key", u3a_mark_noun(arv_u->key)); - tot_w += u3a_maid(pri_o, " kernel", u3a_mark_noun(arv_u->roc)); - tot_w += u3a_maid(pri_o, " egg basket", _cv_mark_ova(arv_u->ova.egg_p)); - return u3a_maid(pri_o, "total arvo stuff", tot_w); + tot_w += u3a_maid(fil_u, " wish cache", u3a_mark_noun(arv_u->yot)); + tot_w += u3a_maid(fil_u, " date", u3a_mark_noun(arv_u->now)); + tot_w += u3a_maid(fil_u, " formatted date", u3a_mark_noun(arv_u->wen)); + tot_w += u3a_maid(fil_u, " instance string", u3a_mark_noun(arv_u->sen)); + tot_w += u3a_maid(fil_u, " identity", u3a_mark_noun(arv_u->own)); + tot_w += u3a_maid(fil_u, " pending events", u3a_mark_noun(arv_u->roe)); + tot_w += u3a_maid(fil_u, " event-log key", u3a_mark_noun(arv_u->key)); + tot_w += u3a_maid(fil_u, " kernel", u3a_mark_noun(arv_u->roc)); + tot_w += u3a_maid(fil_u, " egg basket", _cv_mark_ova(arv_u->ova.egg_p)); + return u3a_maid(fil_u, "total arvo stuff", tot_w); } diff --git a/vere/raft.c b/vere/raft.c index 28565c528..e7687c464 100644 --- a/vere/raft.c +++ b/vere/raft.c @@ -1684,10 +1684,10 @@ _raft_kick(u3_noun vir) /* _raft_spac(): print n spaces. */ -void _raft_spac(c3_w n) +void _raft_spac(FILE* fil_u, c3_w n) { for (; n > 0; n--) - (fprintf(stderr," ")); + (fprintf(fil_u," ")); } /* _raft_print_memory: print memory amount. @@ -1695,7 +1695,7 @@ void _raft_spac(c3_w n) ** Helper for _raft_prof(), just an un-captioned u3a_print_memory(). */ void -_raft_print_memory(c3_w wor_w) +_raft_print_memory(FILE* fil_u, c3_w wor_w) { c3_w byt_w = (wor_w * 4); c3_w gib_w = (byt_w / 1000000000); @@ -1704,17 +1704,17 @@ _raft_print_memory(c3_w wor_w) c3_w bib_w = (byt_w % 1000); if ( gib_w ) { - (fprintf(stderr, "GB/%d.%03d.%03d.%03d\r\n", + (fprintf(fil_u, "GB/%d.%03d.%03d.%03d\r\n", gib_w, mib_w, kib_w, bib_w)); } else if ( mib_w ) { - (fprintf(stderr, "MB/%d.%03d.%03d\r\n", mib_w, kib_w, bib_w)); + (fprintf(fil_u, "MB/%d.%03d.%03d\r\n", mib_w, kib_w, bib_w)); } else if ( kib_w ) { - (fprintf(stderr, "KB/%d.%03d\r\n", kib_w, bib_w)); + (fprintf(fil_u, "KB/%d.%03d\r\n", kib_w, bib_w)); } else { - (fprintf(stderr, "B/%d\r\n", bib_w)); + (fprintf(fil_u, "B/%d\r\n", bib_w)); } } @@ -1757,38 +1757,44 @@ _raft_prof_noun(u3p(u3h_root) hax, u3_noun non, c3_t dud) /* _raft_prof(): print memory profile. RETAIN. */ c3_w -_raft_prof(u3p(u3h_root) hax, c3_w den, u3_noun mas) +_raft_prof(FILE* fil_u, c3_w den, u3_noun mas) { c3_w tot_w = 0; u3_noun h_mas, t_mas; if ( c3n == u3r_cell(mas, &h_mas, &t_mas) ) { - _raft_spac(den); - (fprintf(stderr, "mistyped mass\r\n")); + _raft_spac(fil_u, den); + fprintf(fil_u, "mistyped mass\r\n"); return tot_w; } else if ( _(u3du(h_mas)) ) { - _raft_spac(den); - (fprintf(stderr, "mistyped mass head\r\n")); - u3m_p("h_mas", h_mas); + _raft_spac(fil_u, den); + fprintf(fil_u, "mistyped mass head\r\n"); + { + c3_c* lab_c = u3m_pretty(h_mas); + fprintf(fil_u, "h_mas: %s", lab_c); + free(lab_c); + } return tot_w; } else { - _raft_spac(den); + _raft_spac(fil_u, den); - c3_c* lab_c = u3m_pretty(h_mas); - (fprintf(stderr, "%s: ", lab_c)); - free(lab_c); + { + c3_c* lab_c = u3m_pretty(h_mas); + fprintf(fil_u, "%s: ", lab_c); + free(lab_c); + } u3_noun it_mas, tt_mas; if ( c3n == u3r_cell(t_mas, &it_mas, &tt_mas) ) { - (fprintf(stderr, "mistyped mass tail\r\n")); + fprintf(fil_u, "mistyped mass tail\r\n"); return tot_w; } else if ( c3y == it_mas ) { tot_w += u3a_mark_noun(tt_mas); - _raft_print_memory(tot_w); + _raft_print_memory(fil_u, tot_w); #if 1 /* The basic issue here is that tt_mas is included in @@ -1820,23 +1826,23 @@ _raft_prof(u3p(u3h_root) hax, c3_w den, u3_noun mas) return tot_w; } else if ( c3n == it_mas ) { - (fprintf(stderr, "\r\n")); + fprintf(fil_u, "\r\n"); while ( _(u3du(tt_mas)) ) { - tot_w += _raft_prof(hax, den+2, u3h(tt_mas)); + tot_w += _raft_prof(fil_u, den+2, u3h(tt_mas)); tt_mas = u3t(tt_mas); } - _raft_spac(den); - (fprintf(stderr, "--")); - _raft_print_memory(tot_w); + _raft_spac(fil_u, den); + fprintf(fil_u, "--"); + _raft_print_memory(fil_u, tot_w); return tot_w; } else { - _raft_spac(den); - (fprintf(stderr, "mistyped (strange) mass tail\r\n")); + _raft_spac(fil_u, den); + fprintf(fil_u, "mistyped (strange) mass tail\r\n"); return tot_w; } } @@ -1850,23 +1856,25 @@ _raft_grab(u3_noun rus) if ( u3_nul != u3A->sac ) { c3_w usr_w = 0, man_w = 0, ova_w = 0, sac_w = 0; + FILE* fil_u = stderr; + c3_assert( u3R == &(u3H->rod_u) ); - fprintf(stderr, "\r\n"); - usr_w = _raft_prof(u3_nul, 0, u3A->sac); - u3a_print_memory("total userspace", usr_w); + fprintf(fil_u, "\r\n"); + usr_w = _raft_prof(fil_u, 0, u3A->sac); + u3a_print_memory(fil_u, "total userspace", usr_w); - man_w = u3m_mark(c3y); + man_w = u3m_mark(fil_u); ova_w = u3a_mark_noun(rus); - u3a_print_memory("event & effects", ova_w); + u3a_print_memory(fil_u, "event & effects", ova_w); sac_w = u3a_mark_noun(u3A->sac); - u3a_print_memory("space profile", sac_w); + u3a_print_memory(fil_u, "space profile", sac_w); - u3a_print_memory("total marked", usr_w + man_w + ova_w + sac_w); + u3a_print_memory(fil_u, "total marked", usr_w + man_w + ova_w + sac_w); - u3a_print_memory("sweep", u3a_sweep()); + u3a_print_memory(fil_u, "sweep", u3a_sweep()); // u3h_free(u3R->cax.har_p); // u3R->cax.har_p = u3h_new(); @@ -1874,6 +1882,8 @@ _raft_grab(u3_noun rus) u3z(u3A->sac); u3A->sac = u3_nul; + // restore prompt + // uL(fprintf(uH, "\n")); } } From 98590cccb5b3f6119abe6909ade5240cad99a97c Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Tue, 29 Jan 2019 22:13:31 -0500 Subject: [PATCH 08/12] adds -Dmemory-log=true build option to save |mass output to a file --- include/config.h.in | 1 + meson.build | 1 + meson_options.txt | 2 ++ vere/raft.c | 26 +++++++++++++++++++++++++- 4 files changed, 29 insertions(+), 1 deletion(-) diff --git a/include/config.h.in b/include/config.h.in index 563cfa05a..556b0954f 100644 --- a/include/config.h.in +++ b/include/config.h.in @@ -13,5 +13,6 @@ #mesondefine U3_MEMORY_DEBUG #mesondefine U3_CPU_DEBUG #mesondefine U3_EVENT_TIME_DEBUG +#mesondefine U3_MEMORY_LOG #endif /*CONFIG_H*/ diff --git a/meson.build b/meson.build index 1be941091..f1bf0076a 100644 --- a/meson.build +++ b/meson.build @@ -240,6 +240,7 @@ conf_data.set('URBIT_VERSION', '"0.7.0"') conf_data.set('U3_MEMORY_DEBUG', get_option('gc')) conf_data.set('U3_CPU_DEBUG', get_option('prof')) conf_data.set('U3_EVENT_TIME_DEBUG', get_option('event-time')) +conf_data.set('U3_MEMORY_LOG', get_option('memory-log')) osdet = host_machine.system() cc = meson.get_compiler('c') diff --git a/meson_options.txt b/meson_options.txt index b09e525d0..0d0166a5a 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -4,5 +4,7 @@ option('prof', type : 'boolean', value : false, description : 'Activate profiling. Run with -P.') option('event-time', type : 'boolean', value : false, description : 'Print timing information per event.') +option('memory-log', type : 'boolean', value : false, + description : 'Write memory usage to a logfile.') option('nix', type: 'boolean', value: false, description: 'Build using nix.') diff --git a/vere/raft.c b/vere/raft.c index e7687c464..88d1be6c2 100644 --- a/vere/raft.c +++ b/vere/raft.c @@ -1856,7 +1856,25 @@ _raft_grab(u3_noun rus) if ( u3_nul != u3A->sac ) { c3_w usr_w = 0, man_w = 0, ova_w = 0, sac_w = 0; - FILE* fil_u = stderr; + FILE* fil_u; + +#ifdef U3_MEMORY_LOG + { + c3_c* wen_c = u3r_string(u3A->wen); + + c3_c nam_c[2048]; + snprintf(nam_c, 2048, "%s/.urb/put/%s-mass.txt", u3_Host.dir_c, wen_c); + + fil_u = fopen(nam_c, "w"); + fprintf(fil_u, "%s\r\n", wen_c); + + free(wen_c); + } +#else + { + fil_u = stderr; + } +#endif c3_assert( u3R == &(u3H->rod_u) ); @@ -1876,6 +1894,12 @@ _raft_grab(u3_noun rus) u3a_print_memory(fil_u, "sweep", u3a_sweep()); +#ifdef U3_MEMORY_LOG + { + fclose(fil_u); + } +#endif + // u3h_free(u3R->cax.har_p); // u3R->cax.har_p = u3h_new(); From ffdc465085c4e60c21b81ce029bc40f654033b27 Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Mon, 21 Jan 2019 20:02:41 -0500 Subject: [PATCH 09/12] adds u3m_reclaim to clear persistent caches in vere --- include/noun/manage.h | 5 +++++ noun/manage.c | 30 ++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/include/noun/manage.h b/include/noun/manage.h index 16fa82847..e8212efbf 100644 --- a/include/noun/manage.h +++ b/include/noun/manage.h @@ -125,3 +125,8 @@ */ void u3m_wall(u3_noun wol); + + /* u3m_reclaim: clear persistent caches to reclaim memory + */ + void + u3m_reclaim(void); diff --git a/noun/manage.c b/noun/manage.c index 9cc10773d..1841e4da7 100644 --- a/noun/manage.c +++ b/noun/manage.c @@ -1723,3 +1723,33 @@ u3m_boot(c3_o nuu_o, c3_o bug_o, c3_c* dir_c, u3n_ream(); } } + +/* u3m_reclaim: clear persistent caches to reclaim memory +*/ +void +u3m_reclaim(void) +{ + // clear the memoization cache + // + u3h_free(u3R->cax.har_p); + u3R->cax.har_p = u3h_new(); + + // clear the bytecode cache + // + u3h_free(u3R->byc.har_p); + u3R->byc.har_p = u3h_new(); + + // clear the jet battery hash cache + // + u3h_free(u3R->jed.bas_p); + u3R->jed.bas_p = u3h_new(); + + // clear the jet hank cache + // + u3h_free(u3R->jed.han_p); + u3R->jed.han_p = u3h_new(); + + // clear the u3v_wish cache + u3z(u3A->yot); + u3A->yot = u3_nul; +} From 98f59f6d85c49c259d772683b46bdf836b5a6db5 Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Tue, 22 Jan 2019 01:26:48 -0500 Subject: [PATCH 10/12] reclaim memory on restart --- vere/sist.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/vere/sist.c b/vere/sist.c index 3d893ea40..a5205f3c2 100644 --- a/vere/sist.c +++ b/vere/sist.c @@ -1235,6 +1235,12 @@ u3_sist_boot(void) } if ( c3n == u3_Host.ops_u.nuu ) { + // reclaim memory from persistent caches + // + u3m_reclaim(); + + // restore from event log, replaying if necessary + // _sist_rest(); if ( c3y == u3A->fak ) { From 414e760fd15b324d7fb44f6c4a085fd80af62e52 Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Mon, 28 Jan 2019 12:04:30 -0500 Subject: [PATCH 11/12] reclaim memory on kernel reset --- vere/reck.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/vere/reck.c b/vere/reck.c index c0c4e5e34..595261fdf 100644 --- a/vere/reck.c +++ b/vere/reck.c @@ -355,7 +355,9 @@ _reck_kick_norm(u3_noun pox, u3_noun fav) uL(fprintf(uH, "<<>>\n")); u3z(pox); u3z(fav); - // u3_ds_wipe(u3_Wire); // doesn't work + // reclaim memory from persistent caches + // + u3m_reclaim(); return c3y; } From 2b8a7392adae4ad2f9138bc74f2801767c57f2c6 Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Tue, 29 Jan 2019 23:11:55 -0500 Subject: [PATCH 12/12] refactors u3m_reclaim, plugging memory leaks --- include/noun/jets.h | 5 +++++ noun/jets.c | 8 ++++---- noun/manage.c | 27 +++++++++++++++++++-------- noun/nock.c | 2 +- 4 files changed, 29 insertions(+), 13 deletions(-) diff --git a/include/noun/jets.h b/include/noun/jets.h index 3abc5026f..80d255d24 100644 --- a/include/noun/jets.h +++ b/include/noun/jets.h @@ -262,6 +262,11 @@ c3_w u3j_mark(FILE* fil_u); + /* u3j_free_hank(): free an entry from the hank cache. + */ + void + u3j_free_hank(u3_noun kev); + /* u3j_free(): free jet state. */ void diff --git a/noun/jets.c b/noun/jets.c index c76b7090e..ee4f65bf4 100644 --- a/noun/jets.c +++ b/noun/jets.c @@ -2272,10 +2272,10 @@ u3j_mark(FILE* fil_u) return u3a_maid(fil_u, "total jet stuff", tot_w); } -/* _cj_free_hank(): free hank cache. +/* u3j_free_hank(): free an entry from the hank cache. */ -static void -_cj_free_hank(u3_noun kev) +void +u3j_free_hank(u3_noun kev) { _cj_hank* han_u = u3to(_cj_hank, u3t(kev)); if ( u3_none != han_u->hax ) { @@ -2290,7 +2290,7 @@ _cj_free_hank(u3_noun kev) void u3j_free(void) { - u3h_walk(u3R->jed.han_p, _cj_free_hank); + u3h_walk(u3R->jed.han_p, u3j_free_hank); u3h_free(u3R->jed.war_p); u3h_free(u3R->jed.cod_p); u3h_free(u3R->jed.han_p); diff --git a/noun/manage.c b/noun/manage.c index 1841e4da7..f072a077c 100644 --- a/noun/manage.c +++ b/noun/manage.c @@ -1729,27 +1729,38 @@ u3m_boot(c3_o nuu_o, c3_o bug_o, c3_c* dir_c, void u3m_reclaim(void) { + // clear the u3v_wish cache + // + u3z(u3A->yot); + u3A->yot = u3_nul; + // clear the memoization cache // u3h_free(u3R->cax.har_p); u3R->cax.har_p = u3h_new(); - // clear the bytecode cache - // - u3h_free(u3R->byc.har_p); - u3R->byc.har_p = u3h_new(); - // clear the jet battery hash cache // u3h_free(u3R->jed.bas_p); u3R->jed.bas_p = u3h_new(); + // XX we can't clear the warm jet state + // -- _cj_nail expects it to be present ... + // + // u3h_free(u3R->jed.war_p); + // u3R->jed.war_p = u3h_new(); + // clear the jet hank cache // + u3h_walk(u3R->jed.han_p, u3j_free_hank); u3h_free(u3R->jed.han_p); u3R->jed.han_p = u3h_new(); - // clear the u3v_wish cache - u3z(u3A->yot); - u3A->yot = u3_nul; + // clear the bytecode cache + // + // We can't just u3h_free() -- the value is a post to a u3n_prog. + // Note that this requires that the hank cache also be freed. + // + u3n_free(); + u3R->byc.har_p = u3h_new(); } diff --git a/noun/nock.c b/noun/nock.c index f235258cb..ae9645bbd 100644 --- a/noun/nock.c +++ b/noun/nock.c @@ -2567,7 +2567,7 @@ u3n_mark(FILE* fil_u) return u3a_maid(fil_u, "total nock stuff", bam_w + har_w); } -/* _n_feb(): u3h_walk helper for u3n_bree +/* _n_feb(): u3h_walk helper for u3n_free */ static void _n_feb(u3_noun kev)