Redraw only the spinner when nothing else has changed - #5571
Conversation
88c40e0 to
84a9210
Compare
84a9210 to
7270d5a
Compare
|
Went in a rabbit hole so it'll take some time to wrap up a working solution, my original approach introduced a bug where the full redraw event could be lost while the spinner was shown. I'll let you know when I am done! |
7270d5a to
050ff91
Compare
|
Alright so the problem was that some processes that update the layout do not themselves request a redraw and assumed it would be done through the ticker loop, adding a single full redraw after the ticker has completed (aka whatever job it was doing is done) fixed my issue. |
stefanhaller
left a comment
There was a problem hiding this comment.
Great work!
This only fixes it for the bottom line status view; there's also the inline status that is used e.g. for fast-forwarding a branch, would be nice if this could be improved too. The code is in InlineStatusHelper.renderContext; it seems safe to call OnUIThreadContentOnly there, too. When I quickly tested it though, it didn't make as much of a difference as I would have expected, so maybe there's something else going on in that case. (Found it: it ends up calling Gui.render further down the call chain which undoes the optimization.) I'd be ok with solving this in a followup.
One quirk: if a user sets their gui.spinner.frames to a bunch of strings of unequal lengths, this used to push the rest of the status line over as necessary with every frame, and now it no longer does because we skip the layout. We could ignore this since it's unlikely that users do this, but we could also not let them; I pushed a commit (8a7e1fe) that rejects configs that try this.
8a7e1fe to
47c0e94
Compare
47c0e94 to
b0b690b
Compare
|
Also, were you planning on looking into the WithWaitingStatusSync issue? (either as part of this PR, or as a followup) |
f1d70cf to
6b846f7
Compare
|
I have now added it to sync events too, this one takes the views as parameters otherwise some of the UI would update before the task is actually done. For example if moving a commit down, the UI would show the commit moved down at the same time as the spinner starts to spin, but the highlight and control would only be given back to the user when truly done. I added a commit which should probably be another PR, let me know if that's the case and I will happily do so. |
Ah, good, but that's actually not what I meant. I mistyped in my last comment, I meant WithInlineStatus, not WithWaitingStatusSync, sorry. The WithInlineStatus change needs to happen in Also, for this change the commit structure doesn't work. You can't make an API-breaking change in one commit and then adapt callers in a later commit. In this case I'd suggest to leave the commits as you had them before (59766d3 and e9a4650), and then add a new commit after that for changing
But it called Layout with every redraw, so it should still make a difference.
That's fine, happy to include that here. |
|
Ah that makes more sense, might as well make the changes in this PR for the in-line spinner. |
6b846f7 to
b3f6e49
Compare
|
I took a conservative approach with the in-line spinner, I did not want to change the PS: Thank you for taking the time with the code reviews, it is very much appreciated :) |
1c88afa to
0a3ab7e
Compare
0a3ab7e to
22f542e
Compare
I don't think it's so bad to extend Context; it has only two implementations really, SimpleContext and ListContextTrait. I pushed dfc3593 that adds I'm still not super happy with it, because there's an asymmetry: HandleRender takes care of calling Apart from that, I pushed two more trivial fixups. Now the only remaining problem is that the commit "Support to request a content-only UI refresh" still doesn't compile. |
|
Wait, none of this HandleContentOnlyRender stuff makes any sense; I didn't think. Currently the only difference between HandleRender and HandleContentOnlyRender is that the former calls Gui.render. We should totally move this out to the call sites (many of which don't actually need it even, as far as I can see), then we don't need two different methods on Context. Since this is a bigger change and requires careful examination of each call site, I suggest we do this in a followup and simply drop the inline status commit (and my fixups) from this branch. |
efcd664 to
8b69e1e
Compare
|
Done, I also ensured all commits can be built and tests pass for each. |
stefanhaller
left a comment
There was a problem hiding this comment.
Looks good, thanks. There's one more little style thing that I pushed a fixup for, but I'm happy with this state now.
I will open another PR to discuss the in-line changes.
I'm not really sure this will save me time. Reviewing such a PR will probably take as much time as making the change myself, so I think I'd prefer to do that in this case.
|
For some reason Github swallowed my inline comment for why I made that last fixup. I'm too lazy to type that again, let me know if you want to discuss any of that. |
This didn't cause a bug so far because switching repos always happens from within an OnWaitingStatus, so the spinner would take care of calling layout and draw. However, later in this branch we are going to optimize the spinner so that it no longer calls layout, at which point this would break, so make sure we rerender at the point where it's needed.
This skips the whole-UI layout calculations, and lets tcell's dirty cell handling redraw only changed cells.
The spinner looks weird if they don't. While we're at it, validate that frames must not be empty, which would have crashed with a division by zero.
47477a4 to
706f1d0
Compare
Sounds good!
I can see how making the argument explicit have benefits and is less ambiguous to callers, all good. |
Instead of redrawing the two views on each tick, only redraw the spinner
706f1d0 to
b7edcba
Compare
|
@AntoineGS Here's the followup-PR for the inline spinner: #5592. Code review would be appreciated, but especially testing; I feel this is a bit of a risky change, there might be redraw glitches where a layout is missing now. |
As a followup to #5571, improve performance for inline spinners too. This requires a bit of preparation; in particular, we change ListContextTrait.HandleRender to no longer force a UI layout/redraw, so callers need to take care of this themselves where needed. This requires careful testing to see that we didn't miss any situation where redrawing only worked by accident; see the first commit of the branch for an example.
lazygit 0.62.0 Created-by: HarmonybrewBot Commit-by: HarmonybrewBot Merged-by: HarmonybrewBot Description: Created by `brew bump` --- Created with `brew bump-formula-pr`.<details> <summary>release notes</summary> <pre>The big change in this release is what I have been referring to as the "keybinding revamp": it allows you to use richer keybindings than the few that were available before; see [Custom_Keybindings.md](https://github.com/jesseduffield/lazygit/blob/master/docs/keybindings/Custom_Keybindings.md) for details. It also describes a new keybinding syntax that is a bit more intuitive than the previous `<c-x>` notation (but the old one is still supported for backwards compatibility). Note the section about Terminal compatibility in that document; not all terminals support the new protocol equally well, so it may be a good idea to switch to one that does. Breaking change: The default keybinding for submitting a commit from the commit description editor has changed from alt-enter to command-enter on Mac, or ctrl-enter on Linux and Windows; these are the same bindings that are used in many multi-line edit field situations, e.g. in GitHub comments. Unfortunately these are not supported by all terminals; see the above-mentioned [terminal compatibility](https://github.com/jesseduffield/lazygit/blob/master/docs/keybindings/Custom_Keybindings.md#terminal-compatibility) for more on that. If you want to revert this change, you can do so by adding the following to your config: ```yml keybinding: universal: confirmInEditor: [<alt+enter>, <ctrl+s>] ``` The complete list of changes follows: <!-- Release notes generated using configuration in .github/release.yml at v0.62.0 --> ## What's Changed ### Enhancements 🔥 * Retry on ref lock errors during fetch/pull by @majiayu000 in jesseduffield/lazygit#5161 * Preserve whitespace when remembering commit message by @stefanhaller in jesseduffield/lazygit#5528 * Define PR colors as hex colors to make them the same as GitHub's by @stefanhaller in jesseduffield/lazygit#5480 * Revamp keybinding mechanism to support richer keybindings (e.g. `ctrl-alt-shift-x `) by @stefanhaller in jesseduffield/lazygit#5563 * Platform-specific edit bindings for move-by-word and backspace-word by @stefanhaller in jesseduffield/lazygit#5564 * Change canonical keybinding syntax (`<ctrl+a>` instead of `<c-a>`) by @stefanhaller in jesseduffield/lazygit#5565 * Use more widely-supported Unicode symbols for the commit graph by @stefanhaller in jesseduffield/lazygit#5573 * Show push URLs for remotes that have any by @stefanhaller in jesseduffield/lazygit#5576 * Support GitHub Enterprise for the Pull Requests feature by @stefanhaller in jesseduffield/lazygit#5596 * Allow keybindings to configure more than one key by @stefanhaller in jesseduffield/lazygit#5634 * Add `<alt+up>`/`<alt+down>` as alternate keybindings for moving commits up/down by @stefanhaller in jesseduffield/lazygit#5637 * Add support for git flow using the git-flow-next tool by @hmaddocks in jesseduffield/lazygit#5288 ### Fixes 🔧 * Fix copying a file's absolute path when running in a linked worktree by @stefanhaller in jesseduffield/lazygit#5523 * Preserve commit message when quitting while the commit message panel is open by @stefanhaller in jesseduffield/lazygit#5524 * Stop showing cached PRs when we no longer have a base remote by @stefanhaller in jesseduffield/lazygit#5543 * If multiple remotes exist but only one is a Github remote, pick it without prompting by @stefanhaller in jesseduffield/lazygit#5544 * Fix cherry-picking a range selection of commits by @stefanhaller in jesseduffield/lazygit#5599 * Dont log GitHub PR fetching errors to the Command log by @stefanhaller in jesseduffield/lazygit#5600 * Avoid auto-forwarding main branches checked out in other worktrees by @stefanhaller in jesseduffield/lazygit#5621 * Fix cycling pagers when main view is focused by @stefanhaller in jesseduffield/lazygit#5639 ### Maintenance ⚙️ * Bump samber.lo to latest version by @stefanhaller in jesseduffield/lazygit#5545 * Bump github.com/kyokomi/emoji/v2 from 2.2.8 to 2.2.13 by @dependabot[bot] in jesseduffield/lazygit#5481 * Bump github.com/gookit/color from 1.4.2 to 1.6.0 by @dependabot[bot] in jesseduffield/lazygit#5482 * Bump github.com/sirupsen/logrus from 1.9.3 to 1.9.4 by @dependabot[bot] in jesseduffield/lazygit#5483 * Bump dario.cat/mergo from 1.0.1 to 1.0.2 by @dependabot[bot] in jesseduffield/lazygit#5484 * Bump peter-evans/create-pull-request from 8.1.0 to 8.1.1 by @dependabot[bot] in jesseduffield/lazygit#5514 * Bump goreleaser/goreleaser-action from 7.0.0 to 7.1.0 by @dependabot[bot] in jesseduffield/lazygit#5529 * Bump actions/github-script from 8 to 9 by @dependabot[bot] in jesseduffield/lazygit#5515 * Bump golang.org/x/sys from 0.42.0 to 0.43.0 by @dependabot[bot] in jesseduffield/lazygit#5548 * Copy gocui into lazygit repo by @stefanhaller in jesseduffield/lazygit#5561 * Update to tcell v3 by @stefanhaller in jesseduffield/lazygit#5562 * Clear LC_* env vars when running LANG tests by @AntoineGS in jesseduffield/lazygit#5568 * Fix failing windows tests by @stefanhaller in jesseduffield/lazygit#5574 * Fix new gopls linter warnings by @stefanhaller in jesseduffield/lazygit#5580 * Disable gh telemetry when running integration tests by @stefanhaller in jesseduffield/lazygit#5587 * Fix the check_for_fixups.sh script again by @stefanhaller in jesseduffield/lazygit#5590 * Add script to preview release notes by @stefanhaller in jesseduffield/lazygit#5620 * Bump github.com/gookit/color from 1.6.0 to 1.6.1 by @dependabot[bot] in jesseduffield/lazygit#5586 * Bump github.com/sahilm/fuzzy from 0.1.1 to 0.1.2 by @dependabot[bot] in jesseduffield/lazygit#5606 * Bump golang.org/x/sys from 0.43.0 to 0.45.0 by @dependabot[bot] in jesseduffield/lazygit#5607 * Bump github.com/gdamore/tcell/v3 from 3.3.0 to 3.4.0 by @dependabot[bot] in jesseduffield/lazygit#5618 * Bump goreleaser/goreleaser-action from 7.1.0 to 7.2.2 by @dependabot[bot] in jesseduffield/lazygit#5619 ### Docs 📖 * Fix undo shortcut in Undoing.md by @stefanhaller in jesseduffield/lazygit#5640 * Update docs and schema for release by @stefanhaller in jesseduffield/lazygit#5645 ### I18n 🌎 * Update translations from Crowdin by @stefanhaller in jesseduffield/lazygit#5644 ### Performance Improvements 📊 * Improve performance of showDivergenceFromBaseBranch by @AntoineGS in jesseduffield/lazygit#5536 * Redraw only the spinner when nothing else has changed by @AntoineGS in jesseduffield/lazygit#5571 * Improve inline spinner performance by @stefanhaller in jesseduffield/lazygit#5592 ## New Contributors * @majiayu000 made their first contribution in jesseduffield/lazygit#5161 * @AntoineGS made their first contribution in jesseduffield/lazygit#5536 * @hmaddocks made their first contribution in jesseduffield/lazygit#5288 **Full Changelog**: jesseduffield/lazygit@v0.61.1...v0.62.0 </pre> <p>View the full release notes at <a href="https://github.com/jesseduffield/lazygit/releases/tag/v0.62.0">https://github.com/jesseduffield/lazygit/releases/tag/v0.62.0</a>.</p> </details> <hr> See merge request: Harmonybrew/homebrew-core!8880
PR Description
This fixes #4734, where lazygit would use a lot of CPU when the spinner was shown due to redrawing the entire screen every time the spinner needed a redraw.
The change adds the ability to request a UI redraw without invalidating the full UI, thus only redrawing the spinner, re-routing the spinner to this new flow.
CPU usage on a chromebook went from 60% to 5% when the spinner is shown.
Changing the refresh rate of the spinner from 50ms to 200ms brings it down from 5% to 1% if ever we would like to change the default, personally I prefer the slower moving spinner, but that's subjective.
Please check if the PR fulfills these requirements
go generate ./...)