Merge branch 'master' into hotfix

* master:
  refactors u3m_reclaim, plugging memory leaks
  reclaim memory on kernel reset
  reclaim memory on restart
  adds u3m_reclaim to clear persistent caches in vere
  adds -Dmemory-log=true build option to save |mass output to a file
  threads output file pointer through memory marking and printing
  [CI] run |mass after +test
  fixes |mass, unifying the implementation with u3m_grab()
  refactors and clarifies heuristic printing of an allocation box
  adds comment explaining u3a_minimum
  refactors memory leak printfs in u3a_sweep()
  refactors libnoun memory marking, adds optional printfs
This commit is contained in:
Joe Bryan 2019-01-30 15:11:31 -05:00
commit 9ef6de4bcc
18 changed files with 373 additions and 202 deletions

View File

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

View File

@ -13,5 +13,6 @@
#mesondefine U3_MEMORY_DEBUG
#mesondefine U3_CPU_DEBUG
#mesondefine U3_EVENT_TIME_DEBUG
#mesondefine U3_MEMORY_LOG
#endif /*CONFIG_H*/

View File

@ -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
@ -402,6 +404,11 @@
c3_w
u3a_mark_noun(u3_noun som);
/* u3a_mark_road(): mark ad-hoc persistent road structures.
*/
c3_w
u3a_mark_road(FILE* fil_u);
/* u3a_sweep(): sweep a fully marked road.
*/
c3_w
@ -422,10 +429,15 @@
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_print_memory(FILE* fil_u, c3_c* cap_c, c3_w wor_w);
/* u3a_maid(): maybe print memory.
*/
c3_w
u3a_maid(FILE* fil_u, c3_c* cap_c, c3_w wor_w);
/* u3a_deadbeef(): write 0xdeadbeef from hat to cap.
*/

View File

@ -260,7 +260,12 @@
/* u3j_mark(): mark jet state for gc.
*/
c3_w
u3j_mark(void);
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.
*/

View File

@ -94,7 +94,7 @@
/* u3m_mark(): mark all nouns in the road.
*/
c3_w
u3m_mark(void);
u3m_mark(FILE* fil_u);
/* u3m_grab(): garbage-collect the world, plus extra roots.
*/
@ -125,3 +125,8 @@
*/
void
u3m_wall(u3_noun wol);
/* u3m_reclaim: clear persistent caches to reclaim memory
*/
void
u3m_reclaim(void);

View File

@ -110,7 +110,7 @@
/* u3n_mark(): mark bytecode cache.
*/
c3_w
u3n_mark(void);
u3n_mark(FILE* fil_u);
/* u3n_free(): free bytecode cache.
*/

View File

@ -147,4 +147,4 @@
/* u3v_mark(): mark arvo kernel.
*/
c3_w
u3v_mark(void);
u3v_mark(FILE* fil_u);

View File

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

View File

@ -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.')

View File

@ -1616,9 +1616,9 @@ u3a_mark_noun(u3_noun som)
/* 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)
{
FILE *fil_f = u3_term_io_hija();
c3_assert( 0 != fil_u );
c3_w byt_w = (wor_w * 4);
c3_w gib_w = (byt_w / 1000000000);
@ -1628,22 +1628,153 @@ 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(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(fil_f, "%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(fil_f, "%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(fil_f, "%s: B/%d\r\n", cap_c, bib_w);
fprintf(fil_u, "%s: B/%d\r\n", cap_c, bib_w);
}
}
u3_term_io_loja(0);
}
/* u3a_maid(): maybe print memory.
*/
c3_w
u3a_maid(FILE* fil_u, c3_c* cap_c, c3_w wor_w)
{
if ( 0 != fil_u ) {
u3a_print_memory(fil_u, cap_c, wor_w);
}
return wor_w;
}
/* u3a_mark_road(): mark ad-hoc persistent road structures.
*/
c3_w
u3a_mark_road(FILE* fil_u)
{
c3_w tot_w = 0;
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.
*/
static c3_c*
_ca_print_box(u3a_box* 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;
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
//
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;
}
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)
{
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(stderr, " size", box_u->siz_w);
{
c3_c* dat_c = _ca_print_box(box_u);
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)
{
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(stderr, " size", box_u->siz_w);
{
c3_c* dat_c = _ca_print_box(box_u);
fprintf(stderr, " data: %s\r\n", dat_c);
free(dat_c);
}
}
#endif
/* u3a_sweep(): sweep a fully marked road.
*/
c3_w
@ -1700,7 +1831,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.
*
@ -1711,34 +1842,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 {
@ -1751,25 +1868,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;
@ -1795,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);

View File

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

View File

@ -2250,24 +2250,32 @@ _cj_mark_hank(u3_noun kev, void* dat)
/* u3j_mark(): mark jet state for gc.
*/
c3_w
u3j_mark(void)
u3j_mark(FILE* fil_u)
{
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(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(fil_u, " call site cache", han_w);
}
return tot_w;
if ( u3R == &(u3H->rod_u) ) {
tot_w += u3a_maid(fil_u, " hot jet state", u3h_mark(u3R->jed.hot_p));
}
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 ) {
@ -2282,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);

View File

@ -491,18 +491,13 @@ _pave_parts(void)
/* u3m_mark(): mark all nouns in the road.
*/
c3_w
u3m_mark(void)
u3m_mark(FILE* fil_u)
{
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(fil_u);
tot_w += u3j_mark(fil_u);
tot_w += u3n_mark(fil_u);
tot_w += u3a_mark_road(fil_u);
return tot_w;
}
@ -932,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);
@ -1029,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.
@ -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(0);
{
va_list vap;
u3_noun tur;
@ -1729,3 +1723,44 @@ 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 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 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 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();
}

View File

@ -2556,15 +2556,18 @@ _n_bam(u3_noun kev, void* dat)
/* u3n_mark(): mark the bytecode cache for gc.
*/
c3_w
u3n_mark()
u3n_mark(FILE* fil_u)
{
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(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
/* _n_feb(): u3h_walk helper for u3n_free
*/
static void
_n_feb(u3_noun kev)

View File

@ -405,24 +405,19 @@ _cv_mark_ova(u3p(u3v_cart) egg_p)
/* u3v_mark(): mark arvo kernel.
*/
c3_w
u3v_mark(void)
u3v_mark(FILE* fil_u)
{
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(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);
}

View File

@ -1684,16 +1684,18 @@ _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. 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)
_raft_print_memory(FILE* fil_u, c3_w wor_w)
{
c3_w byt_w = (wor_w * 4);
c3_w gib_w = (byt_w / 1000000000);
@ -1702,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));
}
}
@ -1755,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
@ -1818,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;
}
}
@ -1843,85 +1851,67 @@ _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;
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) );
fprintf(stderr, "\r\n");
usr_w = _raft_prof(u3_nul, 0, u3A->sac);
fprintf(stderr, "total userspace: ");
_raft_print_memory(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);
ova_w = u3a_mark_noun(ova);
fprintf(stderr, "effects list: ");
_raft_print_memory(ova_w);
man_w = u3m_mark(fil_u);
ova_w = u3a_mark_noun(rus);
u3a_print_memory(fil_u, "event & effects", ova_w);
sac_w = u3a_mark_noun(u3A->sac);
fprintf(stderr, "space profile: ");
_raft_print_memory(sac_w);
u3a_print_memory(fil_u, "space profile", sac_w);
utv_w = u3v_mark();
fprintf(stderr, "arvo stuff: ");
_raft_print_memory(utv_w);
u3a_print_memory(fil_u, "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(fil_u, "sweep", u3a_sweep());
das_w = u3h_mark(u3R->jed.cod_p);
fprintf(stderr, " cold jet state: ");
_raft_print_memory(das_w);
#ifdef U3_MEMORY_LOG
{
fclose(fil_u);
}
#endif
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;
// restore prompt
//
uL(fprintf(uH, "\n"));
}
}
int FOO;
/* _raft_crop(): Delete finished events.
*/
static void
@ -2062,7 +2052,7 @@ u3_raft_chip(void)
}
_raft_kick(u3k(vir));
_raft_grab(vir);
_raft_grab(rus);
u3z(rus);
}

View File

@ -355,7 +355,9 @@ _reck_kick_norm(u3_noun pox, u3_noun fav)
uL(fprintf(uH, "<<<reset>>>\n"));
u3z(pox); u3z(fav);
// u3_ds_wipe(u3_Wire); // doesn't work
// reclaim memory from persistent caches
//
u3m_reclaim();
return c3y;
}

View File

@ -1256,6 +1256,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 ) {