Hyper 3 is finally out! The primary focus for this release is performance.
The latest version includes several enhancements that make Hyper really fast. For those of us who spend a significant amount of time on the command line, this release is a total game changer.
Download Hyper 3 below to try it out, and read on to learn more about what's new.
Looking back on this release, a pleasant surprise has been how little time it took from "let's make this thing faster" to "Holy shell! That's fast!"
Below, we visit some of the important changes that were shipped as part of this release:
The renderer is the piece of code that draws actual pixels on the screen based on the state of the terminal. The original Hyper renderer was based on the DOM. While that was a flexible approach thanks to CSS, it was also very slow.
Hyper 2 improved upon this by switching from
xterm.js and using its
canvas-based renderer. While that made Hyper 2 faster, for Hyper 3 we knew it was
possible to deliver even faster performance by completely rewriting the renderer with
By fortunate coincidence, as we were still figuring things out,
Daniel Imms (from
VSCode fame), just returned from a "vacation"
where he happened to be write a shiny new WebGL renderer.
Isn't the open source community just amazing? We immediately merged Daniel's branch onto a test fork, and well, it ran circles around Hyper 2. Thanks Daniel!
We are aware of a few minor limitations with using this renderer (e.g selection is always black-and-white, and you can't have more than 16 terminals visible simultaneously) but the performance benefits outweigh them. The new renderer is still work-in-progress, so you can expect further improvements in the near future.
We also discovered that commands that were very verbose would cause Hyper to
temporarily choke for a few seconds. For example, running
find ~ would cause Hyper to:
- Run painfully slow for ~5 seconds (at ~1 frame-per-second)
- Suddenly get faster (at ~15 frames-per-second) and finish printing everything in ~10 seconds.
Digging within the CPU profile, we noticed that the "renderer" process was spending most of its time handling an overwhelming amount of messages coming in from the main process.
Electron uses a multi-process architecture where each window runs on its own separate "renderer" process. Additionally, there's one Node.js-based "main" process that communicates directly with the underlying OS. In order for terminal data to be rendered by Hyper, it must be passed from the main process to the renderer process using IPC (Inter-Process Communication).
Node's IPC, unfortunately, comes with a non-trivial amount of overhead.
Messages are sent back and forth as JSON strings, which must be encoded on
one side and decoded on the other. Also, receiving data through IPC is
an async operation, and thus queued in V8's event loop. Yielding back to the
event loop each time after processing small messages makes matters further worse.
This repeated IPC caused thrashing when processing bursts of text (like running
cat on a large file).
To mitigate this problem, we came up with a simple solution: batch data into larger chunks before sending them to the renderer process. IPC batching reduces the number of messages for verbose commands significantly and allows the renderer to focus on, well, rendering.
One important consideration was to batch as much data as possible to reduce the IPC overhead, but not so much that we introduce perceivable latency. With this approach, the renderer process now spends most of its time doing terminal emulation and rendering instead of processing IPC messages. The outcome is a much smoother, and faster terminal.
On a similar vein, we are also testing a new approach to decide how much data is parsed before yielding to the renderer. The idea is to prevent skipped frames for a more responsive terminal.
Hyper 3 bumps the underlying Electron from V1 to V3. We also tested V4, but a regression in the Canvas API forced us to stay on V3. The upgrade brings in newer versions of V8 and Node.js, and their corresponding bug fixes.
Faster Startup Time
Hyper 3 improves startup time by creating the first pseudoterminal (pty) as soon as possible. A pty is a facility provided by operating systems to allow programs such as Hyper to emulate terminals.
In previous versions, Hyper would wait for the Chromium window to open, send an "I'm ready" message, and only then create the pty. Those two activities take a substantial amount of time, but could be done in parallel.
Hyper 3 starts initializing both at the same time. By the time the window says "I'm ready", the pty is already warmed-up and ready to be consumed. This gives Hyper 3 a decent boost in launch time (about 150ms on Linux, potentially better on other platforms).
If you're on MacOS, you can now press
Command + Control + Space to get an
emoji popup and jazz up those commit messages.
More Themes on Hyper Store
Since Hyper 2, we have added many new themes into the Hyper Store. This means it's now even easier to customise your Hyper experience to your personality.
We have a detailed contribution page that explains how you can go about enlisting your extension. We encourage all contribution and look forward to adding more themes and plugins from the community!
The Road Ahead
Terminals have existed since the 60s, and have been a powerful tool in our workflows. Their flexibility guarantees that they will remain relevant for years to come. We're in for the long haul.
We're excited to keep improving Hyper, both in terms of performance and capabilities — there's a lot to do. Hyper is completely open source, and we welcome your involvement and contribution.
We're genuinely thankful to the open source community. We're not saying this only because we are building on top of an incredible set of open source libraries, but also because we find the helpful ethos of the community very touching.
As soon as the
xterm.js team heard we
were working on performance, they jumped right in and helped us with
feedback and several initiatives they had on their side. We would like to extend
huge thanks to Daniel Imms,
Benjamin Staneck for their contribution and feedback.