aboutsummaryrefslogtreecommitdiffstats
path: root/.auto/prompt.md
diff options
context:
space:
mode:
authoruser <user@clank>2026-08-07 01:55:31 +0200
committeruser <user@clank>2026-08-07 01:55:31 +0200
commitcf45e115bcd137020002e84b67da7b00547901b5 (patch)
tree3954101322a281db2c2a739d647331fc33414be1 /.auto/prompt.md
parent_idatui_spans: one capturing re.split over the tag pairs instead of finditer+... (diff)
downloadida-tui-cf45e115bcd137020002e84b67da7b00547901b5.tar.gz
ida-tui-cf45e115bcd137020002e84b67da7b00547901b5.tar.xz
ida-tui-cf45e115bcd137020002e84b67da7b00547901b5.zip
Re-apply #5 (lru_cache on the per-line render + Heads built with their opcode bytes already attached) with the graph_minimap scenario's racy SETUP made deterministic: clear _graph_sticky before the second navigation so Space is known to be entering the graph, not leaving it. No assertion changed.
Result: {"status":"keep","total_ms":22980.2,"lg_boot_ms":738.2,"lg_decomp_ms":2401.8,"lg_graph_ms":944.1,"lg_hex_ms":920.6,"lg_index_ms":75.2,"lg_listing_cold_ms":538.5,"lg_listing_warm_ms":411.1,"lg_nav_ms":6813.9,"lg_palette_ms":4.9,"lg_render_ms":221.8,"lg_search_ms":5630.1,"pure_graph_ms":240.7,"sm_boot_ms":537.5,"sm_decomp_ms":595.1,"sm_graph_ms":715.7,"sm_hex_ms":858.8,"sm_index_ms":0,"sm_listing_cold_ms":263.3,"sm_listing_warm_ms":265.3,"sm_nav_ms":335.2,"sm_palette_ms":0.3,"sm_render_ms":271.4,"sm_search_ms":196.5,"fails":0}
Diffstat (limited to '.auto/prompt.md')
-rw-r--r--.auto/prompt.md48
1 files changed, 44 insertions, 4 deletions
diff --git a/.auto/prompt.md b/.auto/prompt.md
index 39126b9..a2ced97 100644
--- a/.auto/prompt.md
+++ b/.auto/prompt.md
@@ -72,7 +72,16 @@ expected payoff:
## Off Limits
- `tests/**` — the correctness gate. Do not weaken, skip, shorten or "fix" a
- test to make a change pass. If a test fails, the change is wrong.
+ test to make a change pass. If a test fails, **assume the change is wrong**.
+
+ One narrow exception, and it costs you a proof: a scenario whose *setup* is
+ racy, where the speedup merely decides which of two async loads lands first.
+ Before touching it you must (a) bisect to show which change flips it, (b)
+ reproduce the race outside the suite, showing the app reaching two different
+ states from the same steps, and (c) show the repaired scenario passing on
+ BOTH the fast and the slow code. Only the setup may change — every `c.check`
+ stays exactly as it was — and the ASI must record all three proofs. Done once
+ so far, for `graph_minimap` (experiment #6).
- `.auto/bench.py` may only be changed to add *more* signal (extra metrics,
extra NOTES). Never to do less work, shorten a sweep, drop a phase, loosen a
wait, or pick easier functions. If you change what it measures, say so in the
@@ -96,7 +105,38 @@ expected payoff:
## What's Been Tried
-(baseline only — fill this in as experiments accumulate)
+Baseline: `total_ms` ≈ 46 600. `lg_nav_ms` ≈ 29 000 (62% of it), of which a
+single cold jump to a high address was ≈ 28 200.
+
+**Wins**
+
+1. *(#3, −42%)* **ida-pro-mcp installs a `sys.setprofile` hook around every tool
+ call.** Its deadline mechanism profiles every python call/return so a
+ pure-python tool body can be interrupted — a 3.3× tax on a backend whose
+ tools are call-heavy (`heads`: 92 → 28 µs/row without it). `worker.py` now
+ sets `IDA_MCP_TOOL_TIMEOUT_SEC=0` and arms the deadline itself with one
+ polling watchdog thread + `ida_kernwin.set_cancelled()` — the half that
+ actually frees the IDA main thread.
+2. *(#4, −3%)* **`_idatui_spans` via one capturing `re.split`**, and whitespace
+ collapsed with `" ".join(txt.split())` rather than `re.sub`. 13.2 → 11.1
+ µs/line.
+3. *(#6)* **`lru_cache` on the per-line render** (`_idatui_line_parts`) plus
+ building `Head`s with their opcode bytes already attached.
+
+**Dead ends / things not to re-try**
+
+- `re.finditer` per tag in the span walker is *slower* than a plain character
+ loop (14.4 vs 13.2 µs/line): Match objects cost more than the ~54 trivial
+ iterations they replace.
+- `ListingModel.PAGE` (500 / 1000 / 2000) makes no measurable difference —
+ the cost is per row, not per round trip. Don't tune it.
+- `re.sub` for the whitespace collapse costs ~1 µs per call at ~6.5 calls/line.
+
+**Measurement traps**
-- Baseline: `total_ms` ≈ 46 000. `lg_nav_ms` ≈ 28 600 (62% of it), of which a
- single cold jump to a high address is ≈ 27 800.
+- `cProfile` massively distorts this code (it is call-heavy): it reported
+ `_idatui_spans` at 68% of the `heads` tool when the real share was ~10%.
+ A/B with `time.perf_counter` in one process instead.
+- Anything that walks the listing twice in one process is measuring a warm
+ `_idatui_line_parts` cache the second time. Run cold cases first, or in
+ separate processes.