fix: Suppress VGitSync during staging; 95%+ performance improvement #425
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.
Builds on top of #422 and #423.
Description
Fixes performance degradation during staging operations by suppressing redundant VGitSync broadcasts. Achieves 99.6% reduction in buffer refresh calls (1,380 -> 6 LiveGutter:fetch calls) and 95% reduction in total git operations (10,421 -> 564 calls across 41 staging operations).
When staging hunks, every git index change triggered a cascade: filesystem watcher detects change -> VGitSync event fires -> git_buffer_store.for_each() iterates all tracked buffers -> each buffer runs LiveGutter:fetch() -> GitBuffer:diff() -> 3-4 git commands per buffer. With 15 tracked buffers, this meant 15x unnecessary buffer refreshes per stage operation, resulting in thousands of redundant git command calls.
This adds suppress_sync_and_refresh(buffer, ms) API to git_buffer_store that temporarily suppresses VGitSync broadcasts and refreshes only the specified buffer after a delay. Applied to all DiffScreen staging methods (stage_hunk, unstage_hunk, reset_hunk, stage, unstage, reset) and Hunks buffer operations (stage_all, cursor_stage).
Note: External git operations during the suppression window (~200ms) won't trigger a refresh until the next VGitSync event — an acceptable tradeoff given the short window.
Tested with 15 tracked buffers over 41 staging operations. No functional regressions observed - all git operations complete successfully, gutter signs update correctly, and UI remains responsive.
Performance Summary
Improvement:
Profiling Details
Environment: 15 tracked buffers, ~40 stage operations (DiffScreen:stage_hunk)
Before:
After: