diff options
| author | user <user@clank> | 2026-08-07 03:28:55 +0200 |
|---|---|---|
| committer | user <user@clank> | 2026-08-07 03:28:55 +0200 |
| commit | 98b3b98eb1bf8f195ef4ebb1375c9f161d758c17 (patch) | |
| tree | 810ec6ef2e88453a9fc076216dbc8a9b7e797a45 /idatui/app.py | |
| parent | Baseline for the v5 bench (landing polls every 2ms instead of 10ms; the poll ... (diff) | |
| download | ida-tui-98b3b98eb1bf8f195ef4ebb1375c9f161d758c17.tar.gz ida-tui-98b3b98eb1bf8f195ef4ebb1375c9f161d758c17.tar.xz ida-tui-98b3b98eb1bf8f195ef4ebb1375c9f161d758c17.zip | |
Three targeted cuts: the graph's transposition pass counts keep and swap in one pass over the neighbour pairs (was four _pair_cross calls); the barycentre median answers degree 1 and 2 without sorting; and the search body is built from windowed model reads instead of one locked row lookup per line.
Result: {"status":"keep","total_ms":17944.4,"lg_boot_ms":703.7,"lg_decomp_ms":2453.7,"lg_graph_ms":1000,"lg_hex_ms":478,"lg_index_ms":96,"lg_listing_cold_ms":453,"lg_listing_warm_ms":411.2,"lg_nav_ms":6555.9,"lg_palette_ms":4.9,"lg_render_ms":218.4,"lg_search_ms":1308.8,"pure_graph_ms":212.3,"sm_boot_ms":432.4,"sm_decomp_ms":1267.8,"sm_graph_ms":742.7,"sm_hex_ms":440,"sm_index_ms":2.5,"sm_listing_cold_ms":264.3,"sm_listing_warm_ms":289.5,"sm_nav_ms":305.4,"sm_palette_ms":0.3,"sm_render_ms":258.6,"sm_search_ms":45,"fails":0}
Diffstat (limited to 'idatui/app.py')
| -rw-r--r-- | idatui/app.py | 41 |
1 files changed, 34 insertions, 7 deletions
diff --git a/idatui/app.py b/idatui/app.py index 6c0a872..c37846f 100644 --- a/idatui/app.py +++ b/idatui/app.py @@ -690,15 +690,21 @@ class SearchMixin: key = (count, src) if self._hay_key == key: return self._hay - text_of = self._search_line_text starts: list[int] = [] parts: list[str] = [] pos = 0 - for i in range(count): - s = text_of(i) or "" + chunk = 4096 + for base in range(0, count, chunk): + for s in self._search_line_texts(base, min(chunk, count - base)): + if not s: + s = "" + starts.append(pos) + parts.append(s) + pos += len(s) + 1 + while len(starts) < count: # a short window: keep the indices lined up starts.append(pos) - parts.append(s) - pos += len(s) + 1 + parts.append("") + pos += 1 blob = "\n".join(parts) folded = blob.lower() hay = None if len(folded) != len(blob) else (starts, blob, folded) @@ -713,6 +719,12 @@ class SearchMixin: def _search_line_text(self, i: int) -> str | None: raise NotImplementedError + def _search_line_texts(self, start: int, count: int) -> list: + """``count`` line texts from ``start``. Overridable so a view whose rows + come from a locked model can fetch a window in one go.""" + text_of = self._search_line_text + return [text_of(i) for i in range(start, start + count)] + def _search_ensure(self, done) -> None: """Ensure all line texts are available, then call ``done()`` on the UI thread. Default: assume ready.""" @@ -1031,8 +1043,7 @@ class ListingView(SearchMixin, NavMixin, ColumnCursor, ScrollView, can_focus=Tru return "" return self._op_bytes_text(h).ljust(self._op_w) + " " - def _line_plain(self, idx: int) -> str | None: - h = self._head(idx) + def _plain_of(self, h: Head | None) -> str | None: if h is None: return None # Function headers and code labels sit at depth 0 (with the address); @@ -1045,6 +1056,22 @@ class ListingView(SearchMixin, NavMixin, ColumnCursor, ScrollView, can_focus=Tru extra = _LST_INDENT if h.kind == "member" else "" return base + self._op_field(h) + extra + self._name_prefix(h) + h.text + def _line_plain(self, idx: int) -> str | None: + return self._plain_of(self._head(idx)) + + def _search_line_texts(self, start: int, count: int) -> list: + """A window of plain lines in one model call. + + Building the search body row by row took the model's lock and bisected + its row table a quarter of a million times; ``window`` does both once + for the whole window. + """ + model = self.model + if model is None: + return [] + plain = self._plain_of + return [plain(h) for h in model.window(start, count)] + def _insn_col(self, idx: int) -> int: """Column where the instruction/content text begins, past the address + opcode-bytes gutter — the shift+home target. Mirrors ``_line_plain``'s |
