learn-wgpu icon indicating copy to clipboard operation
learn-wgpu copied to clipboard

Memory leak on MacOS

Open ghost opened this issue 2 years ago • 4 comments

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

ghost avatar Jul 27 '21 22:07 ghost

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.

pacmanmati avatar Aug 08 '21 13:08 pacmanmati

works fine on Intel MacBook Pro , it should be a M1 SoC related issue.

JunkuiZhang avatar Aug 12 '21 04:08 JunkuiZhang

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.

Nnubes256 avatar Sep 02 '22 11:09 Nnubes256

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: image

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.

williamhCode avatar May 23 '23 14:05 williamhCode