From 168f66cc99455774e60be4e27e6368af99762fe0 Mon Sep 17 00:00:00 2001 From: Ryan Fleury Date: Thu, 25 Jan 2024 11:17:16 -0800 Subject: [PATCH] further progress on new process memory cache; first pass at visualizing changed watch window rows, based on ctrl process memory cache history --- src/ctrl/ctrl_core.c | 62 +++++++++++++++++++++++++++++-------- src/ctrl/ctrl_core.h | 4 +-- src/df/gfx/df_gfx.c | 1 + src/df/gfx/df_views.c | 27 +++++++++++++++- src/hash_store/hash_store.c | 4 +-- src/scratch/ryan_scratch.c | 15 +++++---- 6 files changed, 87 insertions(+), 26 deletions(-) diff --git a/src/ctrl/ctrl_core.c b/src/ctrl/ctrl_core.c index a974beb4..0bc0b513 100644 --- a/src/ctrl/ctrl_core.c +++ b/src/ctrl/ctrl_core.c @@ -918,33 +918,32 @@ ctrl_query_cached_data_from_process_vaddr_range(Arena *arena, CTRL_MachineID mac U128 *page_hashes = push_array(scratch.arena, U128, page_count); U128 *page_last_hashes = push_array(scratch.arena, U128, page_count); - //- rjf: gather hashes for each page - for(U64 page_idx = 0; page_idx < page_count; page_idx += 1) - { - U64 page_base_vaddr = page_range.min + page_idx*page_size; - U128 page_hash = ctrl_stored_hash_from_process_vaddr_range(machine_id, process, r1u64(page_base_vaddr, page_base_vaddr+page_size), 0); - page_hashes[page_idx] = page_hash; - } - - //- rjf: gather last hashes for each page + //- rjf: gather hashes & last-hashes for each page for(U64 page_idx = 0; page_idx < page_count; page_idx += 1) { U64 page_base_vaddr = page_range.min + page_idx*page_size; U128 page_key = ctrl_hash_store_key_from_process_vaddr_range(machine_id, process, r1u64(page_base_vaddr, page_base_vaddr+page_size), 0); + U128 page_hash = ctrl_stored_hash_from_process_vaddr_range(machine_id, process, r1u64(page_base_vaddr, page_base_vaddr+page_size), 0); U128 page_last_hash = hs_hash_from_key(page_key, 1); + page_hashes[page_idx] = page_hash; page_last_hashes[page_idx] = page_last_hash; } - //- rjf: setup output buffer + //- rjf: setup output buffers void *read_out = push_array(arena, U8, dim_1u64(range)); + U64 *byte_bad_flags = push_array(arena, U64, (dim_1u64(range)+63)/64); + U64 *byte_changed_flags = push_array(arena, U64, (dim_1u64(range)+63)/64); //- rjf: iterate pages, fill output { U64 write_off = 0; for(U64 page_idx = 0; page_idx < page_count; page_idx += 1) { + // rjf: read data for this page String8 data = hs_data_from_hash(scope, page_hashes[page_idx]); Rng1U64 data_vaddr_range = r1u64(page_range.min + page_idx*page_size, page_range.min + page_idx*page_size+data.size); + + // rjf: skip/chop bytes which are irrelevant for the actual requested read String8 in_range_data = data; if(page_idx == page_count-1 && data_vaddr_range.max > range.max) { @@ -954,11 +953,42 @@ ctrl_query_cached_data_from_process_vaddr_range(Arena *arena, CTRL_MachineID mac { in_range_data = str8_skip(in_range_data, range.min-data_vaddr_range.min); } + + // rjf: write this chunk MemoryCopy((U8*)read_out+write_off, in_range_data.str, in_range_data.size); + + // rjf: if this page's hash & last_hash don't match, diff each byte & + // fill out changed flags + if(!u128_match(page_hashes[page_idx], page_last_hashes[page_idx])) + { + String8 last_data = hs_data_from_hash(scope, page_last_hashes[page_idx]); + String8 in_range_last_data = last_data; + if(page_idx == page_count-1 && data_vaddr_range.max > range.max) + { + in_range_last_data = str8_chop(in_range_last_data, data_vaddr_range.max-range.max); + } + if(page_idx == 0 && range.min > data_vaddr_range.min) + { + in_range_last_data = str8_skip(in_range_last_data, range.min-data_vaddr_range.min); + } + for(U64 idx = 0; idx < in_range_data.size; idx += 1) + { + U8 last_byte = idx < in_range_last_data.size ? in_range_last_data.str[idx] : 0; + U8 now_byte = idx < in_range_data.size ? in_range_data.str[idx] : 0; + if(last_byte != now_byte) + { + U64 idx_in_read_out = write_off+idx; + byte_changed_flags[idx_in_read_out/64] |= (1ull<<(idx_in_read_out%64)); + } + } + } + + // rjf: increment past this chunk write_off += in_range_data.size; if(data.size < page_size) { - write_off += page_size-data.size; + U64 missed_byte_count = page_size-data.size; + write_off += missed_byte_count; } } } @@ -966,6 +996,8 @@ ctrl_query_cached_data_from_process_vaddr_range(Arena *arena, CTRL_MachineID mac //- rjf: fill result result.data.str = (U8*)read_out; result.data.size = dim_1u64(range); + result.byte_bad_flags = byte_bad_flags; + result.byte_changed_flags = byte_changed_flags; hs_scope_close(scope); scratch_end(scratch); @@ -3121,7 +3153,9 @@ ctrl_mem_stream_thread__entry_point(void *p) //- rjf: take task B32 got_task = 0; - OS_MutexScopeR(process_stripe->rw_mutex) + U64 preexisting_memgen_idx = 0; + U128 preexisting_hash = {0}; + OS_MutexScopeW(process_stripe->rw_mutex) { for(CTRL_ProcessMemoryCacheNode *n = process_slot->first; n != 0; n = n->next) { @@ -3134,6 +3168,8 @@ ctrl_mem_stream_thread__entry_point(void *p) if(MemoryMatchStruct(&range_n->vaddr_range, &vaddr_range) && range_n->zero_terminated == zero_terminated) { got_task = !ins_atomic_u32_eval_cond_assign(&range_n->is_taken, 1, 0); + preexisting_memgen_idx = range_n->memgen_idx; + preexisting_hash = range_n->hash; goto take_task__break_all; } } @@ -3148,7 +3184,7 @@ ctrl_mem_stream_thread__entry_point(void *p) void *range_base = 0; U64 zero_terminated_size = 0; U64 memgen_idx = ctrl_memgen_idx(); - if(got_task) + if(got_task && memgen_idx != preexisting_memgen_idx) { range_size = dim_1u64(vaddr_range); U64 arena_size = AlignPow2(range_size + ARENA_HEADER_SIZE, KB(64)); diff --git a/src/ctrl/ctrl_core.h b/src/ctrl/ctrl_core.h index 2ec06297..52d1adf8 100644 --- a/src/ctrl/ctrl_core.h +++ b/src/ctrl/ctrl_core.h @@ -367,8 +367,8 @@ typedef struct CTRL_ProcessMemorySlice CTRL_ProcessMemorySlice; struct CTRL_ProcessMemorySlice { String8 data; - U64 *byte_good_flags; - B32 fresh; + U64 *byte_bad_flags; + U64 *byte_changed_flags; }; //////////////////////////////// diff --git a/src/df/gfx/df_gfx.c b/src/df/gfx/df_gfx.c index 8a559f2d..54ace1a9 100644 --- a/src/df/gfx/df_gfx.c +++ b/src/df/gfx/df_gfx.c @@ -3045,6 +3045,7 @@ df_window_update_and_render(Arena *arena, OS_EventList *events, DF_Window *ws, D } ui_labelf("Target Hz: %.2f", 1.f/df_dt()); ui_labelf("Ctrl Run Index: %I64u", ctrl_run_idx()); + ui_labelf("Ctrl Mem Gen Index: %I64u", ctrl_memgen_idx()); ui_labelf("Window %p", window); ui_set_next_pref_width(ui_children_sum(1)); ui_set_next_pref_height(ui_children_sum(1)); diff --git a/src/df/gfx/df_views.c b/src/df/gfx/df_views.c index dc66c9c6..78da164c 100644 --- a/src/df/gfx/df_views.c +++ b/src/df/gfx/df_views.c @@ -976,6 +976,27 @@ df_eval_watch_view_build(DF_Window *ws, DF_Panel *panel, DF_View *view, DF_EvalW B32 row_expanded = df_expand_key_is_set(&eval_view->expand_tree_table, row->key); DF_EvalHistoryCacheNode *history_cache_node = df_eval_history_cache_node_from_key(eval_view, row->key); + //- rjf: determine if row's data is fresh + B32 row_is_fresh = 0; + switch(row->eval.mode) + { + default:{}break; + case EVAL_EvalMode_Addr: + { + U64 size = tg_byte_size_from_graph_raddbg_key(parse_ctx.type_graph, parse_ctx.rdbg, row->eval.type_key); + Rng1U64 vaddr_rng = r1u64(row->eval.offset, row->eval.offset+size); + CTRL_ProcessMemorySlice slice = ctrl_query_cached_data_from_process_vaddr_range(scratch.arena, process->ctrl_machine_id, process->ctrl_handle, vaddr_rng); + for(U64 idx = 0; idx < (size+63)/64; idx += 1) + { + if(slice.byte_changed_flags[idx] != 0) + { + row_is_fresh = 1; + break; + } + } + }break; + } + //- rjf: store root edit commit info if(row_selected) { @@ -1032,7 +1053,11 @@ 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); + ui_set_next_flags(disabled_flags|(row_is_fresh*UI_BoxFlag_DrawOverlay)); + if(row_is_fresh) + { + ui_set_next_overlay_color(mul_4f32(df_rgba_from_theme_color(DF_ThemeColor_Highlight0), v4f32(1, 1, 1, 0.2f))); + } UI_NamedTableVectorF("row_%I64x", row_hash) { //- rjf: expression diff --git a/src/hash_store/hash_store.c b/src/hash_store/hash_store.c index 81b7d6a2..c80cd191 100644 --- a/src/hash_store/hash_store.c +++ b/src/hash_store/hash_store.c @@ -142,9 +142,9 @@ hs_submit_data(U128 key, Arena **data_arena, String8 data) } if(key_node) { - if(key_node->hash_history_gen+1 >= ArrayCount(key_node->hash_history)) + if(key_node->hash_history_gen >= ArrayCount(key_node->hash_history)) { - key_expired_hash = key_node->hash_history[(key_node->hash_history_gen-1)%ArrayCount(key_node->hash_history)]; + key_expired_hash = key_node->hash_history[key_node->hash_history_gen%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; diff --git a/src/scratch/ryan_scratch.c b/src/scratch/ryan_scratch.c index 0c2a5a40..265cda0c 100644 --- a/src/scratch/ryan_scratch.c +++ b/src/scratch/ryan_scratch.c @@ -1,17 +1,16 @@ // Copyright (c) 2024 Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) -int Foo(int x, int y) -{ - return x + y; -} - int main(void) { + int x = 0; + int y = 0; + int z = 0; + for(;;) { - int x = 23; - int y = 45; - Foo(x, y); + x += 1; + y += 1; + z += 1; } return 0; }