maplibre-rs icon indicating copy to clipboard operation
maplibre-rs copied to clipboard

maplibre-demo: High CPU and GPU usage on macOS while idle

Open vollkorntomate opened this issue 3 years ago • 10 comments

The maplibre-demo binary has a quite high CPU and GPU usage when doing nothing. Activity monitor shows around 40% CPU usage and between 25-35% GPU usage while the app is in the foreground (and has focus) and no layers are being visibly rendered and the map is not interacted with. Roughly the same usage is reported while the app is in the background (window has no focus)

🤔 Expected Behavior

The CPU and GPU usage should be at a minimum, near 0%.

😯 Current Behavior

See above.

The latest commits (from Oct 23 and 24) seem to have improved the issue. Earlier, GPU usage was near 100% while in background. However, this improvement might also be due to the macOS Ventura update.

💁 Possible Solution

I was able to narrow down the source of the problem to apparently be inside maplibre-winit/src/winit/mod.rs:170 and the call to map_schedule::InteractiveMapSchedule::update_and_redraw(), since the RedrawRequested event fires multiple times per second and thus the map re-renders all the time, costing CPU and GPU resources.

A possible solution might be to only redraw the map if

  1. it has been moved or zoomed since the last redraw or
  2. loading the map hasn't finished and thus new objects need to be rendered

🌍 Your Environment

  • Desktop
    • macOS 13.0 (Ventura)
    • M1 Max, 24 GPU Cores
  • commit ec1ad07
  • built with cargo build -p maplibre-demo
  • run with ./target/debug/maplibre-demo headed

vollkorntomate avatar Oct 25 '22 16:10 vollkorntomate

Did you run your experiments in release mode?

I'm actually not entirely certain what to expect in terms of numbers. I think there are also multiple effects which play a role here:

  • maplibre-rs is in background and currently not visible

    In this case its the job of the OS to reduce the framerate. Browsers like Firefox do this sucessfully right now with maplibre-rs No animations are currently running in maplibre-rs. The map is not moved. Data is not updated. Window is not resized. -> We should limit the frame-rate to 0 FPS in this case. No need to redraw. We need an issue for that.

After all I think that maplibre-rs even when running with 60FPS it should not consume more than 5% of CPU if the map is not moved. We need to get a feeling first on how much "energy" a simple renderer should take (energy = CPU cycles/s and GPU usage).

So we need more numbers here before.

maxammann avatar Oct 26 '22 07:10 maxammann

Did you run your experiments in release mode?

I actually ran them in debug mode. Just now I tried it again in release mode and it doesn't seem to make any difference, the numbers are the same.

No animations are currently running in maplibre-rs. The map is not moved. Data is not updated. Window is not resized. We should limit the frame-rate to 0 FPS in this case. No need to redraw. We need an issue for that.

Is this linked to an issue or somewhere from the roadmap?

vollkorntomate avatar Oct 26 '22 18:10 vollkorntomate

Is this linked to an issue or somewhere from the roadmap?

Not yet, but we probably could create an RFC which is called "energy saving", or just directly create an issue.

maxammann avatar Oct 29 '22 13:10 maxammann

I'm also experiencing the 100% core usage problem. I think the problem here is that the handler of WindowEvent::RedrawRequested calls map.window().request_redraw() again, effectively creating a busy wait loop, so the core usage is always 100% regardless of the performance of rendering.

HKalbasi avatar Oct 07 '24 23:10 HKalbasi

I'm also experiencing the 100% core usage problem. I think the problem here is that the handler of WindowEvent::RedrawRequested calls map.window().request_redraw() again, effectively creating a busy wait loop, so the core usage is always 100% regardless of the performance of rendering.

The winit library is sadly a bit inconsistent sometimes. I believe that call is required. The library is also only rendering 60FPS. So the redraw function is called only that often.

In not sure if the 100% are to be expected or not.

If the CPU is fast then it should idle and CPU utilization should be below 100%. Maybe this is a bug in wgpu?

maxammann avatar Oct 09 '24 14:10 maxammann

The library is also only rendering 60FPS. So the redraw function is called only that often.

I commented out the rendering (the run_schedule line in the same loop) and I'm still getting the 100% cpu usage. Either I removed that logic, or it is not working. Where is the code that limit it to 60fps? Maybe it is not working on my machine (for the record, I'm running it on a vm, it might be the problem)

I believe that call is required.

Why? I removed the request redraw call from there and added it to the device input event, and I got the same result with near zero cpu usage.

HKalbasi avatar Oct 09 '24 17:10 HKalbasi

Why? I removed the request redraw call from there and added it to the device input event, and I got the same result with near zero cpu usage.

Did it still execute the rendering loop 60 frames a second? I remember that this is platform depending so it might be only required on iOS.

maxammann avatar Oct 10 '24 06:10 maxammann

I commented out the rendering (the run_schedule line in the same loop) and I'm still getting the 100% cpu usage.

That could be by design. I believe the OS is responsible for calling the loop function. How often it is doing that depends on the OS. The OS can decide for instance to suspend rendering.

I'm not sure if what you experience is b design though. I imagine without the run_schedule it is just an empty while loop that gets executed.

maxammann avatar Oct 10 '24 06:10 maxammann

@HKalbasi On which OS are you? I'm testing on wayland right now and I have only 5% CPU usage.

maxammann avatar Oct 14 '24 19:10 maxammann

I'm on ubuntu 22.04 on wayland on a vm.

HKalbasi avatar Oct 15 '24 11:10 HKalbasi