Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(perf): Integrate Revery layers for editor surface #2798

Open
wants to merge 33 commits into
base: master
Choose a base branch
from

Conversation

bryphe
Copy link
Member

@bryphe bryphe commented Dec 4, 2020

Today, Onivim renders like a video game - it renders the entire screen every time the state changes. Given that, it's actually amazing how performant it is, even with all this work.

Text rendering, in particular, is very expensive - and we're re-rendering all of the text, across all of the editors, every time anything changes - this is quite grossly inefficient. It also means, if one part of the UI is expensive to render, it can make every operation slower (like #1285 - a text layout inefficiency in rendering the explorer caused every. operation. to. be. slow).

revery-ui/revery#1005 adds a new primitive called a Layer. A Layer actually creates it's own surface for rendering, and only updates it when a condition is met. This is exactly what we need for the editor surface and other rich UI elements to avoid the expense of text rendering when nothing has changed. It's not perfect, it only impacts draw (not layout), but it turns out the draw is significantly more costly at the moment than layout, so it addresses the largest bottleneck.

The downside is that these surfaces require memory, so it's the trade-off of memory-to-runtime, but this trade-offs makes sense, as it can help facilitate a more responsive UI and avoid unnecessary rendering costs.

Another cost is the additional complexity of a re-render-condition - if this condition is not correct, there could be cases where we are not redrawing when we should (or, redrawing too aggressively). Usually, though, the condition can be simple - since these objects are immutable, a physical equality / reference check is generally sufficient.

This approach is similar to what web browsers do - except browsers do this implicitly, whereas we are adding an explicit primitive. Often developers will try and hint at the browser to promote a specific element to a layer (by using the CSS will-change or transform properties), for a smooth animation.

revery-ui/revery#1005 also adds some debug visualizations to show when layers are re-rendered (green means it is not being re-rendered, red means it is) - this can help troubleshoot cases where the render condition is not correct:

2020-12-04 08 29 02

TODO:

  • Fix diagnostics - they should trigger a re-render
  • Set proper background color for VimList layer
  • Fix crash in extensions pane (compare: functional value)
  • Fix theme changing - ensure changing theme triggers re-render
  • Fix scroll animation re-rendering in vimlist
  • Gate behind an experimental feature flag
  • Revery - Implement optimization - if a layer shrinks, it doesn't need to be recreated
  • Test moving between monitors in OSX

@bryphe bryphe added the WIP label Dec 4, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant