DaggerfallUI OnGUI - trying to increase performance by stepping out of...

Discuss coding questions, pull requests, and implementation details.
Post Reply
agamer
Posts: 8
Joined: Sat Jul 06, 2019 2:29 am

DaggerfallUI OnGUI - trying to increase performance by stepping out of...

Post by agamer »

I setup a bool to return out of OnGUI calls inside DaggerfallUI when no window above HUD is on stack. I did this to test performance gains for less OnGUI calls while running this on oculus GO, which is android based. It seemed to help when benchmarking with profiler. What are the unintended (bad?) consequences of doing such a thing? I can put vitals and compass and other ui parts in their own space using the solution InterKarma and InconsollableCellist came up with I think? So far menus come up ok even dialogs and other OnGUI items without impact, but I'm cutting my dev teeth on this project (and really enjoying it) and because I'm less familiar with the ins and outs I thought it would be good to get some pro feedback on it. Below is what I did (stole from others codes and hacked into ui script)

Code: Select all

{
bool enableOnGUI = true;

        private void UIManager_OnWindowChange(object sender, System.EventArgs e)
        {
            int windowCount = uiManager.WindowCount;
            //if (windowCount > 0 && !(DaggerfallUI.UIManager.TopWindow is DaggerfallWorkshop.Game.UserInterfaceWindows.DaggerfallHUD))
            if (windowCount > 0 && !(DaggerfallUI.UIManager.TopWindow is DaggerfallWorkshop.Game.UserInterfaceWindows.DaggerfallHUD))
            {
                // Window count up and is more than HUD-- enable OnGUI!
                enableOnGUI = true;
            }
            else if (windowCount <= 0 || DaggerfallUI.UIManager.TopWindow is DaggerfallWorkshop.Game.UserInterfaceWindows.DaggerfallHUD)
            {
                // Window count 0 or only HUD -- disable OnGUI
                enableOnGUI = false;
            }
        }

        void OnGUI()
        {
            if (!enableOnGUI)
                return;
} 
I'm excited to get this going and see how well I can improve performance for Oculus GO specifically, but then eager to see how well it runs on quest as it is a bump up in hardware. So far I'm enjoying playing this way on the GO, especially after adding the nice lighting effects shaders.

User avatar
Interkarma
Posts: 7244
Joined: Sun Mar 22, 2015 1:51 am

Re: DaggerfallUI OnGUI - trying to increase performance by stepping out of...

Post by Interkarma »

DaggerfallUI.OnGUI() jobs are:
  • Process hotkeys for window at top of stack
  • Call Draw() on window at top of stack
Timing the OnGUI call with System.Diagnostics.Stopwatch shows that it reliably consumes 0-1ms at all times, regardless of which windows are open. At best you'd be saving sub-1ms by short-circuiting this method. It only operates on the top window, usually the HUD, and there's never much work to do. Even the heftier UIs like the automap don't take up much actual time in Draw().

I'm surprised you'd see any noticeable difference here, unless some other changes have introduced slow-downs not seen in the base game.

agamer
Posts: 8
Joined: Sat Jul 06, 2019 2:29 am

Re: DaggerfallUI OnGUI - trying to increase performance by stepping out of...

Post by agamer »

Thanks for the quick (and gentle) reply! I will dig more and give better details.
"unless some other changes have introduced slow-downs not seen in the base game."
Yes. This. I'm sure it is related to something I'm doing with UserInterfaceRenderTarget items and how I'm using them but when I profiled it there was alot of frame time (cpu) spent in IMGUI/OnGUI. That was profiled while running on the Oculus Go, which could be related to the platform, but also the way I'm using (abusing?) the floatingui items. I will spend more time with it and get a better handle on what I'm reading because I may also be incorrectly interpreting the profiler info. Again, thanks for your time and response!

User avatar
Interkarma
Posts: 7244
Joined: Sun Mar 22, 2015 1:51 am

Re: DaggerfallUI OnGUI - trying to increase performance by stepping out of...

Post by Interkarma »

If you do need to do the short-circuit trick when no windows above HUD, it should be OK. I can't think of any bad outcomes right now. But if the root problem is elsewhere, it could potentially be rectified in a better way and make the system more scalable.

Keep digging with profiler and stopwatch, you can usually tease out the exact problem after a while. :)

User avatar
DigitalMonk
Posts: 111
Joined: Sun Nov 10, 2019 8:01 pm

Re: DaggerfallUI OnGUI - trying to increase performance by stepping out of...

Post by DigitalMonk »

I have no idea if this is relevant to your situation, because I'm not familiar with DFU's code or with the Profiler you're using. I just wanted to pass along a bit of painful advice for understanding "sampling-based" profilers.

Quick note: profilers generally come in two forms: "instrumented" _can_ be more accurate in a world of many small functions at the expense of massive slowdown and unrealistic interactions with drivers and the real world, or "sampling" which has low impact on run time performance but can only give a statistical approximation of what's happening. Most profilers are sampling profilers, or at least default to that mode.

The problem with sampling profilers is that they don't see all your code. Commonly, they take one sample every 1ms, or maybe every 0.1ms, to see where in the code the CPU happens to be at that instant in time. If the rendering code is VSYNC'ed, and your screen refresh rate is an integral number of milliseconds, you could easily see an apparent high usage in a small portion of the rendering pipeline, simply because the sampling time happens to line up there. Say you're locked to a 60Hz monitor. Frame time is 16.67ms, which isn't integral, but if we consider it at 17ms, every 17 samples of your data will be looking at a particular place in the rendering pipeline processing. If OnGui takes 1ms consistently, that's wide enough for the sampler to hit it consistently. This could lead to the profiler claiming that OnGui was taking ~6% of the time of the system, when in reality it is only consuming 0.1%.

There are other issues with sampling profilers, largely based on the fact that a 1GHz single core computer can nominally execute 1 million opcodes in 1ms, so you have 1 sample point out of 1 million things that that CPU did in that time period. Of course, the CPU is never able to maintain full theoretical throughput, but given that modern processors are more in the range of 3GHz and 4+ cores, it's not unreasonable to take a rule-of-thumb that your profiler is only seeing 0.0001% of the executing code (or maybe 0.001%, if you can speed it up to 0.1ms sampling) and then telling you which pieces of your code are most heavily used. It can work, but if it's telling you something that seems impossible, just remember that it's having to extrapolate wildly from limited data.

In particular, for any kind of video application, I would STRONGLY recommend turning off VSYNC before profiling if you want to have any chance of understanding what the code is actually doing.

(And my apologies if you already have, and if I've just wasted your time :oops: But maybe it will help someone else...)

User avatar
Interkarma
Posts: 7244
Joined: Sun Mar 22, 2015 1:51 am

Re: DaggerfallUI OnGUI - trying to increase performance by stepping out of...

Post by Interkarma »

That's an interesting reply DM! Thanks for adding to conversation.

I'd say agamer is using the Unity Profiler. It's very tightly integrated with the runtime and can give some great insight thanks to that coupling. But it's still a sample-based profiler, and I don't know enough about its inner workings to say if it experiences these problems, or how frequently.

I personally still like to fall back on using System.Diagnostics.Stopwatch to time execution for single-threaded methods. Then I can wrap the exact bits of code I want timing on and keep drilling down.

agamer
Posts: 8
Joined: Sat Jul 06, 2019 2:29 am

Re: DaggerfallUI OnGUI - trying to increase performance by stepping out of...

Post by agamer »

Thanks for the guidance, that is a bit to digest. The explanations offered were on point so thanks to both for taking the time. DigitalMonk - the vsync example you mentioned probably is at play here, as the hardware (platform?) is locked to 72 or 60hz, with an option to choose target framerate, although it may not be misleading as much because the time I'm seeing is 40-60%. Those numbers might be high enough to indicate a big enough problem above the timing issues you described. Where that problem is at still eludes me but only because I didn't get the time I wanted to tinker today. I did capture a profile sample of just the startup scene and it showed a similar result. I will tinker more and will definitely share anything interesting I find. Unity's base profiler likely is more the "sample" approach as InterKarma mentioned, or maybe defaults to that mode. There is also a deep profiler option available that I'm guessing might follow the "instrumented" approach mentioned and I will test using that as well once I have a better handle on the tools. I will also test timing using stopwatch because that is something I can play with in methods/routines and control a bit more and get good execution time and cpu time. After a little practice with this I should be able to produce something. Onward and upward to 60 (or 72) fps on the oculus go. I'm really eager to play on this old headset so I gotta make it work.

For the Oculus Go to hit 60/72 fps it needs something like
50-100 draw calls per frame
50,000-100,000 triangles or vertices per frame
...but in my experience these numbers are variable and conservative if handled correctly. Also when I tested with a few earlier DFU builds on the go, it seemed to run well enough and reach lower than the above numbers in some cases, even without performance optimizations and no mods.

Again thanks to both of you for taking the time to give feedback and guidance, very helpful!

User avatar
Hazelnut
Posts: 3016
Joined: Sat Aug 26, 2017 2:46 pm
Contact:

Re: DaggerfallUI OnGUI - trying to increase performance by stepping out of...

Post by Hazelnut »

FWIW the horse head animation rendering is done using onGUI()
See my mod code for examples of how to change various aspects of DFU: https://github.com/ajrb/dfunity-mods

User avatar
Interkarma
Posts: 7244
Joined: Sun Mar 22, 2015 1:51 am

Re: DaggerfallUI OnGUI - trying to increase performance by stepping out of...

Post by Interkarma »

Cheers Hazelnut. That's good info to add.

I believe agamer was only short-circuiting DaggerfallUI.OnGUI() though, and this shouldn't affect other Monobehaviour classes that also use OnGUI() for some work, e.g. TransportManager.OnGUI().

User avatar
carademono
Posts: 210
Joined: Sat Jul 11, 2020 3:20 pm

Re: DaggerfallUI OnGUI - trying to increase performance by stepping out of...

Post by carademono »

I have an Oculus Go and would looooooooove to playtest DFUnity on it, if you're at all interested in an extra pair of eyes. Daggerfall is much more fun than quarantine!

Post Reply