-
Notifications
You must be signed in to change notification settings - Fork 81
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Performance oddities on OS X 10.15.5 #62
Comments
Notice that the Rust version and C version is quite different implementations. It would be better to to report it there. Also it's possible to set the wait time to |
I did notice that and did set the wait time to None in the rust version. The behaviors were identical. I can include the rust code if desired but it is the virtual equivalent of the above C code. My thought was that it is not something with the minifb code (either version) but rather because of the very similar behavior of effectively limiting to 30 FPS it may something in the OSX layer. For what it is worth I am running Catalina on a 2017 MPB, Intel HD Graphics 630 1536 MB, and 16 GB RAM. Above I said "drawInMTKView in OSXViewDelegate.m comes into play because of the ~.96 number" which is false. The .96 number (which is likely not relevant) is in mfb_wait_sync in McMiniFB.m. My mistake. |
I experimented a bit more and found something interesting. When the FPS is set to below 60 it works as expected. When it is 60 is goes funky and all of a sudden the stack trace under mfb_open_ex starts to take ~33ms (30 FPS - all numbers are approximate). I put printfs in the above code as follows:
The output of this code for a few frame rates ( set by calling mfb_set_target_fps ): 10: Notice most time is 'in' mfb_wait_sync as would be expected. Fields are:
30: (As above - Also you can see that the 0.96 limit is being enforced in mfb_wait_sync as expected)
50:
59:
60:
But once in a while you get:
FWIW, you get identical numbers for any setting over 60. I profiled the code using FPS 60 and 30. There are a few differences that jump out which will not be a surprise from the above numbers:
I will look and see if there are any Metal oddities around update rates. This is so stark and obvious that I can't be the first to hit it. It is possible that It is a setting somewhere on my machine. I remember that certain trackpad settings in the past would limit frame rates for example. |
Compiling libminifb.a with USE_METAL_API=OFF removed the FPS limitation. I can sustain 120 FPS (didn't try faster) on the no-op example above. I read that MTKView limits frame rates to 60 FPS. I wonder if something in there is being tickled, at least in my configuration of software/hardware. I do know know enough about the API to say. Disabling metal unfortunately does not solve my problem on the Rust side which is what I prefer to use ( memory safe languages == good ). Obviously not a question for this project but the Rust version does not have the preprocessor conditionals and I would need to port the 15 places where it is used in the C version. Add to that that disabling Metal is probably not the "right thing" to do and I circle back to trying to figure out where I am going wrong with Metal. |
Yeah so if you disable Metal you won't be able to use |
I'll try and get my hands on a different Mac or two and see if I can reproduce it or not. Definitely unique behavior. |
Great! Thanks for investigating :) |
What better to do on a Sunday morning than to continue banging my head against this wall. I made some progress, though I do not have a full explanation as of yet. I got it all to build under xcode (I never use it so it was a bit foreign to me) in order to easily get the GPU data. What I saw there conformed with the documentation: When I set FPS to 60 I got 60 FPS. When I set it to 59, I got 30 FPS. Of course, at the application level, each loop was taking ~16.6 with 59 FPS and ~33.3 ms with 60 FPS. Obviously the MTKView is working independently from the application level. Why it is causing the call under drawInMTKView to block at 60 and not at 30, I do not know yet. Thinking that maybe there is some rounding error when converting from FPS -> g_time_for_frame -> view.preferredFramesPerSecond I hard coded the last to 30. And it worked. By worked I mean I got 30 FPS in the GPU debugger and the application was humming along at 60 'loops' per second. Leaving the mfb_set_target_fps() at 60, I changed the hard coded preferredFramesPerSecond to 10 and I got 10 FPS in the GPU debugger and still 60 loops per second in the application (as expected). When preferredFramesPerSecond is 60 (or higher), I get the blocking behavior where each loop takes 33.3ms.
(*) The difference between measured and expected is due to the 0.96 limit in mfb_wait_sync So solution? No. Workaround, yes. Hardcoding (for now) preferredFramesPerSecond and using a different number for mfb_set_target_fps gets me where I need to be for the moment. It is more important to me to have the application level tick along at a regular than it is to have a 60 FPS frame rate. Could I have just saved all this work and set the rate to 30 FPS to start with? Sure! But where would be the fun in that? The mystery remaining is to explain the behavior when preferredFramesPerSecond is set to 60. Why does it 'block' for 33.3ms 95% or so of the time? Something about the triple buffering? The fact that it is sometimes 16.67 (1 frame) and most of the time 33.3 (2 frames) is suspicious. Living on the edge I removed the semaphores protecting the ring buffer or buffer and no effect. May a Metal wizard someday stumble upon this and slap me aside the head and say, "HERE'S your problem!" |
So I currently use tripple buffering (as recommended by the documentation to not get any GPU stalls) What you could try to is to set this https://github.com/emoon/rust_minifb/blob/master/src/native/macosx/OSXWindowFrameView.h#L6 I don't think it will/shouldn't unless something is broken when the Metal setup (the Metal code I use there is the first one I ever wrote for Metal so there may be issues) |
because minifb has fps issues on macOS. cf. aduros#554 emoon/minifb#62
because minifb has fps issues on macOS. cf. aduros#554 emoon/minifb#62
because minifb has fps issues on macOS. cf. aduros#554 emoon/minifb#62
I stated with the rust version and then switched to the C version to debug this issue. In short, I cannot reliably get any frame rates faster than 30 FPS ( ~33 ms per frame ). I dug into the code and the only explicit timing code I see is in mfb_wait_sync in MacMiniFB.m. I figured before I started looking up OSX API calls (not as familiar with them as I want to be) I would see if this is a known issue of some sort.
This is with the latest version of the rust and C APIs using Metal.
In short, if I set a framerate in the C version or set the limit_update_rate in the Rust version, once I go below 30 FPS the majority of the frames still take ~33ms. Sample output from the code below fro fps set to 60:
And fps set to 10 (somehow I think the code in drawInMTKView in OSXViewDelegate.m comes into play because of the ~.96 number but I do not know how it gets there:
My barebones code is below. This is drastically reduced from the original to try and isolate the issue.:
The text was updated successfully, but these errors were encountered: