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

Aggregate updates from low-latency plugins to avoid flashes of unstyled content #267

Closed
4 tasks
trishume opened this issue May 7, 2017 · 0 comments
Closed
4 tasks

Comments

@trishume
Copy link
Collaborator

trishume commented May 7, 2017

One problem with the current asynchronous plugin model is that it can send O(number_of_plugins) updates to the front-end for every character typed.

One possibility is to aggregate them in the front-end until the next draw-cycle, but that can still be glitchy if the first update comes in right-before a redraw and the highlighted text comes after. This will still lead to a "flash of unstyled content" to use web terminology. The problem is that I prefer an occasional extra 16ms of latency over the wrong thing being drawn and then 16ms later flashing to the correct thing, it looks bad.

One way to fix this is to introduce the concept of "low-latency" plugins that always either send an update in response to an edit, or acknowledge it without doing anything. Then the core can wait for all low-latency plugins to acknowledge or 10ms to pass before sending the update to the front-end.

Then say the syntax highlighting plugin can send updates to highlight the next 100 lines and then acknowledge, and proceed with any more lines it has to highlight.

  • Wait for multi-plugin support
  • Add the concept of a "low-latency" plugin
  • Add the concept of an "acknowledgement". This is necessary so things like the bracket-matcher which don't always send updates don't always cause it to time out, and so that the syntax highlighter can send updates for the rest of the viewport before acknowledging.
  • Delay sending an update to the front-end until all "low-latency" plugins have acknowledged, 10ms passes from the user edit, or possibly also when another user edit comes in.

This could still in principle show unstyled content for an unlucky fast typist if they hit another key between the first key and the first key being styled, the second key will be sent out unstyled. But it's still much better, and that case should be rare, especially if the syntax highlighting plugin immediately gives up on any previous jobs upon receiving a new one.

Unfortunately, this is still broken-ish. without special handling you'll end up doing twice the syntax highlighting work in bracket-matching cases. You'll type an open-quote and Xi will send to the syntect plugin for re-highlighting, which will start re-highlighting the rest of the file as a string, meanwhile the bracket-matcher will add a close-quote, which will trigger another syntect job which will fix the previous job and start fixing the highlighting for however many lines it messed up before the close quote came in. I think the way Sublime and other reasonable editors do it is to synchronously process all things triggered by the user's keystroke (bracket-matching, auto-indent, snippet expansion, possibly even plugins) and after all of those have completed, then it does syntax highlighting. I'm not sure how much it will affect latency, probably some, but it will certainly affect power usage.

The only way I can think of to fix that is to create a graph of which "low-latency" plugins can affect other plugins, then topological sort it (it ought to be acyclic) and wait for plugin results with a timeout synchronously in that order. This order could just be a list in a config file done by hand because it will be a small list and easy to figure out what the best order would be. This is only viable if the round-trip latency on RPC requests is maybe less than 100 microseconds. It might also be a good idea to only send the updates to other higher-latency plugins after the low-latency plugins are done so that they don't also start jobs and then immediately throw them away when the matched bracket comes in.

And of course my mental model of Jonathan Blow won't shut up about how the overhead of the RPCs and the asynchronous model resolving will take 100-1000x longer than just doing straightforward bracket-matching and auto-indent synchronously in-process. Doing so would be faster, easier, would always display the correct content first try and would never do unnecessary work.

cc participants when this was discussed on IRC: @rkusa @cmyr @raphlinus

@cmyr cmyr added the plugins label May 25, 2017
@raphlinus raphlinus mentioned this issue Nov 24, 2017
10 tasks
cmyr added a commit to cmyr/xi-editor that referenced this issue Apr 20, 2018
With this patch, edit events are not rendered to the client immediately
if there are any active plugins. Instead a render is scheduled after a
brief delay (currently 2 ms) during which window any changes received
from plugins will be batched into a single render.

Progress on xi-editor#437. Closes xi-editor#267.
cmyr added a commit to cmyr/xi-editor that referenced this issue Apr 20, 2018
With this patch, edit events are not rendered to the client immediately
if there are any active plugins. Instead a render is scheduled after a
brief delay (currently 2 ms) during which window any changes received
from plugins will be batched into a single render.

Progress on xi-editor#437. Closes xi-editor#267.
cmyr added a commit to cmyr/xi-editor that referenced this issue Apr 21, 2018
With this patch, edit events are not rendered to the client immediately
if there are any active plugins. Instead a render is scheduled after a
brief delay (currently 2 ms) during which window any changes received
from plugins will be batched into a single render.

Progress on xi-editor#437. Closes xi-editor#267.
@cmyr cmyr closed this as completed in #626 Apr 24, 2018
cmyr added a commit that referenced this issue Apr 24, 2018
With this patch, edit events are not rendered to the client immediately
if there are any active plugins. Instead a render is scheduled after a
brief delay (currently 2 ms) during which window any changes received
from plugins will be batched into a single render.

Progress on #437. Closes #267.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants