From c19da037dbd1464f24b1d1afdffe380132667425 Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Wed, 25 Oct 2023 13:49:27 -0400 Subject: [PATCH 1/2] serf: adds stateful memory-pressure thresholds --- pkg/vere/serf.c | 69 +++++++++++++++++++++++++++++++++++++------------ pkg/vere/serf.h | 1 + 2 files changed, 54 insertions(+), 16 deletions(-) diff --git a/pkg/vere/serf.c b/pkg/vere/serf.c index cfbbc47be3..f61883ef29 100644 --- a/pkg/vere/serf.c +++ b/pkg/vere/serf.c @@ -198,6 +198,22 @@ u3_serf_post(u3_serf* sef_u) } } +/* _serf_curb(): check for memory threshold +*/ +static inline c3_t +_serf_curb(c3_w pre_w, c3_w pos_w, c3_w hes_w) +{ + return (pre_w > hes_w) && (pos_w <= hes_w); +} + +/* serf memory-threshold levels +*/ +enum { + _serf_init = 0, + _serf_hit1 = 1, + _serf_hit0 = 2 +}; + /* _serf_sure_feck(): event succeeded, send effects. */ static u3_noun @@ -253,38 +269,59 @@ _serf_sure_feck(u3_serf* sef_u, c3_w pre_w, u3_noun vir) // For future flexibility, the urgency of the notification is represented // by a *decreasing* number: 0 is maximally urgent, 1 less so, &c. // - // high-priority: 2^22 contiguous words remaining (~8 MB) + // high-priority: 2^25 contiguous words remaining (~128 MB) // low-priority: 2^27 contiguous words remaining (~536 MB) - // XX maybe use 2^23 (~16 MB) and 2^26 (~268 MB? + // + // once a threshold is hit, it's not a candidate to be hit again + // until memory usage falls below: + // + // high-priority: 2^26 contiguous words remaining (~256 MB) + // low-priority: 2^26 + 2^27 contiguous words remaining (~768 MB) // // XX these thresholds should trigger notifications sent to the king // instead of directly triggering these remedial actions. // { u3_noun pri = u3_none; - c3_w pos_w = u3a_open(u3R); - c3_w low_w = (1 << 27); - c3_w hig_w = (1 << 22); + c3_w pos_w = u3a_open(u3R); - if ( (pre_w > low_w) && !(pos_w > low_w) ) { - // XX set flag(s) in u3V so we don't repeat endlessly? - // - pac_o = c3y; - rec_o = c3y; - pri = 1; + // if contiguous free space shrunk, check thresholds + // (and track state to avoid thrashing) + // + if ( pos_w < pre_w ) { + if ( (_serf_hit0 != sef_u->mas_w) + && _serf_curb(pre_w, pos_w, 1 << 25) ) + { + sef_u->mas_w = _serf_hit0; + pac_o = c3y; + pri = 0; + } + else if ( (_serf_init == sef_u->mas_w) + && _serf_curb(pre_w, pos_w, 1 << 27) ) + { + sef_u->mas_w = _serf_hit1; + rec_o = c3y; + pri = 1; + } } - else if ( (pre_w > hig_w) && !(pos_w > hig_w) ) { - pac_o = c3y; - rec_o = c3y; - pri = 0; + else if ( _serf_init != sef_u->mas_w ) { + if ( ((1 << 26) + (1 << 27)) < pos_w ) { + sef_u->mas_w = _serf_init; + } + else if ( (_serf_hit0 == sef_u->mas_w) + && ((1 << 26) < pos_w) ) + { + sef_u->mas_w = _serf_hit1; + } } + // reclaim memory from persistent caches periodically // // XX this is a hack to work two things // - bytecode caches grow rapidly and can't be simply capped // - we don't make very effective use of our free lists // - else if ( 0 == (sef_u->dun_d % 1000ULL) ) { + if ( 0 == (sef_u->dun_d % 1000ULL) ) { rec_o = c3y; } diff --git a/pkg/vere/serf.h b/pkg/vere/serf.h index 5808f362e7..08dbec9cd3 100644 --- a/pkg/vere/serf.h +++ b/pkg/vere/serf.h @@ -11,6 +11,7 @@ c3_d sen_d; // last event requested c3_d dun_d; // last event processed c3_l mug_l; // hash of state + c3_w mas_w; // memory threshold state c3_o pac_o; // pack kernel c3_o rec_o; // reclaim cache c3_o mut_o; // mutated kerne From 280ac6a5e1d274f196da895b56d79cd1ca150325 Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Wed, 25 Oct 2023 14:06:25 -0400 Subject: [PATCH 2/2] serf: switch to bitmap for post-ops, track granularly --- pkg/vere/serf.c | 80 +++++++++++++++++++++++++------------------------ pkg/vere/serf.h | 4 +-- 2 files changed, 42 insertions(+), 42 deletions(-) diff --git a/pkg/vere/serf.c b/pkg/vere/serf.c index f61883ef29..80a5b1ccf3 100644 --- a/pkg/vere/serf.c +++ b/pkg/vere/serf.c @@ -51,6 +51,25 @@ :: next steps: -- */ +/* serf memory-threshold levels +*/ +enum { + _serf_mas_init = 0, // initial + _serf_mas_hit1 = 1, // past low threshold + _serf_mas_hit0 = 2 // have high threshold +}; + +/* serf post-op flags +*/ +enum { + _serf_fag_none = 0, // nothing to do + _serf_fag_hit1 = 1 << 0, // hit low threshold + _serf_fag_hit0 = 1 << 1, // hit high threshold + _serf_fag_mute = 1 << 2, // mutated state + _serf_fag_much = 1 << 3, // bytecode hack + _serf_fag_vega = 1 << 4 // kernel reset +}; + /* _serf_grab(): garbage collect, checking for profiling. RETAIN. */ static void @@ -174,28 +193,27 @@ u3_serf_grab(void) void u3_serf_post(u3_serf* sef_u) { - if ( c3y == sef_u->rec_o ) { + if ( sef_u->fag_w & (_serf_fag_hit1|_serf_fag_much|_serf_fag_vega) ) { u3m_reclaim(); - sef_u->rec_o = c3n; } // XX this runs on replay too, |mass s/b elsewhere // - if ( c3y == sef_u->mut_o ) { + if ( sef_u->fag_w & _serf_fag_mute ) { _serf_grab(sef_u->sac); sef_u->sac = u3_nul; - sef_u->mut_o = c3n; } - if ( c3y == sef_u->pac_o ) { + if ( sef_u->fag_w & _serf_fag_hit0 ) { u3a_print_memory(stderr, "serf: pack: gained", u3m_pack()); u3l_log(""); - sef_u->pac_o = c3n; } if ( u3C.wag_w & u3o_toss ) { u3m_toss(); } + + sef_u->fag_w = _serf_fag_none; } /* _serf_curb(): check for memory threshold @@ -206,22 +224,11 @@ _serf_curb(c3_w pre_w, c3_w pos_w, c3_w hes_w) return (pre_w > hes_w) && (pos_w <= hes_w); } -/* serf memory-threshold levels -*/ -enum { - _serf_init = 0, - _serf_hit1 = 1, - _serf_hit0 = 2 -}; - /* _serf_sure_feck(): event succeeded, send effects. */ static u3_noun _serf_sure_feck(u3_serf* sef_u, c3_w pre_w, u3_noun vir) { - c3_o rec_o = c3n; - c3_o pac_o = c3n; - // intercept |mass, observe |reset // { @@ -252,7 +259,7 @@ _serf_sure_feck(u3_serf* sef_u, c3_w pre_w, u3_noun vir) // reclaim memory from persistent caches on |reset // if ( c3__vega == u3h(fec) ) { - rec_o = c3y; + sef_u->fag_w |= _serf_fag_vega; } riv = u3t(riv); @@ -289,29 +296,29 @@ _serf_sure_feck(u3_serf* sef_u, c3_w pre_w, u3_noun vir) // (and track state to avoid thrashing) // if ( pos_w < pre_w ) { - if ( (_serf_hit0 != sef_u->mas_w) + if ( (_serf_mas_hit0 != sef_u->mas_w) && _serf_curb(pre_w, pos_w, 1 << 25) ) { - sef_u->mas_w = _serf_hit0; - pac_o = c3y; - pri = 0; + sef_u->mas_w = _serf_mas_hit0; + sef_u->fag_w |= _serf_fag_hit0; + pri = 0; } - else if ( (_serf_init == sef_u->mas_w) + else if ( (_serf_mas_init == sef_u->mas_w) && _serf_curb(pre_w, pos_w, 1 << 27) ) { - sef_u->mas_w = _serf_hit1; - rec_o = c3y; - pri = 1; + sef_u->mas_w = _serf_mas_hit1; + sef_u->fag_w |= _serf_fag_hit1; + pri = 1; } } - else if ( _serf_init != sef_u->mas_w ) { + else if ( _serf_mas_init != sef_u->mas_w ) { if ( ((1 << 26) + (1 << 27)) < pos_w ) { - sef_u->mas_w = _serf_init; + sef_u->mas_w = _serf_mas_init; } - else if ( (_serf_hit0 == sef_u->mas_w) + else if ( (_serf_mas_hit0 == sef_u->mas_w) && ((1 << 26) < pos_w) ) { - sef_u->mas_w = _serf_hit1; + sef_u->mas_w = _serf_mas_hit1; } } @@ -321,8 +328,8 @@ _serf_sure_feck(u3_serf* sef_u, c3_w pre_w, u3_noun vir) // - bytecode caches grow rapidly and can't be simply capped // - we don't make very effective use of our free lists // - if ( 0 == (sef_u->dun_d % 1000ULL) ) { - rec_o = c3y; + if ( !(sef_u->dun_d % 1024ULL) ) { + sef_u->fag_w |= _serf_fag_much; } // notify daemon of memory pressure via "fake" effect @@ -334,9 +341,6 @@ _serf_sure_feck(u3_serf* sef_u, c3_w pre_w, u3_noun vir) } } - sef_u->rec_o = c3o(sef_u->rec_o, rec_o); - sef_u->pac_o = c3o(sef_u->pac_o, pac_o); - return vir; } @@ -351,7 +355,7 @@ _serf_sure_core(u3_serf* sef_u, u3_noun cor) u3A->roc = cor; u3A->eve_d = sef_u->dun_d; sef_u->mug_l = u3r_mug(u3A->roc); - sef_u->mut_o = c3y; + sef_u->fag_w |= _serf_fag_mute; } /* _serf_sure(): event succeeded, save state and process effects. @@ -1053,9 +1057,7 @@ u3_serf_init(u3_serf* sef_u) // } // } - sef_u->pac_o = c3n; - sef_u->rec_o = c3n; - sef_u->mut_o = c3n; + sef_u->fag_w = _serf_fag_none; sef_u->sac = u3_nul; return rip; diff --git a/pkg/vere/serf.h b/pkg/vere/serf.h index 08dbec9cd3..7cd2ca47d0 100644 --- a/pkg/vere/serf.h +++ b/pkg/vere/serf.h @@ -12,9 +12,7 @@ c3_d dun_d; // last event processed c3_l mug_l; // hash of state c3_w mas_w; // memory threshold state - c3_o pac_o; // pack kernel - c3_o rec_o; // reclaim cache - c3_o mut_o; // mutated kerne + c3_w fag_w; // post-op flags u3_noun sac; // space measurementl void (*xit_f)(void); // exit callback } u3_serf;