rust-windowing / winit

Window handling library in pure Rust
https://docs.rs/winit/
Apache License 2.0
4.88k stars 913 forks source link

Very high CPU usage on Wayland due to constant RedrawRequested events #3933

Closed vladh closed 2 months ago

vladh commented 2 months ago

Description

I'm using iced and encountering very high GPU usage in all use cases, on Wayland only. (https://github.com/iced-rs/iced/issues/2558)

I'm testing whether winit is the cause of the issue. I'm using the following Hello World program:

use winit::application::ApplicationHandler;
use winit::event::WindowEvent;
use winit::event_loop::{ActiveEventLoop, ControlFlow, EventLoop};
use winit::window::{Window, WindowId};

#[derive(Default)]
struct App {
    window: Option<Window>,
}

impl ApplicationHandler for App {
    fn resumed(&mut self, event_loop: &ActiveEventLoop) {
        self.window = Some(event_loop.create_window(Window::default_attributes()).unwrap());
    }

    fn window_event(&mut self, event_loop: &ActiveEventLoop, _id: WindowId, event: WindowEvent) {
        match event {
            WindowEvent::CloseRequested => {
                event_loop.exit();
            },
            WindowEvent::RedrawRequested => {
                self.window.as_ref().unwrap().request_redraw();
            }
            _ => (),
        }
    }
}

fn main() {
    let event_loop = EventLoop::new().unwrap();
    event_loop.set_control_flow(ControlFlow::Wait);
    let mut app = App::default();
    let _ = event_loop.run_app(&mut app);
}

Running this on my system causes very high CPU usage:

2024-09-28-18-46-01

My understanding is that this shouldn't happen with ControlFlow::Wait.

The CPU usage drops to ~0% if I remove this line:

self.window.as_ref().unwrap().request_redraw();

Printing the events received shows constant RedrawRequested events — 76,000 events per second.

Do you have any pointers about how I might continue debugging this? I'm happy to put in more work, but am a bit stumped right now.

Debugging output

No response

Window isn't shown unless you draw

Winit version

0.30.5

kchibisov commented 2 months ago

you ask to draw as fast as you can so everything works as expected. If you want to throttle drawing, use pre_present_notify(all of that is mentioned in docs).

kchibisov commented 2 months ago

Keep in mind here, the pre_present_notify will only work if you do the drawing, if you don't ever do that it's pretty much useless and won't change anything.

The default window.rs example does things pretty much as they should and draws with the display refresh rate, etc, etc.