diff options
| author | blasty <peter@haxx.in> | 2026-08-07 03:05:33 +0200 |
|---|---|---|
| committer | blasty <peter@haxx.in> | 2026-08-07 03:05:33 +0200 |
| commit | 8e2cf13804e64c54d02aa4932ccb7ae1058edd2d (patch) | |
| tree | 4e4d5d93d231129e40d289dd5ab00d22f1c49da5 /idatui | |
| parent | Re-run of #16 (keep the joined search body across a cancelled search and acro... (diff) | |
| download | ida-tui-8e2cf13804e64c54d02aa4932ccb7ae1058edd2d.tar.gz ida-tui-8e2cf13804e64c54d02aa4932ccb7ae1058edd2d.tar.xz ida-tui-8e2cf13804e64c54d02aa4932ccb7ae1058edd2d.zip | |
Re-run of #18 (_CellRow slice assignment, one-string box borders, memoised Style sum), confirming it: 17590 -> 17501. lg_graph averages 951 over the two runs against 1136 before.
Result: {"status":"keep","total_ms":17501.4,"lg_boot_ms":711,"lg_decomp_ms":2484.8,"lg_graph_ms":1017.2,"lg_hex_ms":431.9,"lg_index_ms":98.7,"lg_listing_cold_ms":528,"lg_listing_warm_ms":409.2,"lg_nav_ms":6488.2,"lg_palette_ms":4.7,"lg_render_ms":214.8,"lg_search_ms":1473.5,"pure_graph_ms":244.3,"sm_boot_ms":451.4,"sm_decomp_ms":596,"sm_graph_ms":691.3,"sm_hex_ms":444.5,"sm_index_ms":0,"sm_listing_cold_ms":263,"sm_listing_warm_ms":284.2,"sm_nav_ms":374.7,"sm_palette_ms":0.3,"sm_render_ms":252.1,"sm_search_ms":37.5,"fails":0}
Diffstat (limited to 'idatui')
| -rw-r--r-- | idatui/app.py | 56 |
1 files changed, 42 insertions, 14 deletions
diff --git a/idatui/app.py b/idatui/app.py index 53dd79b..6c0a872 100644 --- a/idatui/app.py +++ b/idatui/app.py @@ -2161,6 +2161,13 @@ _GPAD = 1 # columns of padding inside a box _MINI_W, _MINI_H = 30, 14 +#: Memo for ``Style + Style``. Rich rebuilds a whole Style on every ``+``, and +#: the graph merges an overlay (cursor band, trail, highlight) over a run of +#: cells that share only a handful of base styles -- so the same pair is +#: recombined hundreds of times per frame. +_STYLE_SUM: dict[tuple, Style] = {} + + class _CellRow: """A row of (char, style) cells that coalesces into a Strip. @@ -2183,13 +2190,39 @@ class _CellRow: self.st[i] = style def text(self, i: int, s: str, style: Style) -> None: - for k, c in enumerate(s): - self.put(i + k, c, style) + """Write ``s`` at cell ``i``, clipped to the row. + + Slice assignment rather than a call per character: a graph row is drawn + from box borders, instruction text and the minimap, and doing it a cell + at a time made painting one frame thousands of bound-method calls. + Assigning a str to a list slice expands it to characters in C. + """ + if not s: + return + a = i if i > 0 else 0 + b = i + len(s) + if b > self.width: + b = self.width + if b <= a: + return + self.ch[a:b] = s[a - i:b - i] + self.st[a:b] = [style] * (b - a) def restyle(self, a: int, b: int, style: Style) -> None: """Merge ``style`` over the cells in [a, b) (keeps the characters).""" - for i in range(max(a, 0), min(b, self.width)): - self.st[i] = self.st[i] + style + if a < 0: + a = 0 + if b > self.width: + b = self.width + st = self.st + combine = _STYLE_SUM + for i in range(a, b): + base = st[i] + key = (base, style) + got = combine.get(key) + if got is None: + got = combine[key] = base + style + st[i] = got def strip(self) -> Strip: segs: list[Segment] = [] @@ -2796,10 +2829,8 @@ class GraphView(NavMixin, ScrollView, can_focus=True): label = f"loc_{n.block.start:X}" if n.block else "" if b is not None and b.rows and b.rows[0].name: label = b.rows[0].name - out.put(left, graph.BOX["tl"], bs) - for i in range(1, w - 1): - out.put(left + i, graph.BOX["h"], bs) - out.put(left + w - 1, graph.BOX["tr"], bs) + out.text(left, graph.BOX["tl"] + graph.BOX["h"] * (w - 2) + + graph.BOX["tr"], bs) tag = f" {label} " if len(tag) <= w - 4: st = _S_GENTRY if (self.fc and n.id == self.fc.entry) else ( @@ -2809,15 +2840,12 @@ class GraphView(NavMixin, ScrollView, can_focus=True): out.put(left + w - 2, "↺", _S_EDGE[graph.E_BACK]) return if row == n.y + n.h - 1: - out.put(left, graph.BOX["bl"], bs) - for i in range(1, w - 1): - out.put(left + i, graph.BOX["h"], bs) - out.put(left + w - 1, graph.BOX["br"], bs) + out.text(left, graph.BOX["bl"] + graph.BOX["h"] * (w - 2) + + graph.BOX["br"], bs) return out.put(left, graph.BOX["v"], bs) out.put(left + w - 1, graph.BOX["v"], bs) - for i in range(1, w - 1): - out.put(left + i, " ", _S_INSN) + out.text(left + 1, " " * (w - 2), _S_INSN) i = row - n.y - 1 rows = self._rows(n.id) if not (0 <= i < len(rows)): |
