mirror of
https://github.com/ilyakooo0/urbit.git
synced 2024-12-16 02:22:12 +03:00
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:
commit
9ef6de4bcc
@ -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 ...
|
||||
|
@ -13,5 +13,6 @@
|
||||
#mesondefine U3_MEMORY_DEBUG
|
||||
#mesondefine U3_CPU_DEBUG
|
||||
#mesondefine U3_EVENT_TIME_DEBUG
|
||||
#mesondefine U3_MEMORY_LOG
|
||||
|
||||
#endif /*CONFIG_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
|
||||
@ -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.
|
||||
*/
|
||||
|
@ -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.
|
||||
*/
|
||||
|
@ -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);
|
||||
|
@ -110,7 +110,7 @@
|
||||
/* u3n_mark(): mark bytecode cache.
|
||||
*/
|
||||
c3_w
|
||||
u3n_mark(void);
|
||||
u3n_mark(FILE* fil_u);
|
||||
|
||||
/* u3n_free(): free bytecode cache.
|
||||
*/
|
||||
|
@ -147,4 +147,4 @@
|
||||
/* u3v_mark(): mark arvo kernel.
|
||||
*/
|
||||
c3_w
|
||||
u3v_mark(void);
|
||||
u3v_mark(FILE* fil_u);
|
||||
|
@ -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')
|
||||
|
@ -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.')
|
||||
|
211
noun/allocate.c
211
noun/allocate.c
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
34
noun/jets.c
34
noun/jets.c
@ -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);
|
||||
|
@ -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();
|
||||
}
|
||||
|
11
noun/nock.c
11
noun/nock.c
@ -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)
|
||||
|
@ -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);
|
||||
}
|
||||
|
168
vere/raft.c
168
vere/raft.c
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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 ) {
|
||||
|
Loading…
Reference in New Issue
Block a user