learn-wgpu
learn-wgpu copied to clipboard
Memory leak on MacOS
Hi, I'm following this tutorial trying to learn wgpu.
Idk why but when I start the program (also only creating the pipeline) it starts taking something like 50Gb of RAM and the os kills it. This seems to happen only on MacOS and I don't know if it's a M1 SoC related issue.
I also opened an issue on the wgpu repo but wgpu examples seems to run just fine so I think there is something wrong with the tutorial, indeed I opened this issue here
P.S.
If you want you can contact me on discord too: LolzDEV#3402
I'm having a similar issue when running the tutorial code (e.g. tutorial4-buffer). The application mostly runs fine until I switch workspaces, then the process' memory usage goes through the roof. M1 OSX also.
works fine on Intel MacBook Pro , it should be a M1 SoC related issue.
Hello, some investigation on this problem was done over on https://github.com/bevyengine/bevy/issues/5856. As a side effect of doing a lot of that investigation using learn-wgpu
, I found that the following change on the run()
function mitigates this problem:
+ let mut is_occluded = true;
event_loop.run(move |event, _, control_flow| {
- *control_flow = ControlFlow::Poll
+ *control_flow = if is_occluded {
+ ControlFlow::Wait
+ } else {
+ ControlFlow::Poll
+ };
match event {
- Event::MainEventsCleared => window.request_redraw(),
+ Event::MainEventsCleared if !is_occluded => window.request_redraw(),
Event::WindowEvent {
ref event,
window_id,
} if window_id == window.id() => {
+ if let WindowEvent::Occluded(occ) = event {
+ is_occluded = *occ;
+ *control_flow = if is_occluded {
+ ControlFlow::Wait
+ } else {
+ ControlFlow::Poll
+ }
+ }
WindowEvent::Occluded
was introduced on winit 0.27.0
, so make sure to update Cargo.toml
:
[dependencies]
winit = "0.27.2"
This change makes the winit
runloop stop polling if the window is occluded, which essentially makes the application go to sleep, mitigating the memory leak.
Let me know if this fixes the problem if you are on Apple Silicon. Do keep in mind this is only a mitigation: I recently just found that on --release
mode, while it will no longer leak memory uncontrollably, it will still leak around 100 Mb when doing an alt-tab (this is a very timing-dependent issue; it does behave better without optimizations). However, that might be just enough for the problem to become bearable for most users (it might be worth it to include on the guide as a note specifically for macOS users?).
If one is feeling really, really adventurous, this problem can also be completely fixed by driving the winit
runloop using Apple's CVDisplayLink
.
I do not really have enough experience with graphics programming to recommend using the following code on a production application, but here is a gist that uses the display-link
crate to drive the winit
runloop by jerry-rigging both through a makeshift semaphore recipe taken from the Rust documentation.
...it's a really hacky approach, but it does definitely fix the memory usage completely. This enforces Vsync, however.
I tried your solution, and while it did work for a while, unfortunately it still leaked after switching spaces a few more times.
~66mb -> 1.4 GB:
It seems like checking window occlusion is not quite enough, and my conclusion is that everywhere I go Apple wreaks havoc to the technology I'm pursuing. I found wgpu and ditched OpenGL for good (cuz apple), but now I'm getting memory leak problems that no one has solved in the past 2 years. I'm wondering how libraries like bgfx solve this issue, since they have a Metal backend, and I'm pretty sure they don't use CVDisplayLink.
Edit: After more investigation i really do think it's an Apple problem. I tried Google's Dawn and they have the same issue.