Skip to content

Commit 1d8abb1

Browse files
committed
switch to tighter cache for loaded debug infos
1 parent c318c10 commit 1d8abb1

File tree

2 files changed

+81
-47
lines changed

2 files changed

+81
-47
lines changed

src/raddbg/raddbg_core.c

Lines changed: 56 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -9992,6 +9992,12 @@ rd_init(CmdLine *cmdln)
99929992
cfg_node_new(rd_state->cfg, cfg_node_root(), str8_lit("transient"));
99939993
}
99949994

9995+
// rjf: set up loaded debug info cache
9996+
{
9997+
rd_state->loaded_dbg_info_slots_count = 4096;
9998+
rd_state->loaded_dbg_info_slots = push_array(arena, RD_LoadedDbgInfoSlot, rd_state->loaded_dbg_info_slots_count);
9999+
}
10000+
999510001
// rjf: set up window cache
999610002
{
999710003
rd_state->window_state_slots_count = 64;
@@ -10355,69 +10361,72 @@ rd_frame(void)
1035510361
}
1035610362

1035710363
//////////////////////////////
10358-
//- rjf: iterate all loaded debug infos, remove hot markers
10364+
//- rjf: apply debug info config trees -> loaded debug info cache
1035910365
//
10360-
if(rd_state->frame_depth == 1)
1036110366
{
10362-
CFG_Node *transient = cfg_node_child_from_string(cfg_node_root(), str8_lit("transient"));
10363-
CFG_Node *loaded_debug_infos = cfg_node_child_from_string_or_alloc(rd_state->cfg, transient, str8_lit("loaded_debug_infos"));
10364-
for(CFG_Node *child = loaded_debug_infos->first; child != &cfg_nil_node; child = child->next)
10365-
{
10366-
cfg_node_release(rd_state->cfg, cfg_node_child_from_string(child, str8_lit("hot")));
10367-
}
10368-
}
10369-
10370-
//////////////////////////////
10371-
//- rjf: iterate all loaded debug infos, touch their dbgi load markers
10372-
//
10373-
if(rd_state->frame_depth == 1)
10374-
{
10375-
CFG_Node *transient = cfg_node_child_from_string(cfg_node_root(), str8_lit("transient"));
10376-
CFG_Node *loaded_debug_infos = cfg_node_child_from_string_or_alloc(rd_state->cfg, transient, str8_lit("loaded_debug_infos"));
10367+
U64 current_update_tick_idx = update_tick_idx();
10368+
10369+
//- rjf: for each debug info config, reflect in cache - open if needed
1037710370
CFG_NodePtrList dbg_infos = cfg_node_top_level_list_from_string(scratch.arena, str8_lit("debug_info"));
1037810371
for EachNode(n, CFG_NodePtrNode, dbg_infos.first)
1037910372
{
10373+
// rjf: unpack debug info config
1038010374
CFG_Node *di = n->v;
1038110375
String8 path = rd_path_from_cfg(di);
1038210376
CFG_Node *di_timestamp = cfg_node_child_from_string(di, str8_lit("timestamp"));
1038310377
U64 timestamp = 0;
1038410378
try_u64_from_str8_c_rules(di_timestamp->first->string, &timestamp);
10385-
String8 loaded_di_key = push_str8f(scratch.arena, "$%I64x `%S` `%I64u`", di->id, path, timestamp);
10386-
CFG_Node *loaded_di = cfg_node_child_from_string(loaded_debug_infos, loaded_di_key);
10387-
if(loaded_di == &cfg_nil_node)
10379+
DI_Key key = di_key_from_path_timestamp(path, timestamp);
10380+
10381+
// rjf: touch in cache
10382+
U64 hash = u64_hash_from_str8(str8_struct(&key));
10383+
U64 slot_idx = hash%rd_state->loaded_dbg_info_slots_count;
10384+
RD_LoadedDbgInfoSlot *slot = &rd_state->loaded_dbg_info_slots[slot_idx];
10385+
RD_LoadedDbgInfoNode *node = 0;
10386+
for(RD_LoadedDbgInfoNode *n = slot->first; n != 0; n = n->hash_next)
1038810387
{
10389-
loaded_di = cfg_node_new(rd_state->cfg, loaded_debug_infos, loaded_di_key);
10390-
CFG_Node *path_node = cfg_node_new(rd_state->cfg, loaded_di, str8_lit("path"));
10391-
cfg_node_new(rd_state->cfg, path_node, path);
10392-
CFG_Node *timestamp_node = cfg_node_new(rd_state->cfg, loaded_di, str8_lit("timestamp"));
10393-
cfg_node_new(rd_state->cfg, timestamp_node, di_timestamp->first->string);
10394-
DI_Key dbgi_key = di_key_from_path_timestamp(path, timestamp);
10395-
di_open(dbgi_key);
10388+
if(di_key_match(key, n->key))
10389+
{
10390+
node = n;
10391+
break;
10392+
}
1039610393
}
10397-
cfg_node_child_from_string_or_alloc(rd_state->cfg, loaded_di, str8_lit("hot"));
10394+
if(node == 0)
10395+
{
10396+
node = rd_state->free_loaded_dbg_info_node;
10397+
if(node)
10398+
{
10399+
SLLStackPop_N(rd_state->free_loaded_dbg_info_node, hash_next);
10400+
}
10401+
else
10402+
{
10403+
node = push_array(rd_state->arena, RD_LoadedDbgInfoNode, 1);
10404+
}
10405+
DLLPushBack_NP(slot->first, slot->last, node, hash_next, hash_prev);
10406+
node->key = key;
10407+
di_open(key);
10408+
}
10409+
node->last_tick_idx_touched = current_update_tick_idx;
10410+
DLLRemove_NP(rd_state->loaded_dbg_info_lru_first, rd_state->loaded_dbg_info_lru_last, node, lru_next, lru_prev);
10411+
DLLPushBack_NP(rd_state->loaded_dbg_info_lru_first, rd_state->loaded_dbg_info_lru_last, node, lru_next, lru_prev);
1039810412
}
10399-
}
10400-
10401-
//////////////////////////////
10402-
//- rjf: iterate all loaded debug infos, close those without hot markers
10403-
//
10404-
if(rd_state->frame_depth == 1)
10405-
{
10406-
CFG_Node *transient = cfg_node_child_from_string(cfg_node_root(), str8_lit("transient"));
10407-
CFG_Node *loaded_debug_infos = cfg_node_child_from_string_or_alloc(rd_state->cfg, transient, str8_lit("loaded_debug_infos"));
10408-
for(CFG_Node *child = loaded_debug_infos->first, *next = &cfg_nil_node; child != &cfg_nil_node; child = next)
10413+
10414+
//- rjf: iterate least-recently-used loaded debug infos - if any have not been updated this tick,
10415+
// then evict
10416+
for(RD_LoadedDbgInfoNode *n = rd_state->loaded_dbg_info_lru_first, *next = 0; n != 0; n = next)
1040910417
{
10410-
next = child->next;
10411-
if(cfg_node_child_from_string(child, str8_lit("hot")) == &cfg_nil_node)
10418+
next = n->lru_next;
10419+
if(n->last_tick_idx_touched >= current_update_tick_idx)
1041210420
{
10413-
CFG_Node *path_node = cfg_node_child_from_string(child, str8_lit("path"));
10414-
CFG_Node *timestamp_node = cfg_node_child_from_string(child, str8_lit("timestamp"));
10415-
U64 timestamp = 0;
10416-
try_u64_from_str8_c_rules(timestamp_node->first->string, &timestamp);
10417-
DI_Key dbgi_key = di_key_from_path_timestamp(path_node->first->string, timestamp);
10418-
di_close(dbgi_key, 0);
10419-
cfg_node_release(rd_state->cfg, child);
10421+
break;
1042010422
}
10423+
U64 hash = u64_hash_from_str8(str8_struct(&n->key));
10424+
U64 slot_idx = hash%rd_state->loaded_dbg_info_slots_count;
10425+
RD_LoadedDbgInfoSlot *slot = &rd_state->loaded_dbg_info_slots[slot_idx];
10426+
DLLRemove_NP(rd_state->loaded_dbg_info_lru_first, rd_state->loaded_dbg_info_lru_last, n, lru_next, lru_prev);
10427+
DLLRemove_NP(slot->first, slot->last, n, hash_next, hash_prev);
10428+
SLLStackPush_N(rd_state->free_loaded_dbg_info_node, n, hash_next);
10429+
di_close(n->key, 0);
1042110430
}
1042210431
}
1042310432

src/raddbg/raddbg_core.h

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -343,6 +343,24 @@ struct RD_WindowStateSlot
343343
////////////////////////////////
344344
//~ rjf: Main Per-Process Graphical State
345345

346+
typedef struct RD_LoadedDbgInfoNode RD_LoadedDbgInfoNode;
347+
struct RD_LoadedDbgInfoNode
348+
{
349+
RD_LoadedDbgInfoNode *hash_next;
350+
RD_LoadedDbgInfoNode *hash_prev;
351+
RD_LoadedDbgInfoNode *lru_next;
352+
RD_LoadedDbgInfoNode *lru_prev;
353+
DI_Key key;
354+
U64 last_tick_idx_touched;
355+
};
356+
357+
typedef struct RD_LoadedDbgInfoSlot RD_LoadedDbgInfoSlot;
358+
struct RD_LoadedDbgInfoSlot
359+
{
360+
RD_LoadedDbgInfoNode *first;
361+
RD_LoadedDbgInfoNode *last;
362+
};
363+
346364
typedef struct RD_AmbiguousPathNode RD_AmbiguousPathNode;
347365
struct RD_AmbiguousPathNode
348366
{
@@ -480,6 +498,13 @@ struct RD_State
480498
CFG_State *cfg;
481499
CFG_SchemaTable *cfg_schema_table;
482500

501+
// rjf: loaded debug info cache
502+
U64 loaded_dbg_info_slots_count;
503+
RD_LoadedDbgInfoSlot *loaded_dbg_info_slots;
504+
RD_LoadedDbgInfoNode *loaded_dbg_info_lru_first;
505+
RD_LoadedDbgInfoNode *loaded_dbg_info_lru_last;
506+
RD_LoadedDbgInfoNode *free_loaded_dbg_info_node;
507+
483508
// rjf: window state cache
484509
U64 window_state_slots_count;
485510
RD_WindowStateSlot *window_state_slots;

0 commit comments

Comments
 (0)