fix(profiler): honour top_n in profiler-commit-query by_index - #667
Open
filip131311 wants to merge 1 commit into
Open
fix(profiler): honour top_n in profiler-commit-query by_index#667filip131311 wants to merge 1 commit into
filip131311 wants to merge 1 commit into
Conversation
by_index never received top_n — the renderer had no such parameter and the dispatch passed only (commits, commit_index) — so an explicit top_n: 8 returned all 306 fibers, ~20k characters. react-profiler-analyze points at this mode for drilling into a slow commit, so it is both the most likely call and the most likely to blow an agent's context. top_n is now threaded and applied, and the response says what it did: the heading stops claiming Full Detail, the header keeps the true fiber total alongside the shown count, and a footer names the hidden count. It is applied only when explicitly passed. Giving by_index the schema's default of 20 looked reasonable and is a trap: these rows are fibers, not components, and they collapse hard. On a real commit of 306 fibers, top_n=20 covers 10 distinct components while the analyze report that recommends this mode already shows up to 15 — the escape hatch would have returned less than the report it escapes from, silently. So top_n is now optional, with the two modes that genuinely defaulted to 20 keeping that default explicitly at their call sites. Because that collapse is invisible from a row count, the footer states it: 'the full set covers 70 distinct components and this view covers 3'. The root-cause chain keeps scanning the full commit rather than the truncated table. The fiber carrying the root cause is typically cheap — it triggers the cascade rather than doing the work — so it falls outside any top_n, and reading the sliced list would drop the most useful line in the output. Also fixes the analyze report's own suggestion, which said 'Use profiler-commit-query mode=by_index to see all' without passing commit_index, sending agents to a different commit than the one being described.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #630.
The bug
by_indexnever receivedtop_n:renderByIndexhad no such parameter and the dispatch passed only(commits, commit_index). Reproduced against the released 0.18.1 CLI on a real session —top_n: 8returned 306 rows / 20,245 characters.It matters because
react-profiler-analyzepoints at this exact mode for drilling into a slow commit, so it is both the most likely call and the most likely to blow an agent's context.Correction to the issue (and to my own first pass)
The issue says "the other three modes honour
top_ncorrectly". That's not right —cascade_treeignores it too (renderCascadeTreetakes notopN; its dispatch also passes two arguments). Onlyby_componentandby_time_rangeslice.I've deliberately not fixed
cascade_treehere, and not for the reason that first looked right. A DFS-prefix budget would in fact be structurally safe there. The real problems are that its roots come from aSetin insertion order with no subtree-cost aggregation, so any cut keeps an arbitrary subtree rather than the expensive one — making it useful needs a cost-ranking pass, which is design work, not a slice. And it dedups byname:depth, so it never had the 306-row blow-up that motivated this issue. Filed separately with the other findings.Why
top_nis honoured only when explicitly passedApplying the schema's existing default of 20 looks obviously right and is a trap. These rows are fibers, not components, and they collapse hard. Measured on the real commit:
The analyze report that recommends this mode already shows up to 15 distinct components (
MAX_COMPONENT_ENTRIES). So a default of 20 would make the escape hatch return strictly less than the report it escapes from — silently, since the footer would only say "298 hidden", not "you learned nothing new".top_nis therefore.optional(), and the two modes that genuinely defaulted to 20 keep it explicitly at their call sites (params.top_n ?? 20), so their behaviour is byte-identical.Since that collapse is invisible from a row count, the footer states it outright:
The trap this had to avoid
The root-cause chain block scans the full commit, not the truncated table. The fiber carrying the root cause is typically cheap — it triggers the cascade rather than doing the work — so it falls outside any
top_n. Slicing before that lookup would silently drop the single most useful line in the output. There's a regression test that pins exactly this: the only fiber with arootCauseParentis the cheapest,top_n=5, and the chain must still be printed.Also fixed
The analyze report suggested
`profiler-commit-query mode=by_index` to see allwithout passingcommit_index— an agent following it verbatim queries a different commit than the one being described. Now names the commit.Note I did not change it to name a
top_nvalue:totalComponentCountcounts distinct component names, whileby_indexemits one row per fiber, so passing it would still truncate — a subtler falsehood inside the line being corrected. With no default cap, "to see all" is simply true again.Verified live
by_index top_n=8Top Fibers,**Fibers:** 306 (showing 8)by_index(no top_n)Full Detail, no noticeby_componentChecks
renderByIndexwasn't exported, so those failures are import errors, not behavioural. The real before/after is the live table above, captured against the released 0.18.1 build.description:untouched); prettier, eslint, both typechecks clean; lock untouched.renderByIndexonly — no overlap with PR fix(profiler): accept the component names the analyze report actually prints #663, which ownsrenderByComponentin the same file.