1
0
Fork 0
mirror of https://github.com/alacritty/alacritty.git synced 2025-08-07 22:12:25 -04:00

Eliminate extra renders

Currently has a bug where screen is blank at startup. That aside,
Alacritty uses basically 0 CPU now. The input thread is still separate
from the render thread, but, given the ability to wake the event loop,
it may be possible to merge them again. I'm not sure if that's actually
desirable.

Performance is seemingly unchanged.
This commit is contained in:
Joe Wilm 2016-08-31 21:16:17 -07:00
parent 0a94ccfcca
commit 0517f376be
3 changed files with 98 additions and 32 deletions

6
Cargo.lock generated
View file

@ -7,7 +7,7 @@ dependencies = [
"errno 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "errno 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
"font 0.1.0", "font 0.1.0",
"gl_generator 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", "gl_generator 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
"glutin 0.6.1 (git+https://github.com/jwilm/glutin?rev=45092a8e2f6706a7b2c613ff212341754e346c9c)", "glutin 0.6.1 (git+https://github.com/jwilm/glutin?rev=16ed800f68022a37203434bd3b542ff5400c1403)",
"libc 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
"notify 2.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "notify 2.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
"parking_lot 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
@ -285,7 +285,7 @@ dependencies = [
[[package]] [[package]]
name = "glutin" name = "glutin"
version = "0.6.1" version = "0.6.1"
source = "git+https://github.com/jwilm/glutin?rev=45092a8e2f6706a7b2c613ff212341754e346c9c#45092a8e2f6706a7b2c613ff212341754e346c9c" source = "git+https://github.com/jwilm/glutin?rev=16ed800f68022a37203434bd3b542ff5400c1403#16ed800f68022a37203434bd3b542ff5400c1403"
dependencies = [ dependencies = [
"android_glue 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "android_glue 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -906,7 +906,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum gdi32-sys 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "65256ec4dc2592e6f05bfc1ca3b956a4e0698aa90b1dff1f5687d55a5a3fd59a" "checksum gdi32-sys 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "65256ec4dc2592e6f05bfc1ca3b956a4e0698aa90b1dff1f5687d55a5a3fd59a"
"checksum gl_generator 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f1d8edc81c5ae84605a62f5dac661a2313003b26d59839f81d47d46cf0f16a55" "checksum gl_generator 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f1d8edc81c5ae84605a62f5dac661a2313003b26d59839f81d47d46cf0f16a55"
"checksum gleam 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)" = "13a363b2a5264b600e530db2f14b3c487098e6dee0655f2810ea779385cbac5a" "checksum gleam 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)" = "13a363b2a5264b600e530db2f14b3c487098e6dee0655f2810ea779385cbac5a"
"checksum glutin 0.6.1 (git+https://github.com/jwilm/glutin?rev=45092a8e2f6706a7b2c613ff212341754e346c9c)" = "<none>" "checksum glutin 0.6.1 (git+https://github.com/jwilm/glutin?rev=16ed800f68022a37203434bd3b542ff5400c1403)" = "<none>"
"checksum heapsize 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "abb306abb8d398e053cfb1b3e7b72c2f580be048b85745c52652954f8ad1439c" "checksum heapsize 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "abb306abb8d398e053cfb1b3e7b72c2f580be048b85745c52652954f8ad1439c"
"checksum inotify 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e8458c07bdbdaf309c80e2c3304d14c3db64e7465d4f07cf589ccb83fd0ff31a" "checksum inotify 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e8458c07bdbdaf309c80e2c3304d14c3db64e7465d4f07cf589ccb83fd0ff31a"
"checksum itoa 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ae3088ea4baeceb0284ee9eea42f591226e6beaecf65373e41b38d95a1b8e7a1" "checksum itoa 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ae3088ea4baeceb0284ee9eea42f591226e6beaecf65373e41b38d95a1b8e7a1"

View file

@ -13,7 +13,7 @@ notify = "2.6"
bitflags = "*" bitflags = "*"
font = { path = "./font" } font = { path = "./font" }
errno = "0.1.6" errno = "0.1.6"
parking_lot = "0.3.1" parking_lot = { version = "0.3.1", features = ["nightly"] }
serde = "0.8" serde = "0.8"
serde_yaml = "0.4" serde_yaml = "0.4"
serde_macros = "0.8" serde_macros = "0.8"

View file

@ -52,21 +52,45 @@ mod io;
mod sync; mod sync;
use std::sync::{mpsc, Arc}; use std::sync::{mpsc, Arc};
use std::sync::atomic::{AtomicBool, Ordering};
use sync::PriorityMutex; use parking_lot::{Condvar, Mutex};
use config::Config; use config::Config;
use io::{Utf8Chars, Utf8CharsError};
use meter::Meter; use meter::Meter;
use renderer::{QuadRenderer, GlyphCache}; use renderer::{QuadRenderer, GlyphCache};
use sync::PriorityMutex;
use term::Term; use term::Term;
use tty::process_should_exit; use tty::process_should_exit;
use util::thread; use util::thread;
use io::{Utf8Chars, Utf8CharsError};
/// Channel used by resize handling on mac /// Channel used by resize handling on mac
static mut resize_sender: Option<mpsc::Sender<(u32, u32)>> = None; static mut resize_sender: Option<mpsc::Sender<(u32, u32)>> = None;
struct Waiter {
mutex: Mutex<bool>,
cond: Condvar,
}
impl Waiter {
pub fn new() -> Waiter {
Waiter {
mutex: Mutex::new(false),
cond: Condvar::new(),
}
}
pub fn notify(&self) {
self.cond.notify_one();
}
pub fn wait(&self) {
let mut guard = self.mutex.lock();
self.cond.wait(&mut guard);
}
}
/// Resize handling for Mac /// Resize handling for Mac
fn window_resize_handler(width: u32, height: u32) { fn window_resize_handler(width: u32, height: u32) {
unsafe { unsafe {
@ -126,6 +150,9 @@ fn main() {
let rasterizer = font::Rasterizer::new(dpi.x(), dpi.y(), dpr); let rasterizer = font::Rasterizer::new(dpi.x(), dpi.y(), dpr);
let waiter = Arc::new(Waiter::new());
let dirty = Arc::new(AtomicBool::new(false));
// Create renderer // Create renderer
let mut renderer = QuadRenderer::new(width, height); let mut renderer = QuadRenderer::new(width, height);
@ -163,7 +190,11 @@ fn main() {
let terminal = Arc::new(PriorityMutex::new(terminal)); let terminal = Arc::new(PriorityMutex::new(terminal));
let pty_reader_thread = spawn_pty_reader(terminal.clone(), reader); let pty_reader_thread = spawn_pty_reader(terminal.clone(),
reader,
waiter.clone(),
dirty.clone(),
window.create_window_proxy());
let window = Arc::new(window); let window = Arc::new(window);
@ -173,11 +204,15 @@ fn main() {
renderer, renderer,
glyph_cache, glyph_cache,
render_timer, render_timer,
rx); rx,
waiter.clone(),
dirty);
handle_window_events(&mut writer, terminal, window); handle_window_events(&mut writer, terminal, window);
pty_reader_thread.join().ok(); pty_reader_thread.join().ok();
waiter.notify();
render_thread.join().ok(); render_thread.join().ok();
println!("Goodbye"); println!("Goodbye");
} }
@ -219,12 +254,23 @@ fn handle_window_events<W>(writer: &mut W,
&mut input::WriteNotifier(writer), &mut input::WriteNotifier(writer),
*terminal.mode()) *terminal.mode())
}, },
glutin::Event::Awakened => {
if process_should_exit() {
println!("input thread exitting");
break;
}
}
_ => (), _ => (),
} }
} }
} }
fn spawn_pty_reader<R>(terminal: Arc<PriorityMutex<Term>>, mut pty: R) -> std::thread::JoinHandle<()> fn spawn_pty_reader<R>(terminal: Arc<PriorityMutex<Term>>,
mut pty: R,
waiter: Arc<Waiter>,
dirty: Arc<AtomicBool>,
proxy: ::glutin::WindowProxy) -> std::thread::JoinHandle<()>
where R: std::io::Read + Send + 'static, where R: std::io::Read + Send + 'static,
{ {
thread::spawn_named("pty reader", move || { thread::spawn_named("pty reader", move || {
@ -233,11 +279,12 @@ fn spawn_pty_reader<R>(terminal: Arc<PriorityMutex<Term>>, mut pty: R) -> std::t
let mut pty_parser = ansi::Parser::new(); let mut pty_parser = ansi::Parser::new();
loop { loop {
let got = pty.read(&mut buf[start..]).expect("pty fd active"); if let Ok(got) = pty.read(&mut buf[start..]) {
let mut remain = 0; let mut remain = 0;
// if `start` is nonzero, then actual bytes in buffer is > `got` by `start` bytes. // if `start` is nonzero, then actual bytes in buffer is > `got` by `start` bytes.
let end = start + got; let end = start + got;
{
let mut terminal = terminal.lock_low(); let mut terminal = terminal.lock_low();
for c in Utf8Chars::new(&buf[..end]) { for c in Utf8Chars::new(&buf[..end]) {
match c { match c {
@ -251,22 +298,32 @@ fn spawn_pty_reader<R>(terminal: Arc<PriorityMutex<Term>>, mut pty: R) -> std::t
} }
} }
} }
}
dirty.store(true, Ordering::Release);
waiter.notify();
// Move any leftover bytes to front of buffer // Move any leftover bytes to front of buffer
for i in 0..remain { for i in 0..remain {
buf[i] = buf[end - (remain - i)]; buf[i] = buf[end - (remain - i)];
} }
start = remain; start = remain;
} else {
proxy.wakeup_event_loop();
break;
}
} }
}) })
} }
fn spawn_renderer(window: Arc<glutin::Window>, fn spawn_renderer(window: Arc<glutin::Window>,
terminal: Arc<PriorityMutex<Term>>, terminal_mutex: Arc<PriorityMutex<Term>>,
mut renderer: QuadRenderer, mut renderer: QuadRenderer,
mut glyph_cache: GlyphCache, mut glyph_cache: GlyphCache,
render_timer: bool, render_timer: bool,
rx: mpsc::Receiver<(u32, u32)>) -> std::thread::JoinHandle<()> { rx: mpsc::Receiver<(u32, u32)>,
waiter: Arc<Waiter>,
dirty: Arc<AtomicBool>) -> std::thread::JoinHandle<()> {
thread::spawn_named("render", move || { thread::spawn_named("render", move || {
unsafe { unsafe {
let _ = window.make_current(); let _ = window.make_current();
@ -277,7 +334,15 @@ fn spawn_renderer(window: Arc<glutin::Window>,
// Scope ensures terminal lock isn't held when calling swap_buffers // Scope ensures terminal lock isn't held when calling swap_buffers
{ {
// Acquire term lock // Acquire term lock
let mut terminal = terminal.lock_high(); let mut terminal = terminal_mutex.lock_high();
if !dirty.load(Ordering::Acquire) {
drop(terminal);
waiter.wait();
terminal = terminal_mutex.lock_high();
}
dirty.store(false, Ordering::Release);
// Resize events new_size and are handled outside the poll_events // Resize events new_size and are handled outside the poll_events
// iterator. This has the effect of coalescing multiple resize // iterator. This has the effect of coalescing multiple resize
@ -328,6 +393,7 @@ fn spawn_renderer(window: Arc<glutin::Window>,
if process_should_exit() { if process_should_exit() {
break; break;
} else {
} }
} }
}) })