RFC: Generate back-pressure to keep a steady framerate
@juancampa is already working on this.
Since Dec 17, 2018.
- Dominant language
- TypeScript
- Stars
- 44.7k
- Forks
- 3.6k
- Avg merge
- 21m
- Merged PRs (30d)
- 1
Description
Opening this RFC to hear everyone's thoughts and ideas
Problem
Renderer is slowed down and starts dropping frames when the pty emits a lot of data (say, by running yes)
To recap, the data pipeline in hyper works as follows:
node-ptyemits the binary data coming from the OS (typically in chunks of 4k but could be more, e.g. 64k)session.jslistens and batches this data for a few ms to reduce IPC thrashing when there's a lot of output. 1️⃣app/rpc.jssends the batched data to the renderer process (as "session data")lib/utils/rpc.jsreceives the data in the renderer process and emits a "session data" eventlib/indexdispatches a redux action with the datalib/store/write-middleware.jssends the data to the xterm.jsTerminalinstanceTerminalstores it in the writeBuffer (an array of strings) and starts parsing (asynchronously)- Terminal takes every chunk and parses it completely 2️⃣ (this is the most CPU intensive part and the current bottleneck)
(feel free to correct me if there's something inaccurate)
Proposed solution
In 2️⃣, keep track of how long it's taking to process each byte and determine how long each chunk should be so as to spend less than, say, 16ms (60fps here) parsing it. Then use this value either at 1️⃣ or at 2️⃣ to make sure chunks are not oversized.
Of course, as pointed out by @jerch, we must also account for GC and rendering, so the actual time should be less than 16ms.
I'm leaning heavily towards 2️⃣ because it keeps the splitting logic close to where the back-pressure is generated (implemented in xterm.js)
Caveats
It's very hard to *guarantee a specific FPS just by looking at chunk size because not all bytes have the same cost (e.g. newlines are way more expensive than printable characters)
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.