feat(build): report collectMs/detectMs as separate phases#993
feat(build): report collectMs/detectMs as separate phases#993carlos-alm merged 4 commits intomainfrom
Conversation
Split collect and detect-change work out of setupMs in BuildResult.phases. These two phases have very different cost profiles (file-walk + ignore matching vs hash/mtime checks), and collapsing them hid where time was actually being spent during incremental-build perf investigations. - types.ts: add collectMs/detectMs to BuildResult.phases - context.ts: add collectMs/detectMs to ctx.timing - collect-files.ts, detect-changes.ts: wrap exported entries with performance.now() (try/finally so early returns still record timing) - pipeline.ts: formatTimingResult and formatNativeTimingResult surface the two fields separately instead of folding native-side values back into setupMs Rust PipelineTiming already tracks collect_ms and detect_ms, so no new instrumentation on the native side. docs check acknowledged — observability-only change, no README/CLAUDE/ ROADMAP impact. Impact: 6 functions changed, 7 affected
|
Claude finished @carlos-alm's task —— View job PR Review: feat(build): report collectMs/detectMs as separate phasesReviewing this PR according to the established review criteria. Progress:
Root Cause AnalysisProblem Being Solved: Issue #977 requests splitting Why This Approach: This is a legitimate observability improvement. The PR splits timing for two distinct operations:
Risk Assessment: Low risk - purely additive timing instrumentation with no behavioral changes. Code Quality Review ✓Implementation is solid: Timing instrumentation:
Type safety:
Consistency:
Testing:
Backlog Compliance
Final Recommendation
The PR correctly identifies that file collection and change detection are distinct performance bottlenecks worth measuring separately. The implementation properly instruments both JS and native code paths while maintaining backward compatibility. |
Greptile SummaryThis PR splits Confidence Score: 5/5Safe to merge — no correctness issues found; timing instrumentation is properly guarded with try/finally and the interface drift from the prior review is resolved. All findings are P2 or lower. The try/finally pattern is used correctly on all code paths (including early returns). The additive detectMs accumulation is intentional and well-documented. The PipelineContext.timing interface now accurately reflects the concrete class. Tests cover the new fields. No files require special attention. Important Files Changed
Sequence DiagramsequenceDiagram
participant P as pipeline.ts
participant C as collectFiles
participant D as detectChanges
participant T as ctx.timing
P->>C: collectFiles(ctx)
activate C
Note over C: start = performance.now()
C->>T: timing.collectMs = elapsed
alt scoped path
C->>T: timing.detectMs += ~0ms (assignments only)
end
deactivate C
P->>D: detectChanges(ctx)
activate D
Note over D: start = performance.now()
alt scoped path
D->>D: handleScopedBuild(ctx)
else incremental / full
D->>D: getChangedFiles / fullBuild logic
end
D->>T: timing.detectMs = (timing.detectMs ?? 0) + elapsed
deactivate D
P->>P: formatTimingResult(ctx)
Note over P: setupMs, collectMs, detectMs, parseMs…
Reviews (4): Last reviewed commit: "refactor(build): separate collectMs from..." | Re-trigger Greptile |
Codegraph Impact Analysis7 functions changed → 7 callers affected across 5 files
|
…ion (#993) Impact: 1 functions changed, 0 affected
|
@greptileai Thanks — addressed the PipelineContext timing interface drift in bf3c3d3. Replaced
|
Addresses Greptile P2 feedback on #993: - collectMs no longer includes change-detection work on the scoped-rebuild path. Only filesystem-walk work (existence checks + file list) is timed under collectMs; parseChanges/removed/isFullBuild assignments are timed under detectMs for semantic consistency with the non-scoped path. - detectChanges now accumulates detectMs additively to respect the partial contribution from collectFiles on the scoped path. - Pipeline test asserts collectMs and detectMs are >= 0, not just 'number', so a silent regression where timing is never recorded would be caught. Impact: 2 functions changed, 5 affected
|
Addressed Greptile's P2 feedback in 87ce95d:
Verified:
|
Summary
setupMsinBuildResult.phasesso incremental-build perf investigations can see the two phases separately (file-walk + ignore-matching vs hash/mtime checks).collectFilesanddetectChangeswithperformance.now()wrapped intry/finallyso early returns still record timing.collectMs/detectMsback intosetupMs— the RustPipelineTimingalready tracks them, so the formatter just surfaces them.Closes #977.
Files touched
src/types.ts— addscollectMs/detectMstoBuildResult.phasessrc/domain/graph/builder/context.ts— addscollectMs/detectMstoctx.timingsrc/domain/graph/builder/stages/collect-files.ts— wrapscollectFileswithperformance.now()src/domain/graph/builder/stages/detect-changes.ts— wrapsdetectChangeswithperformance.now()src/domain/graph/builder/pipeline.ts—formatTimingResultandformatNativeTimingResultsurface the two fieldstests/builder/pipeline.test.ts— asserts the new fieldsNo README/CLAUDE/ROADMAP updates — observability-only change.
Test plan
npx tsc --noEmitnpx vitest run tests/builder(14/14 pass)npx vitest run tests/integration/incremental-parity.test.ts(pass)