extend ctrl process memory cache reads with freshness info - it is a bit too coarse grained at page granularity, that should've been easy to predict... in any case, to start addressing that, start keeping >1 hash key hash history in hash store layer, such that history may be preserved for a bit longer & diff'd with new key hashes

This commit is contained in:
Ryan Fleury
2024-01-25 09:06:03 -08:00
parent 76b2facbf4
commit d0c3d9dc21
8 changed files with 93 additions and 39 deletions
+20 -9
View File
@@ -754,10 +754,10 @@ ctrl_process_read(CTRL_MachineID machine_id, CTRL_Handle process, Rng1U64 range,
return actual_bytes_read;
}
internal String8
internal CTRL_ProcessMemorySlice
ctrl_query_cached_data_from_process_vaddr_range(Arena *arena, CTRL_MachineID machine_id, CTRL_Handle process, Rng1U64 range)
{
String8 result = {0};
CTRL_ProcessMemorySlice result = {0};
if(range.max > range.min &&
dim_1u64(range) <= MB(256) &&
range.min <= 0x000FFFFFFFFFFFFFull &&
@@ -821,6 +821,7 @@ ctrl_query_cached_data_from_process_vaddr_range(Arena *arena, CTRL_MachineID mac
{
page_found = 1;
MemoryCopy((U8*)read_out + (page_vaddr-page_range.min), page_data.str, KB(4));
result.fresh = result.fresh || !!(node4->page_fresh_flags[lvl5_idx/64] & (1ull<<(lvl5_idx%64)));
}
else
{
@@ -898,6 +899,16 @@ ctrl_query_cached_data_from_process_vaddr_range(Arena *arena, CTRL_MachineID mac
};
U128 page_key = hs_hash_from_data(str8((U8 *)page_key_data, sizeof(page_key_data)));
U128 page_hash = hs_submit_data(page_key, &page_arena, str8((U8 *)page_base, KB(4)));
if(!u128_match(node4->page_hashes[lvl5_idx], u128_zero()) &&
!u128_match(node4->page_hashes[lvl5_idx], page_hash))
{
node4->page_fresh_flags[lvl5_idx/64] |= (1ull<<(lvl5_idx%64));
}
else
{
node4->page_fresh_flags[lvl5_idx/64] &= ~(1ull<<(lvl5_idx%64));
}
result.fresh = result.fresh || !!(node4->page_fresh_flags[lvl5_idx/64] & (1ull<<(lvl5_idx%64)));
node4->page_hashes[lvl5_idx] = page_hash;
}
else
@@ -910,22 +921,22 @@ ctrl_query_cached_data_from_process_vaddr_range(Arena *arena, CTRL_MachineID mac
//- rjf: fill result by skipping/chopping read memory
U64 byte_in_page_idx = (range.min&0x0000000000000FFFull) >> 0;
result.str = (U8*)read_out + byte_in_page_idx;
result.size = dim_1u64(range);
result.data.str = (U8*)read_out + byte_in_page_idx;
result.data.size = dim_1u64(range);
hs_scope_close(scope);
}
return result;
}
internal String8
internal CTRL_ProcessMemorySlice
ctrl_query_cached_zero_terminated_data_from_process_vaddr_limit(Arena *arena, CTRL_MachineID machine_id, CTRL_Handle process, U64 vaddr, U64 limit, U64 endt_us)
{
String8 result = ctrl_query_cached_data_from_process_vaddr_range(arena, machine_id, process, r1u64(vaddr, vaddr+limit));
for(U64 idx = 0; idx < result.size; idx += 1)
CTRL_ProcessMemorySlice result = ctrl_query_cached_data_from_process_vaddr_range(arena, machine_id, process, r1u64(vaddr, vaddr+limit));
for(U64 idx = 0; idx < result.data.size; idx += 1)
{
if(result.str[idx] == 0)
if(result.data.str[idx] == 0)
{
result.size = idx;
result.data.size = idx;
break;
}
}
+11 -2
View File
@@ -333,6 +333,8 @@ struct CTRL_ProcessMemoryCacheNode4
{
U64 page_memgen_idxs[256];
U128 page_hashes[256];
U128 last_page_hashes[256];
U64 page_fresh_flags[4];
};
typedef struct CTRL_ProcessMemoryCacheNode3 CTRL_ProcessMemoryCacheNode3;
@@ -406,6 +408,13 @@ struct CTRL_ProcessMemoryCache
CTRL_ProcessMemoryCacheStripe *stripes;
};
typedef struct CTRL_ProcessMemorySlice CTRL_ProcessMemorySlice;
struct CTRL_ProcessMemorySlice
{
String8 data;
B32 fresh;
};
////////////////////////////////
//~ rjf: Wakeup Hook Function Types
@@ -560,8 +569,8 @@ internal Architecture ctrl_arch_from_handle(CTRL_MachineID machine, CTRL_Handle
//- rjf: process memory reading/writing
internal U64 ctrl_process_read(CTRL_MachineID machine_id, CTRL_Handle process, Rng1U64 range, void *dst);
internal String8 ctrl_query_cached_data_from_process_vaddr_range(Arena *arena, CTRL_MachineID machine_id, CTRL_Handle process, Rng1U64 range);
internal String8 ctrl_query_cached_zero_terminated_data_from_process_vaddr_limit(Arena *arena, CTRL_MachineID machine_id, CTRL_Handle process, U64 vaddr, U64 limit, U64 endt_us);
internal CTRL_ProcessMemorySlice ctrl_query_cached_data_from_process_vaddr_range(Arena *arena, CTRL_MachineID machine_id, CTRL_Handle process, Rng1U64 range);
internal CTRL_ProcessMemorySlice ctrl_query_cached_zero_terminated_data_from_process_vaddr_limit(Arena *arena, CTRL_MachineID machine_id, CTRL_Handle process, U64 vaddr, U64 limit, U64 endt_us);
internal B32 ctrl_process_write_data(CTRL_MachineID machine_id, CTRL_Handle process, U64 vaddr, String8 data);
internal U128 ctrl_stored_hash_from_process_vaddr_range(CTRL_MachineID machine_id, CTRL_Handle process, Rng1U64 range, B32 zero_terminated);
+14 -8
View File
@@ -3486,12 +3486,14 @@ df_tls_base_vaddr_from_thread(DF_Entity *thread)
U64 thread_info_addr = ctrl_tls_root_vaddr_from_thread(thread->ctrl_machine_id, thread->ctrl_handle);
U64 tls_addr_off = tls_index*addr_size;
U64 tls_addr_array = 0;
String8 tls_addr_array_data = ctrl_query_cached_data_from_process_vaddr_range(scratch.arena, process->ctrl_machine_id, process->ctrl_handle, r1u64(thread_info_addr, thread_info_addr+addr_size));
CTRL_ProcessMemorySlice tls_addr_array_slice = ctrl_query_cached_data_from_process_vaddr_range(scratch.arena, process->ctrl_machine_id, process->ctrl_handle, r1u64(thread_info_addr, thread_info_addr+addr_size));
String8 tls_addr_array_data = tls_addr_array_slice.data;
if(tls_addr_array_data.size >= 8)
{
MemoryCopy(&tls_addr_array, tls_addr_array_data.str, sizeof(U64));
}
String8 result_data = ctrl_query_cached_data_from_process_vaddr_range(scratch.arena, process->ctrl_machine_id, process->ctrl_handle, r1u64(tls_addr_array + tls_addr_off, tls_addr_array + tls_addr_off + addr_size));
CTRL_ProcessMemorySlice result_slice = ctrl_query_cached_data_from_process_vaddr_range(scratch.arena, process->ctrl_machine_id, process->ctrl_handle, r1u64(tls_addr_array + tls_addr_off, tls_addr_array + tls_addr_off + addr_size));
String8 result_data = result_slice.data;
if(result_data.size >= 8)
{
MemoryCopy(&base_vaddr, result_data.str, sizeof(U64));
@@ -3953,7 +3955,8 @@ df_eval_memory_read(void *u, void *out, U64 addr, U64 size)
Assert(process->kind == DF_EntityKind_Process);
Temp scratch = scratch_begin(0, 0);
B32 result = 0;
String8 data = ctrl_query_cached_data_from_process_vaddr_range(scratch.arena, process->ctrl_machine_id, process->ctrl_handle, r1u64(addr, addr+size));
CTRL_ProcessMemorySlice slice = ctrl_query_cached_data_from_process_vaddr_range(scratch.arena, process->ctrl_machine_id, process->ctrl_handle, r1u64(addr, addr+size));
String8 data = slice.data;
if(data.size == size)
{
result = 1;
@@ -4251,7 +4254,8 @@ df_value_mode_eval_from_eval(TG_Graph *graph, RADDBG_Parsed *rdbg, DF_CtrlCtx *c
Rng1U64 vaddr_range = r1u64(eval.offset, eval.offset + type_byte_size);
if(dim_1u64(vaddr_range) == type_byte_size)
{
String8 data = ctrl_query_cached_data_from_process_vaddr_range(scratch.arena, process->ctrl_machine_id, process->ctrl_handle, vaddr_range);
CTRL_ProcessMemorySlice slice = ctrl_query_cached_data_from_process_vaddr_range(scratch.arena, process->ctrl_machine_id, process->ctrl_handle, vaddr_range);
String8 data = slice.data;
MemoryZeroArray(eval.imm_u128);
MemoryCopy(eval.imm_u128, data.str, Min(data.size, sizeof(U64)*2));
eval.mode = EVAL_EvalMode_Value;
@@ -4328,14 +4332,16 @@ df_dynamically_typed_eval_from_eval(TG_Graph *graph, RADDBG_Parsed *rdbg, DF_Ctr
{
U64 ptr_vaddr = eval.offset;
U64 addr_size = bit_size_from_arch(arch)/8;
String8 ptr_value_memory = ctrl_query_cached_data_from_process_vaddr_range(scratch.arena, process->ctrl_machine_id, process->ctrl_handle,
r1u64(ptr_vaddr, ptr_vaddr+addr_size));
CTRL_ProcessMemorySlice ptr_value_slice = ctrl_query_cached_data_from_process_vaddr_range(scratch.arena, process->ctrl_machine_id, process->ctrl_handle,
r1u64(ptr_vaddr, ptr_vaddr+addr_size));
String8 ptr_value_memory = ptr_value_slice.data;
if(ptr_value_memory.size >= addr_size)
{
U64 class_base_vaddr = 0;
MemoryCopy(&class_base_vaddr, ptr_value_memory.str, addr_size);
String8 vtable_base_ptr_memory = ctrl_query_cached_data_from_process_vaddr_range(scratch.arena, process->ctrl_machine_id, process->ctrl_handle,
r1u64(class_base_vaddr, class_base_vaddr+addr_size));
CTRL_ProcessMemorySlice vtable_base_ptr_slice = ctrl_query_cached_data_from_process_vaddr_range(scratch.arena, process->ctrl_machine_id, process->ctrl_handle,
r1u64(class_base_vaddr, class_base_vaddr+addr_size));
String8 vtable_base_ptr_memory = vtable_base_ptr_slice.data;
if(vtable_base_ptr_memory.size >= addr_size)
{
U64 vtable_vaddr = 0;
+12 -7
View File
@@ -6786,7 +6786,8 @@ df_single_line_eval_value_strings_from_eval(Arena *arena, DF_EvalVizStringFlags
if(!has_array && direct_type_is_string && (flags & DF_EvalVizStringFlag_ReadOnlyDisplayRules) && eval.mode == EVAL_EvalMode_Addr)
{
U64 string_memory_addr = value_eval.imm_u64;
String8 text = ctrl_query_cached_zero_terminated_data_from_process_vaddr_limit(arena, process->ctrl_machine_id, process->ctrl_handle, string_memory_addr, 256, max_U64);
CTRL_ProcessMemorySlice text_slice = ctrl_query_cached_zero_terminated_data_from_process_vaddr_limit(arena, process->ctrl_machine_id, process->ctrl_handle, string_memory_addr, 256, max_U64);
String8 text = text_slice.data;
space_taken += f_dim_from_tag_size_string(font, font_size, text).x;
space_taken += 2*f_dim_from_tag_size_string(font, font_size, str8_lit("\"")).x;
str8_list_push(arena, &list, str8_lit("\""));
@@ -6858,7 +6859,8 @@ df_single_line_eval_value_strings_from_eval(Arena *arena, DF_EvalVizStringFlags
special_case = 1;
DF_Entity *thread = df_entity_from_handle(ctrl_ctx->thread);
DF_Entity *process = df_entity_ancestor_from_kind(thread, DF_EntityKind_Process);
String8 text = ctrl_query_cached_zero_terminated_data_from_process_vaddr_limit(arena, process->ctrl_machine_id, process->ctrl_handle, eval.offset, 256, max_U64);
CTRL_ProcessMemorySlice text_slice = ctrl_query_cached_zero_terminated_data_from_process_vaddr_limit(arena, process->ctrl_machine_id, process->ctrl_handle, eval.offset, 256, max_U64);
String8 text = text_slice.data;
space_taken += f_dim_from_tag_size_string(font, font_size, text).x;
space_taken += 2*f_dim_from_tag_size_string(font, font_size, str8_lit("\"")).x;
str8_list_push(arena, &list, str8_lit("\""));
@@ -9009,6 +9011,9 @@ df_code_slice(DF_Window *ws, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, DF_
ProfBeginFunction();
Temp scratch = scratch_begin(0, 0);
DF_Entity *selected_thread = df_entity_from_handle(ctrl_ctx->thread);
DF_Entity *selected_thread_process = df_entity_ancestor_from_kind(selected_thread, DF_EntityKind_Process);
U64 selected_thread_rip_unwind_vaddr = df_query_cached_rip_from_thread_unwind(selected_thread, ctrl_ctx->unwind_count);
DF_Entity *selected_thread_module = df_module_from_process_vaddr(selected_thread_process, selected_thread_rip_unwind_vaddr);
CTRL_Event stop_event = df_ctrl_last_stop_event();
DF_Entity *stopper_thread = df_entity_from_ctrl_handle(stop_event.machine_id, stop_event.entity);
B32 is_focused = ui_is_focus_active();
@@ -9847,7 +9852,7 @@ df_code_slice(DF_Window *ws, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, DF_
{
has_line_info = (src2dasm_list->first->v.remap_line == line_num);
line_info_line_num = line_num;
line_info_t = src2dasm_list->first->v.binary->alive_t;
line_info_t = selected_thread_module->alive_t;
}
if(dasm2src_list->first != 0)
{
@@ -9866,7 +9871,7 @@ df_code_slice(DF_Window *ws, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, DF_
DF_Entity *binary = dasm2src_info->binary;
has_line_info = 1;
line_info_line_num = dasm2src_info->pt.line;
line_info_t = binary->alive_t;
line_info_t = selected_thread_module->alive_t;
}
}
if(has_line_info)
@@ -9969,7 +9974,7 @@ df_code_slice(DF_Window *ws, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, DF_
{
mapped_special = 1;
new_color_kind = DF_ThemeColor_CodeFunction;
mix_t = binary->alive_t;
mix_t = selected_thread_module->alive_t;
}
}
if(!mapped_special)
@@ -9979,7 +9984,7 @@ df_code_slice(DF_Window *ws, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, DF_
{
mapped_special = 1;
new_color_kind = DF_ThemeColor_CodeType;
mix_t = binary->alive_t;
mix_t = selected_thread_module->alive_t;
}
}
if(!mapped_special)
@@ -9989,7 +9994,7 @@ df_code_slice(DF_Window *ws, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, DF_
{
mapped_special = 1;
new_color_kind = DF_ThemeColor_CodeLocal;
mix_t = binary->alive_t;
mix_t = selected_thread_module->alive_t;
}
}
break;
+4 -2
View File
@@ -30,7 +30,8 @@ df_view_rule_hooks__rgba_from_eval(DF_Eval eval, TG_Graph *graph, RADDBG_Parsed
U64 array_total_size = tg_byte_size_from_graph_raddbg_key(graph, raddbg, type_key);
U64 array_total_size_capped = ClampTop(array_total_size, 64);
Rng1U64 array_memory_vaddr_rng = r1u64(eval.offset, eval.offset + array_total_size_capped);
String8 array_memory = ctrl_query_cached_data_from_process_vaddr_range(scratch.arena, process->ctrl_machine_id, process->ctrl_handle, array_memory_vaddr_rng);
CTRL_ProcessMemorySlice array_slice = ctrl_query_cached_data_from_process_vaddr_range(scratch.arena, process->ctrl_machine_id, process->ctrl_handle, array_memory_vaddr_rng);
String8 array_memory = array_slice.data;
TG_Key element_type_key = tg_unwrapped_direct_from_graph_raddbg_key(graph, raddbg, type_key);
TG_Kind element_type_kind = tg_kind_from_key(element_type_key);
U64 element_type_size = tg_byte_size_from_graph_raddbg_key(graph, raddbg, element_type_key);
@@ -66,7 +67,8 @@ df_view_rule_hooks__rgba_from_eval(DF_Eval eval, TG_Graph *graph, RADDBG_Parsed
U64 struct_total_size = tg_byte_size_from_graph_raddbg_key(graph, raddbg, type_key);
U64 struct_total_size_capped = ClampTop(struct_total_size, 64);
Rng1U64 struct_memory_vaddr_rng = r1u64(eval.offset, eval.offset + struct_total_size_capped);
String8 struct_memory = ctrl_query_cached_data_from_process_vaddr_range(scratch.arena, process->ctrl_machine_id, process->ctrl_handle, struct_memory_vaddr_rng);
CTRL_ProcessMemorySlice struct_slice = ctrl_query_cached_data_from_process_vaddr_range(scratch.arena, process->ctrl_machine_id, process->ctrl_handle, struct_memory_vaddr_rng);
String8 struct_memory = struct_slice.data;
TG_Type *type = tg_type_from_graph_raddbg_key(scratch.arena, graph, raddbg, type_key);
for(U64 element_idx = 0, member_idx = 0;
element_idx < 4 && member_idx < type->count;
+17 -1
View File
@@ -1032,7 +1032,23 @@ df_eval_watch_view_build(DF_Window *ws, DF_Panel *panel, DF_View *view, DF_EvalW
//- rjf: build normal row
if(!(row->flags & DF_EvalVizRowFlag_Canvas))
{
ui_set_next_flags(disabled_flags);
B32 row_is_fresh = 0;
if(row->eval.mode == EVAL_EvalMode_Addr)
{
Temp temp = temp_begin(scratch.arena);
U64 vaddr = row->eval.offset;
U64 size = tg_byte_size_from_graph_raddbg_key(parse_ctx.type_graph, parse_ctx.rdbg, row->eval.type_key);
CTRL_ProcessMemorySlice slice = ctrl_query_cached_data_from_process_vaddr_range(scratch.arena, process->ctrl_machine_id, process->ctrl_handle, r1u64(vaddr, vaddr+size));
row_is_fresh = slice.fresh;
temp_end(temp);
}
ui_set_next_flags(disabled_flags|(UI_BoxFlag_DrawBackground*row_is_fresh));
if(row_is_fresh)
{
Vec4F32 fresh_bg_color = df_rgba_from_theme_color(DF_ThemeColor_Highlight0);
fresh_bg_color.w *= 0.25f;
ui_set_next_background_color(fresh_bg_color);
}
UI_NamedTableVectorF("row_%I64x", row_hash)
{
//- rjf: expression
+13 -9
View File
@@ -122,7 +122,7 @@ hs_submit_data(U128 key, Arena **data_arena, String8 data)
}
//- rjf: commit this hash to key cache
U128 key_old_hash = {0};
U128 key_expired_hash = {0};
OS_MutexScopeW(key_stripe->rw_mutex)
{
HS_KeyNode *key_node = 0;
@@ -142,15 +142,19 @@ hs_submit_data(U128 key, Arena **data_arena, String8 data)
}
if(key_node)
{
key_old_hash = key_node->hash;
key_node->hash = hash;
if(key_node->hash_history_gen+1 >= ArrayCount(key_node->hash_history))
{
key_expired_hash = key_node->hash_history[(key_node->hash_history_gen-1)%ArrayCount(key_node->hash_history)];
}
key_node->hash_history[key_node->hash_history_gen%ArrayCount(key_node->hash_history)] = hash;
key_node->hash_history_gen += 1;
}
}
//- rjf: if this key was correllated with an old hash, dec key ref count of old hash
if(!u128_match(key_old_hash, u128_zero()))
//- rjf: if this key's history cache was full, dec key ref count of oldest hash
if(!u128_match(key_expired_hash, u128_zero()))
{
U64 old_hash_slot_idx = key_old_hash.u64[1]%hs_shared->slots_count;
U64 old_hash_slot_idx = key_expired_hash.u64[1]%hs_shared->slots_count;
U64 old_hash_stripe_idx = old_hash_slot_idx%hs_shared->stripes_count;
HS_Slot *old_hash_slot = &hs_shared->slots[old_hash_slot_idx];
HS_Stripe *old_hash_stripe = &hs_shared->stripes[old_hash_stripe_idx];
@@ -158,7 +162,7 @@ hs_submit_data(U128 key, Arena **data_arena, String8 data)
{
for(HS_Node *n = old_hash_slot->first; n != 0; n = n->next)
{
if(u128_match(n->hash, key_old_hash))
if(u128_match(n->hash, key_expired_hash))
{
ins_atomic_u64_dec_eval(&n->key_ref_count);
break;
@@ -250,9 +254,9 @@ hs_hash_from_key(U128 key)
{
for(HS_KeyNode *n = key_slot->first; n != 0; n = n->next)
{
if(u128_match(n->key, key))
if(u128_match(n->key, key) && n->hash_history_gen > 0)
{
result = n->hash;
result = n->hash_history[(n->hash_history_gen-1)%ArrayCount(n->hash_history)];
break;
}
}
+2 -1
View File
@@ -12,7 +12,8 @@ struct HS_KeyNode
{
HS_KeyNode *next;
U128 key;
U128 hash;
U128 hash_history[2];
U64 hash_history_gen;
};
typedef struct HS_KeySlot HS_KeySlot;