mirror of
https://github.com/urbit/shrub.git
synced 2024-11-28 22:33:06 +03:00
stash -- nearing initial hash-increment arm scheme
This commit is contained in:
parent
495845a59f
commit
0f5b97bf55
@ -43,7 +43,11 @@
|
||||
typedef struct {
|
||||
c3_w use_w; // number of lines currently filled
|
||||
c3_w max_w; // number of cache lines (0 for no trimming)
|
||||
c3_w clk_w; // clock arm, current hash
|
||||
struct {
|
||||
c3_w mug_w; // current hash
|
||||
c3_o buc_o; // yes if current hash has a bucket
|
||||
c3_w inx_w; // index into current hash bucket iff buc_o
|
||||
} arm_u; // clock arm
|
||||
u3h_slot sot_w[64];
|
||||
} u3h_root;
|
||||
|
||||
|
314
noun/hashtable.c
314
noun/hashtable.c
@ -4,7 +4,7 @@
|
||||
#include "all.h"
|
||||
|
||||
static void _ch_slot_put(u3h_slot* sot_w, u3_noun kev, c3_w lef_w, c3_w rem_w, c3_w* use_w);
|
||||
static c3_o _ch_trim_slot(u3h_slot *sot_w, c3_w lef_w);
|
||||
static c3_o _ch_step_slot(u3h_slot *sot_w, c3_w lef_w, c3_w rem_w, c3_w* buc_w);
|
||||
|
||||
/* u3h_new_cache(): create hashtable with bounded size.
|
||||
*/
|
||||
@ -143,9 +143,6 @@ _ch_node_add(u3h_node* han_u, c3_w lef_w, c3_w rem_w, u3_noun kev, c3_w *use_w)
|
||||
u3h_node* nah_u = u3a_walloc(c3_wiseof(u3h_node) +
|
||||
((len_w + 1) * c3_wiseof(u3h_slot)));
|
||||
nah_u->map_w = han_u->map_w | (1 << bit_w);
|
||||
// arm_w should always be one past the thing we just put in,
|
||||
// to avoid pathological hash-ordering behavior
|
||||
nah_u->arm_w = (inx_w + 1) % (len_w + 1);
|
||||
|
||||
for ( i_w = 0; i_w < inx_w; i_w++ ) {
|
||||
nah_u->sot_w[i_w] = han_u->sot_w[i_w];
|
||||
@ -222,131 +219,6 @@ u3h_put(u3p(u3h_root) har_p, u3_noun key, u3_noun val)
|
||||
}
|
||||
}
|
||||
|
||||
static c3_o
|
||||
_ch_trim_buck(u3h_slot* sot_w)
|
||||
{
|
||||
u3h_buck* hab_u = (u3h_buck*) u3h_slot_to_node(*sot_w);
|
||||
c3_w i_w, j_w, len_w = hab_u->len_w;
|
||||
|
||||
for ( i_w = hab_u->arm_w; i_w < len_w; ++i_w ) {
|
||||
u3h_slot* tos_w = &(hab_u->sot_w[i_w]);
|
||||
hab_u->arm_w += 1;
|
||||
if ( c3y == _ch_trim_slot(tos_w, 0) ) {
|
||||
// child always shrinks in bucket
|
||||
if ( 2 == len_w ) {
|
||||
// pick one of two items in bucket
|
||||
*sot_w = hab_u->sot_w[ (0 == i_w) ? 1 : 0 ];
|
||||
}
|
||||
else {
|
||||
// make smaller bucket
|
||||
c3_w nel_w = len_w - 1;
|
||||
u3h_buck* bah_u = u3a_walloc(c3_wiseof(u3h_buck) +
|
||||
nel_w * c3_wiseof(u3h_slot));
|
||||
bah_u->len_w = nel_w;
|
||||
bah_u->arm_w = hab_u->arm_w;
|
||||
|
||||
for ( j_w = 0; j_w < i_w; ++j_w ) {
|
||||
bah_u->sot_w[j_w] = hab_u->sot_w[j_w];
|
||||
}
|
||||
for ( j_w = i_w; j_w < nel_w; ++j_w ) {
|
||||
bah_u->sot_w[j_w] = hab_u->sot_w[j_w + 1];
|
||||
}
|
||||
|
||||
*sot_w = u3h_node_to_slot(bah_u);
|
||||
}
|
||||
u3a_wfree(hab_u);
|
||||
return c3y;
|
||||
}
|
||||
}
|
||||
hab_u->arm_w = 0;
|
||||
return c3n;
|
||||
}
|
||||
|
||||
static c3_o
|
||||
_ch_trim_node(u3h_slot* sot_w, c3_w lef_w)
|
||||
{
|
||||
u3h_node* han_u = (u3h_node*) u3h_slot_to_node(*sot_w);
|
||||
c3_w i_w, j_w, len_w = _ch_popcount(han_u->map_w);
|
||||
lef_w -= 5;
|
||||
|
||||
for ( i_w = han_u->arm_w; i_w < len_w; ++i_w ) {
|
||||
u3h_slot* tos_w = &(han_u->sot_w[i_w]);
|
||||
if ( c3y == _ch_trim_slot(tos_w, lef_w) ) {
|
||||
if ( 0 == *tos_w ) {
|
||||
// entire child is gone, need to shrink
|
||||
if ( 2 == len_w ) {
|
||||
// shrink to a single key-value pair
|
||||
*sot_w = han_u->sot_w[ (0 == i_w) ? 1 : 0 ];
|
||||
}
|
||||
else {
|
||||
// shrink to a smaller node
|
||||
c3_w nel_w = len_w - 1;
|
||||
u3h_node* nah_u = u3a_walloc(c3_wiseof(u3h_node) +
|
||||
(nel_w * c3_wiseof(u3h_slot)));
|
||||
nah_u->arm_w = han_u->arm_w;
|
||||
nah_u->map_w = han_u->map_w & ~(1 << i_w);
|
||||
|
||||
for ( j_w = 0; j_w < i_w; ++j_w ) {
|
||||
nah_u->sot_w[j_w] = han_u->sot_w[j_w];
|
||||
}
|
||||
for ( j_w = i_w; j_w < nel_w; ++j_w ) {
|
||||
nah_u->sot_w[j_w] = han_u->sot_w[j_w + 1];
|
||||
}
|
||||
*sot_w = u3h_node_to_slot(nah_u);
|
||||
}
|
||||
u3a_wfree(han_u);
|
||||
}
|
||||
return c3y;
|
||||
}
|
||||
else {
|
||||
han_u->arm_w += 1;
|
||||
}
|
||||
}
|
||||
|
||||
han_u->arm_w = 0;
|
||||
return c3n;
|
||||
}
|
||||
|
||||
static c3_o
|
||||
_ch_trim_some(u3h_slot* sot_w, c3_w lef_w)
|
||||
{
|
||||
if ( 0 == lef_w ) {
|
||||
return _ch_trim_buck(sot_w);
|
||||
}
|
||||
else {
|
||||
return _ch_trim_node(sot_w, lef_w);
|
||||
}
|
||||
}
|
||||
|
||||
/* _ch_trim_slot(): trim one key-value pair from slot */
|
||||
static c3_o
|
||||
_ch_trim_slot(u3h_slot *sot_w, c3_w lef_w)
|
||||
{
|
||||
if ( c3y == u3h_slot_is_null(*sot_w) ) {
|
||||
return c3n;
|
||||
}
|
||||
else {
|
||||
if ( c3y == u3h_slot_is_noun(*sot_w) ) {
|
||||
if ( c3y == u3h_slot_is_warm(*sot_w) ) {
|
||||
*sot_w = u3h_noun_be_cold(*sot_w);
|
||||
return c3n;
|
||||
}
|
||||
else {
|
||||
u3_noun kev = u3h_slot_to_noun(*sot_w);
|
||||
fprintf(stderr, "addr: %p\r\n", kev);
|
||||
u3m_p("losing(trim)", kev);
|
||||
u3z(kev);
|
||||
*sot_w = 0;
|
||||
return c3y;
|
||||
}
|
||||
}
|
||||
else {
|
||||
c3_assert( c3y == u3h_slot_is_node(*sot_w) );
|
||||
return _ch_trim_some(sot_w, lef_w);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* _ch_trim_root(): trim one key-value pair from root
|
||||
*/
|
||||
static void
|
||||
@ -356,23 +228,189 @@ _ch_trim_root(u3h_root *har_u)
|
||||
c3_assert(har_u->use_w > 0);
|
||||
|
||||
while ( 1 ) {
|
||||
sot_w = &(har_u->sot_w[har_u->arm_w]);
|
||||
har_u->arm_w = (har_u->arm_w + 1) % 64;
|
||||
if ( c3y == _ch_trim_slot(sot_w, 25) ) {
|
||||
har_u->use_w -= 1;
|
||||
return;
|
||||
}
|
||||
// TODO
|
||||
}
|
||||
}
|
||||
|
||||
/* BREATHING ROOM
|
||||
*
|
||||
*/
|
||||
|
||||
static c3_o
|
||||
_ch_step_node(u3h_slot* sot_w, c3_w lef_w, c3_w rem_w)
|
||||
{
|
||||
c3_w bit_w, map_w, inx_w;
|
||||
u3h_slot* tos_w;
|
||||
u3h_node* han_u = (u3h_node*) u3h_slot_to_node(sot_w);
|
||||
|
||||
lef_w -= 5;
|
||||
bit_w = (rem_w >> lef_w);
|
||||
rem_w = (rem_w & ((1 << lef_w) - 1));
|
||||
map_w = han_u->map_w;
|
||||
inx_w = _ch_popcount(map_w & ((1 << bit_w) - 1));
|
||||
tos_w = &(han_u->sot_w[inx_w]);
|
||||
|
||||
if ( c3n == _ch_step_slot(tos_w, lef_w, rem_w) ) {
|
||||
// nothing trimmed
|
||||
return c3n;
|
||||
}
|
||||
else if ( 0 != *tos_w ) {
|
||||
// something trimmed, but slot still has value
|
||||
return c3y;
|
||||
}
|
||||
else {
|
||||
// shrink!
|
||||
c3_w i_w, len_w = _ch_popcount(map_w);
|
||||
|
||||
if ( 2 == len_w ) {
|
||||
// only one left, pick the other
|
||||
*sot_w = han_u->sot_w[ 0 == inx_w ? 1 : 0 ];
|
||||
}
|
||||
else {
|
||||
// make smaller node
|
||||
c3_w nel_w = len_w - 1;
|
||||
u3h_node* nah_u = u3a_walloc(c3_wiseof(u3h_node) +
|
||||
(nel_w * c3_wiseof(u3h_slot)));
|
||||
nah_u->map_w = han_u->map_w & ~(1 << bit_w);
|
||||
|
||||
for ( i_w = 0; i_w < inx_w; ++i_w ) {
|
||||
nah_u->sot_w[i_w] = han_u->sot_w[i_w];
|
||||
}
|
||||
for ( i_w = inx_w; i_w < nel_w; ++i_w ) {
|
||||
nah_u->sot_w[i_w] = han_u->sot_w[i_w + 1];
|
||||
}
|
||||
*sot_w = u3h_node_to_slot(nah_u);
|
||||
}
|
||||
u3a_wfree(han_u);
|
||||
return c3y;
|
||||
}
|
||||
}
|
||||
|
||||
static c3_o
|
||||
_ch_step_buck(u3h_slot* sot_w, c3_w *buc_w)
|
||||
{
|
||||
c3_w len_w;
|
||||
u3h_buck* hab_u = u3h_slot_to_node(*sot_w);
|
||||
|
||||
for ( len_w = hab_u->len_w; *buc_w < len_w; ++*buc_w ) {
|
||||
u3h_slot* tos_w = &(hab_u->sot_w[*buc_w]);
|
||||
if ( c3y == _ch_step_slot(tos_w, 0, 0) ) {
|
||||
if ( 2 == len_w ) {
|
||||
// 2 things in bucket: pick the other and promote
|
||||
*sot_w = hab_u->sot_w[ (0 == *buc_w) ? 1 : 0 ];
|
||||
}
|
||||
else {
|
||||
// make a smaller bucket
|
||||
c3_w i_w, nel_w = len_w - 1;
|
||||
u3h_buck* bah_u = u3a_walloc(c3_wiseof(u3h_buck) +
|
||||
nel_w * c3_wiseof(u3h_slot));
|
||||
bah_u->len_w = nel_w;
|
||||
for ( i_w = 0; i_w < *buc_w; ++i_w ) {
|
||||
bah_u->sot_w[i_w] = hab_u->sot_w[i_w];
|
||||
}
|
||||
for ( i_w = *buc_w; i_w < nel_w; ++i_w ) {
|
||||
bah_u->sot_w[i_w] = hab_u->sot_w[i_w + 1];
|
||||
}
|
||||
*sot_w = bah_u;
|
||||
}
|
||||
u3a_wfree(hab_u);
|
||||
return c3y;
|
||||
}
|
||||
}
|
||||
return c3n;
|
||||
}
|
||||
|
||||
static c3_o
|
||||
_ch_step_some(u3h_slot* sot_w, c3_w* buc_w, c3_w lef_w, c3_w rem_w)
|
||||
{
|
||||
if ( 0 == lef_w ) {
|
||||
return _ch_step_buck(sot_w, buc_w);
|
||||
}
|
||||
else {
|
||||
return _ch_step_node(sot_w, buc_w, lef_w, rem_w);
|
||||
}
|
||||
}
|
||||
|
||||
static c3_o
|
||||
_ch_step_slot(u3h_slot *sot_w, c3_w lef_w, c3_w rem_w, c3_w* buc_w) {
|
||||
if ( _(u3h_slot_is_null(*sot_w)) ) {
|
||||
return c3n;
|
||||
}
|
||||
else if ( _(u3h_slot_is_node(*sot_w)) ) {
|
||||
return _ch_step_some(sot_w, lef_w, rem_w, buc_w);
|
||||
}
|
||||
else if ( _(u3h_slot_is_warm(*sot_w)) ) {
|
||||
*sot_w = u3h_noun_be_cold(*sot_w);
|
||||
return c3n;
|
||||
}
|
||||
else {
|
||||
u3_noun kev = u3h_slot_to_noun(*sot_w);
|
||||
*sot_w = 0;
|
||||
u3z(kev);
|
||||
return c3y;
|
||||
}
|
||||
}
|
||||
|
||||
static c3_o
|
||||
_ch_step_root(u3h_root* har_u)
|
||||
{
|
||||
c3_w mug_w = har_u->arm_u.clk_w;
|
||||
c3_w inx_w = mug_w >> 25; // 6 bits
|
||||
c3_w rem_w = mug_w & ((1 << 25) - 1);
|
||||
u3h_slot* sot_w = &(har_u->sot_w[inx_w]);
|
||||
return _ch_step_slot(sot_w, 25, rem);
|
||||
}
|
||||
/*
|
||||
if ( _(u3h_slot_is_null(*sot_w)) ) {
|
||||
return c3n;
|
||||
}
|
||||
else if ( _(u3h_slot_is_node(*sot_w)) ) {
|
||||
c3_w rem_w = (mug_w & ((1 << 25) - 1));
|
||||
return _ch_step_node((u3h_node*)u3h_slot_to_node(*sot_w), 25, rem_w);
|
||||
}
|
||||
else if ( _(u3h_slot_is_warm(*sot_w)) ) {
|
||||
*sot_w = u3h_noun_be_warm(*sot_w);
|
||||
}
|
||||
else {
|
||||
u3_noun kev = u3h_slot_to_noun(*sot_w);
|
||||
*sot_w = 0;
|
||||
u3z(kev);
|
||||
return c3y;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
void
|
||||
u3h_del(u3p(u3h_root) har_p, u3_noun key)
|
||||
{
|
||||
u3h_root* har_u = u3to(u3h_root, har_p);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
|
||||
/* u3h_trim_to(): trim to n key-value pairs
|
||||
*/
|
||||
void
|
||||
u3h_trim_to(u3p(u3h_root) har_p, c3_w n_w)
|
||||
{
|
||||
u3h_root* har_u = u3to(u3h_root, har_p);
|
||||
while ( har_u->use_w > n_w ) {
|
||||
_ch_trim_root(har_u);
|
||||
u3h_root* har_u = u3to(u3h_root, har_p);
|
||||
for ( har_u = u3to(u3h_root, har_p);
|
||||
har_u->use_w > n_w;
|
||||
har_u->clk_w = (har_u->clk_w + 1) & 0x80000000 ) { // lower 31 bits
|
||||
u3h_slot* sot_w = _ch_get_slot(har_u->clk_w);
|
||||
if ( _(u3h_slot_is_null(*sot_w) ) ) {
|
||||
continue;
|
||||
}
|
||||
else if ( _(u3h_slot_is_node) ) {
|
||||
//
|
||||
}
|
||||
else if ( _(u3h_slot_is_warm(*sot_w)) ) {
|
||||
*sot_w = u3h_noun_be_cold(*sot_w);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user