From 84b9af2bec2b1d973eb9b632bba430909fccc6d1 Mon Sep 17 00:00:00 2001 From: Jens Breitbart Date: Tue, 17 Feb 2026 21:22:31 +0100 Subject: [PATCH] Batch console output to one VM exit per print call Increase serial buffer from 256 to 2048 bytes and gate newline-triggered flush on debug_assertions. In release builds, data is only flushed when the buffer is full or explicitly at the end of each _print()/_panic_print() call. This reduces VM exits from ~28 per multi-line info!() to just 1. Co-Authored-By: Claude Opus 4.6 --- src/console.rs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/console.rs b/src/console.rs index f107c07bd5..17babd5a30 100644 --- a/src/console.rs +++ b/src/console.rs @@ -14,7 +14,7 @@ use crate::executor::WakerRegistration; #[cfg(not(target_arch = "riscv64"))] use crate::syscalls::interfaces::serial_buf_hypercall; -const SERIAL_BUFFER_SIZE: usize = 256; +const SERIAL_BUFFER_SIZE: usize = 2048; pub(crate) enum IoDevice { #[cfg(not(target_arch = "riscv64"))] @@ -162,6 +162,7 @@ impl Write for Console { if SERIAL_BUFFER_SIZE - self.buffer.len() >= buf.len() { // unwrap: we checked that buf fits in self.buffer self.buffer.extend_from_slice(buf).unwrap(); + #[cfg(debug_assertions)] if buf.contains(&b'\n') { self.flush()?; } @@ -173,6 +174,7 @@ impl Write for Console { } else { // unwrap: we checked that buf fits in self.buffer self.buffer.extend_from_slice(buf).unwrap(); + #[cfg(debug_assertions)] if buf.contains(&b'\n') { self.flush()?; } @@ -209,13 +211,16 @@ pub(crate) static CONSOLE: Lazy> = Lazy::new(|| { #[doc(hidden)] pub fn _print(args: fmt::Arguments<'_>) { - CONSOLE.lock().write_fmt(args).unwrap(); + let mut console = CONSOLE.lock(); + console.write_fmt(args).unwrap(); + console.flush().unwrap(); } #[doc(hidden)] pub fn _panic_print(args: fmt::Arguments<'_>) { let mut console = unsafe { CONSOLE.make_guard_unchecked() }; console.write_fmt(args).ok(); + console.flush().ok(); mem::forget(console); }