summaryrefslogtreecommitdiff
path: root/alacritty_terminal
diff options
context:
space:
mode:
authorChristian Duerr <contact@christianduerr.com>2021-07-08 20:35:58 +0000
committerGitHub <noreply@github.com>2021-07-08 20:35:58 +0000
commit8cb1acc27d863942401df80c3acb8b4016ad6083 (patch)
tree5772b74e40235ef4e9367d33014646a36666e320 /alacritty_terminal
parent4a3bcdb49d2027d4cbf6a2f147b07da38a4b0238 (diff)
downloadalacritty-8cb1acc27d863942401df80c3acb8b4016ad6083.tar.gz
alacritty-8cb1acc27d863942401df80c3acb8b4016ad6083.zip
Fix PTY performance regressions
The patch 9e7655e introduced some changes which improved rendering with very dense grids, but the automatic benchmarks indicated a slight performance difference in the `dense_cells` benchmark. Caching the terminal lock between iterations rather than always calling `try_lock` resolves that issue. While breaking early in the `WouldBlock` case with `unprocessed != 0` does also help resolve these issues, it shows some more significant fluctuations. Combining both fixes does not help. Additionally on Windows receiving `Ok(0)` from the PTY will also occur instead of a `WouldBlock` error, so handling that fixes freezing on Windows. Fixes #5305.
Diffstat (limited to 'alacritty_terminal')
-rw-r--r--alacritty_terminal/src/event_loop.rs45
1 files changed, 40 insertions, 5 deletions
diff --git a/alacritty_terminal/src/event_loop.rs b/alacritty_terminal/src/event_loop.rs
index 1a6ee8f3..b0676e4d 100644
--- a/alacritty_terminal/src/event_loop.rs
+++ b/alacritty_terminal/src/event_loop.rs
@@ -221,10 +221,13 @@ where
// Reserve the next terminal lock for PTY reading.
let _terminal_lease = Some(self.terminal.lease());
+ let mut terminal = None;
loop {
// Read from the PTY.
match self.pty.reader().read(&mut buf[unprocessed..]) {
+ // This is received on Windows/macOS when no more data is readable from the PTY.
+ Ok(0) if unprocessed == 0 => break,
Ok(got) => unprocessed += got,
Err(err) => match err.kind() {
ErrorKind::Interrupted | ErrorKind::WouldBlock => {
@@ -238,11 +241,14 @@ where
}
// Attempt to lock the terminal.
- let mut terminal = match self.terminal.try_lock_unfair() {
- // Force block if we are at the buffer size limit.
- None if unprocessed >= READ_BUFFER_SIZE => self.terminal.lock_unfair(),
- None => continue,
+ let terminal = match &mut terminal {
Some(terminal) => terminal,
+ None => terminal.insert(match self.terminal.try_lock_unfair() {
+ // Force block if we are at the buffer size limit.
+ None if unprocessed >= READ_BUFFER_SIZE => self.terminal.lock_unfair(),
+ None => continue,
+ Some(terminal) => terminal,
+ }),
};
// Write a copy of the bytes to the ref test file.
@@ -252,7 +258,7 @@ where
// Parse the incoming bytes.
for byte in &buf[..unprocessed] {
- state.parser.advance(&mut *terminal, *byte);
+ state.parser.advance(&mut **terminal, *byte);
}
processed += unprocessed;
@@ -425,3 +431,32 @@ where
})
}
}
+
+trait OptionInsert {
+ type T;
+ fn insert(&mut self, value: Self::T) -> &mut Self::T;
+}
+
+// TODO: Remove when MSRV is >= 1.53.0.
+//
+/// Trait implementation to support Rust version < 1.53.0.
+///
+/// This is taken [from STD], further license information can be found in the [rust-lang/rust
+/// repository].
+///
+///
+/// [from STD]: https://github.com/rust-lang/rust/blob/6e0b554619a3bb7e75b3334e97f191af20ef5d76/library/core/src/option.rs#L829-L858
+/// [rust-lang/rust repository]: https://github.com/rust-lang/rust/blob/master/LICENSE-MIT
+impl<T> OptionInsert for Option<T> {
+ type T = T;
+
+ fn insert(&mut self, value: T) -> &mut T {
+ *self = Some(value);
+
+ match self {
+ Some(v) => v,
+ // SAFETY: the code above just filled the option
+ None => unsafe { std::hint::unreachable_unchecked() },
+ }
+ }
+}