diff --git a/Makefile b/Makefile index 58140af..f84d2f2 100644 --- a/Makefile +++ b/Makefile @@ -39,4 +39,4 @@ noasan: $(ROOT_IFACE_DBG) build/imgui.o $(MOLD) $(CXX) -DDEBUG -g -O0 $(CFLAGS) -fsanitize=undefined $(INC) $(ROOTFLAGS) -o rntviewer src/rntviewer.cpp build/imgui.o $(ROOT_IFACE_DBG) $(LIBS) $(ROOTLIBS) r: $(ROOT_IFACE) build/imgui.o - $(MOLD) $(CXX) -O2 $(CFLAGS) $(INC) $(ROOTFLAGS) -o rntviewer src/rntviewer.cpp build/imgui.o $(ROOT_IFACE) $(LIBS) $(ROOTLIBS) + $(MOLD) $(CXX) -O2 -DNDEBUG $(CFLAGS) $(INC) $(ROOTFLAGS) -o rntviewer src/rntviewer.cpp build/imgui.o $(ROOT_IFACE) $(LIBS) $(ROOTLIBS) diff --git a/src/render.cpp b/src/render.cpp index 041a1ac..0c7ee97 100644 --- a/src/render.cpp +++ b/src/render.cpp @@ -61,6 +61,7 @@ u32 mem_edit_bg_color_fn(const u8 *, u64 off, void *user_data) // printf("%lu vs %lu\n", off, rdata.page_groups[rdata.n_page_groups - 1].range.end()); for (Page_Info_Chunk *chunk = rdata.page_chunks; chunk; chunk = chunk->next) { if (chunk->range.start <= off && off <= chunk->range.end()) { + printf("slow path for 0x%lX (last pinfo: 0x%lX - 0x%lX)\n", off, app->last_pinfo->range.start, app->last_pinfo->range.end()); for (u64 group_idx = chunk->first_group; group_idx < rdata.n_page_groups; ++group_idx) { const Page_Info_Group &group = rdata.page_groups[group_idx]; if (off < group.range.start || off > group.range.end()) @@ -74,6 +75,10 @@ u32 mem_edit_bg_color_fn(const u8 *, u64 off, void *user_data) } } } + + fprintf(stderr, "Offset 0x%lX is in chunk 0x%lX - 0x%lX, but found in no page_info range!\n", + off, chunk->range.start, chunk->range.end()); + assert(false); } } #undef COL @@ -166,6 +171,7 @@ void update_and_render(Arena *arena, App_State &app, f32 delta_time_ms) assert(app.vsettings.base_display_addr < app.inspected_file_size); void *content = app.inspected_fmem + app.vsettings.base_display_addr; u64 content_size = app.inspected_file_size - app.vsettings.base_display_addr; + app.last_pinfo = &invalid_pinfo; mem_edit.DrawContents(content, content_size, app.vsettings.base_display_addr); ImGui::TableNextColumn(); diff --git a/src/rntuple.cpp b/src/rntuple.cpp index e2798fa..a748fe0 100644 --- a/src/rntuple.cpp +++ b/src/rntuple.cpp @@ -77,9 +77,9 @@ void gather_metadata(Arena *arena, RMicroFileReader &reader, const RNTuple_File_ // for all clusters, gather page metadata for (const RClusterDescriptor &cluster_desc : descriptor.GetClusterIterable()) { - for (const auto &[col_id, col_range] : cluster_desc.GetColumnRangeIterable()) { + for (const RClusterDescriptor::RColumnRange &col_range : cluster_desc.GetColumnRangeIterable()) { // insert page infos sorted by byte range - const auto &page_range = cluster_desc.GetPageRange(col_id); + const auto &page_range = cluster_desc.GetPageRange(col_range.fPhysicalColumnId); for (const auto &page_info : page_range.fPageInfos) { Page_Info_Node *pinfo = arena_push(arena); pinfo->range.start = page_info.fLocator.GetPosition(); @@ -113,10 +113,12 @@ void gather_metadata(Arena *arena, RMicroFileReader &reader, const RNTuple_File_ fprintf(stderr, "Loaded %lu pages.\nGenerating groups...", n_pages); - // Create page groups. + // Create page groups and chunks. // Each page group is a grouping of GROUP_SIZE page infos whose range is equal to the combined ranges // of its components. It is an acceleration structure used to more quickly find the correct page info // that an offset belongs to. + // A page chunk is a grouping of adjacent page groups, used to quickly determine if an offset is part + // of a page or not. const u64 GROUP_SIZE = 100; Page_Info_Group *groups = arena_push_array_nozero(arena, n_pages / GROUP_SIZE + 1); Page_Info_Node *last = nullptr; @@ -125,39 +127,44 @@ void gather_metadata(Arena *arena, RMicroFileReader &reader, const RNTuple_File_ u64 n_groups = 0; u64 n_chunks = 0; for (Page_Info_Node *pinfo = pinfo_head; pinfo; pinfo = pinfo->next) { - if (idx++ % GROUP_SIZE == 0) { - Page_Info_Group &cur_group = groups[n_groups]; - cur_group.first = pinfo; - cur_group.range.start = pinfo->range.start; - if (n_groups > 1) { - Page_Info_Group &prev_group = groups[n_groups - 1]; - prev_group.range.len = cur_group.range.start - prev_group.range.start; - } - - assert((!chunks_head) ^ (n_groups > 0)); - - if (!chunks_head) { - assert(!chunks_tail); - chunks_head = chunks_tail = arena_push(arena); - chunks_head->range.start = cur_group.range.start; - ++n_chunks; - } else if (groups[n_groups - 1].range.end() != cur_group.range.start) { - // close current chunk - Page_Info_Group &prev_group = groups[n_groups - 1]; - chunks_tail->range.len = (prev_group.range.end() - chunks_tail->range.start); - // open new chunk - Page_Info_Chunk *chunk = arena_push(arena); - chunk->range.start = cur_group.range.start; - chunks_tail->next = chunk; - chunks_tail = chunk; - ++n_chunks; - } else { - chunks_tail->range.len += cur_group.range.len; - } - - ++n_groups; - } last = pinfo; + if (idx++ % GROUP_SIZE != 0) + continue; + + // Create a new group every GROUP_SIZE page infos + + Page_Info_Group &cur_group = groups[n_groups]; + cur_group.first = pinfo; + cur_group.range.start = pinfo->range.start; + if (n_groups > 1) { + Page_Info_Group &prev_group = groups[n_groups - 1]; + prev_group.range.len = cur_group.range.start - prev_group.range.start; + } + + assert((!chunks_head) == (n_groups == 0)); + + if (!chunks_head) { + assert(!chunks_tail); + chunks_head = chunks_tail = arena_push(arena); + chunks_head->range.start = cur_group.range.start; + chunks_head->first_group = n_groups; + ++n_chunks; + } else if (groups[n_groups - 1].range.end() != cur_group.range.start) { + // close current chunk + Page_Info_Group &prev_group = groups[n_groups - 1]; + chunks_tail->range.len = (prev_group.range.end() - chunks_tail->range.start); + // open new chunk + Page_Info_Chunk *chunk = arena_push(arena); + chunk->range.start = cur_group.range.start; + chunk->first_group = n_groups; + chunks_tail->next = chunk; + chunks_tail = chunk; + ++n_chunks; + } else { + chunks_tail->range.len += cur_group.range.len; + } + + ++n_groups; } if (last) groups[n_groups - 1].range.len = last->range.end() - groups[n_groups - 1].range.start; diff --git a/src/rntuple.h b/src/rntuple.h index 7f128ff..46b2b44 100644 --- a/src/rntuple.h +++ b/src/rntuple.h @@ -12,7 +12,7 @@ struct Page_Info_Node { u64 n_elems; }; -inline const Page_Info_Node invalid_pinfo = { nullptr, 0, 0 }; +static const Page_Info_Node invalid_pinfo {}; struct Page_Info_Group { Byte_Range range; diff --git a/src/rntviewer.cpp b/src/rntviewer.cpp index be4f819..d34c396 100644 --- a/src/rntviewer.cpp +++ b/src/rntviewer.cpp @@ -121,7 +121,6 @@ int main(int argc, char **argv) app.ntpl_name = ntpl_name; app.rndata = get_rntuple_data(arena, fname, ntpl_name); app.vsettings = make_viewer_settings(); - app.last_pinfo = &invalid_pinfo; // Start main loop run_main_loop(window, arena, app);