perf: replace busy-loop Poll with WaitUntil frame limiter
Screensaver was consuming ~8% CPU due to ControlFlow::Poll rendering as fast as possible. Switch to WaitUntil with configurable FPS cap. Blank and image screensavers auto-cap at 2fps since they have no animation, reducing CPU usage to near zero.
This commit is contained in:
+3
-2
@@ -30,9 +30,10 @@ type = "blank" # pure black (default, OLED-optimal)
|
|||||||
# ── Display settings ─────────────────────────────────────────────────────────
|
# ── Display settings ─────────────────────────────────────────────────────────
|
||||||
|
|
||||||
[display]
|
[display]
|
||||||
monitor = 0 # monitor index (0 = primary). See: scr33ny monitors
|
monitor = 0 # monitor index (0 = primary). See: scr33ny monitors
|
||||||
burn_shift = 2 # pixel shift for OLED burn-in prevention
|
burn_shift = 2 # pixel shift for OLED burn-in prevention
|
||||||
shift_interval = 120 # seconds between shifts
|
shift_interval = 120 # seconds between shifts
|
||||||
|
fps = 30 # max frames per second (blank/image auto-cap at 2)
|
||||||
|
|
||||||
# ── Idle daemon ───────────────────────────────────────────────────────────────
|
# ── Idle daemon ───────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
|||||||
+14
-3
@@ -1,6 +1,6 @@
|
|||||||
use std::num::NonZeroU32;
|
use std::num::NonZeroU32;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::time::Instant;
|
use std::time::{Duration, Instant};
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use winit::{
|
use winit::{
|
||||||
@@ -55,8 +55,16 @@ pub fn run(config: Config, monitor_idx: usize) -> Result<()> {
|
|||||||
let mut screensaver: Box<dyn Screensaver> = build_screensaver(&config, font.clone())?;
|
let mut screensaver: Box<dyn Screensaver> = build_screensaver(&config, font.clone())?;
|
||||||
let mut widgets: Vec<Box<dyn Widget>> = build_widgets(&config, font)?;
|
let mut widgets: Vec<Box<dyn Widget>> = build_widgets(&config, font)?;
|
||||||
|
|
||||||
|
// Adaptive FPS: blank/image need only 1–2 fps, animations up to config.display.fps
|
||||||
|
let target_fps = match &config.screensaver {
|
||||||
|
ScreensaverConfig::Blank | ScreensaverConfig::Image { .. } => {
|
||||||
|
config.display.fps.min(2)
|
||||||
|
}
|
||||||
|
_ => config.display.fps,
|
||||||
|
}.max(1);
|
||||||
|
let frame_time = Duration::from_millis(1000 / target_fps as u64);
|
||||||
|
|
||||||
let event_loop = EventLoop::new()?;
|
let event_loop = EventLoop::new()?;
|
||||||
event_loop.set_control_flow(ControlFlow::Poll);
|
|
||||||
|
|
||||||
let monitors: Vec<_> = event_loop.available_monitors().collect();
|
let monitors: Vec<_> = event_loop.available_monitors().collect();
|
||||||
let monitor = monitors.get(monitor_idx).or_else(|| monitors.first()).cloned();
|
let monitor = monitors.get(monitor_idx).or_else(|| monitors.first()).cloned();
|
||||||
@@ -131,7 +139,10 @@ pub fn run(config: Config, monitor_idx: usize) -> Result<()> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Event::AboutToWait => window.request_redraw(),
|
Event::AboutToWait => {
|
||||||
|
elwt.set_control_flow(ControlFlow::WaitUntil(Instant::now() + frame_time));
|
||||||
|
window.request_redraw();
|
||||||
|
}
|
||||||
|
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-1
@@ -147,11 +147,13 @@ pub struct DisplayConfig {
|
|||||||
/// Anti-burn-in pixel shift in pixels, applied every shift_interval seconds
|
/// Anti-burn-in pixel shift in pixels, applied every shift_interval seconds
|
||||||
pub burn_shift: u32,
|
pub burn_shift: u32,
|
||||||
pub shift_interval: u64,
|
pub shift_interval: u64,
|
||||||
|
/// Target frames per second. Lower = less CPU. Blank/image need only 1–2.
|
||||||
|
pub fps: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for DisplayConfig {
|
impl Default for DisplayConfig {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self { monitor: 0, burn_shift: 2, shift_interval: 120 }
|
Self { monitor: 0, burn_shift: 2, shift_interval: 120, fps: 30 }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user