[???] GC can't keep up while the game is paused

Forum rules
Please don't bump threads here if you have a problem - it will often be forgotten about if you do. Instead, make a new thread here.

Post a reply

Smilies
:D :) :( :o :shock: :? 8-) :lol: :x :P :oops: :cry: :evil: :twisted: :roll: :wink: :geek: :ugeek: :!: :?: :idea: :arrow: :| :mrgreen: :3: :wub: >:( :blergh:
View more smilies

BBCode is OFF
Smilies are ON

Topic review
   

Expand view Topic review: [???] GC can't keep up while the game is paused

Re: [???] GC can't keep up while the game is paused

by randi » Wed Jan 12, 2022 8:22 am

It's likely just the retained console output.

I should probably also point at that, as counterintuitive as it might seem, the point of the garbage collector is not to quickly dispose of the garbage. The point is to be as unobtrusive as possible so you don't get big frame time spikes every time it takes out the garbage, and all that matters in that regard is that it can get rid of it faster than it's being generated. It's much better than before now. (Which is easy because it was completely broken.) But I also know it can be further improved since it still has some difficulty with rapidly escalating garbage and eventually gives up and spikes at the end to finish it; I will have to give it more thought to decide how best to deal with that.

Re: [???] GC can't keep up while the game is paused

by Player701 » Wed Jan 12, 2022 1:18 am

And yet, removing this call seems to fix the issue for me, confirmed both by stat gc output and by memory usage in Task Manager. I haven't run a relatively long testing session yet but the difference is very much evident from the outset. You can test it yourself by commenting out line 173 in classes/wl/framework/caching/WL_DrawStackCacheWrapper.zs.

Re: [???] GC can't keep up while the game is paused

by Graf Zahl » Wed Jan 12, 2022 1:11 am

Console.Printf should be harmless. It doesn't do any persistent internal allocations that may stick around.

Re: [???] GC can't keep up while the game is paused

by Player701 » Tue Jan 11, 2022 11:38 pm

Wow. Didn't know that would even be possible. Thanks, I'll check it out.
randi wrote:(Also, in case you didn't know, the inventory bar isn't centered at ultrawide resolutions.)
This may or may not be intended behavior, not sure because it's been a while since I touched the actual layout code. Thank you for telling me.

UPD: Funny story, this seems to be caused by Console.Printf that I put there for debugging purposes. It is called when a certain array, which is used for caching, is resized - and it happens very often during scrolling because the cache gets invalidated constantly. Commenting this call out seems to avert the crisis, at least with the new build. Could it be a case of "don't do that" because there really was a shit-ton of print calls there, or is this actually another bug?

Re: [???] GC can't keep up while the game is paused

by randi » Tue Jan 11, 2022 9:34 pm

It looks like you have a memory leak related to the scrolling text. This isn't a case of the GC not keeping up. Do gc full a few times, and you'll see that the amount of used memory is rising.

(Also, in case you didn't know, the inventory bar isn't centered at ultrawide resolutions.)

Re: [???] GC can't keep up while the game is paused

by Player701 » Tue Jan 11, 2022 8:16 am

This particular scenario is triggered when the game is not paused, but I'm pretty sure it's more or less the same issue. Whenever there is a scrolling animation active in my UI, there is a constant allocation of objects that store the position and size of the content that gets scrolled, so it is not possible to cache them. You can test it yourself with the PK3 here. Steps to reproduce:
  1. Load up the Heretic or Hexen IWAD
  2. Go to any map
  3. Issue console command give artifacts
  4. If the HUD is not visible, press "-" or "=" until it appears
Notice the title of the selected item above its icon in the inventory bar, scrolling back and forth. As long as it is visible and scrolling, the memory usage is constantly increasing. Pausing the game or disabling the HUD stops the animation, and the memory usage then stabilizes (although it does not seem to go down immediately, probably kept in reserve for new allocations). The animation speed is currently dependent on the frame rate (something else I wanted to address but haven't gotten to yet) but even at 60 FPS it is still fast enough for the problem to manifest.

Re: [???] GC can't keep up while the game is paused

by Graf Zahl » Tue Jan 11, 2022 7:56 am

Using the version I downloaded when testing it the GC managed to keep memory in check. It had to fight for sure, but it always entered the pause stage again in-between and overall allocations remained constant. Yes, that's the one doing 4000+ allocations per frame.

Re: [???] GC can't keep up while the game is paused

by randi » Tue Jan 11, 2022 7:55 am

Please provide steps for reproducing. The GC should be able to handle anything without you having to adjust your code.

Re: [???] GC can't keep up while the game is paused

by Player701 » Tue Jan 11, 2022 7:35 am

Hmm. I don't see much difference between the latest git build g4.8pre-114-ga1d0d2727 and the release version (4.7.1). There still exists a certain edge case in my mod which I haven't been able to optimize so far; testing results in constantly increasing memory usage in both versions. Guess I'll eventually have to resort to using structs after all...

Re: [???] GC can't keep up while the game is paused

by Graf Zahl » Tue Jan 11, 2022 7:12 am

Randi's PR finally fixes this. :)

Re: [???] GC can't keep up while the game is paused

by Player701 » Thu Nov 25, 2021 8:04 am

So it seems that my initial optimizations were not enough, because in several testing sessions, while the game was paused, the memory usage simply went up continously and never stabilized or went down. Then I went ahead and implemented a cache for the draw stack data in my UI code via an array of history entires containing previous input and output data. The idea is that if the sequence of push/pop operations and their input data is the same at each draw pass, then the calculations that result in new objects being created can be skipped, and cached output can be used instead. It seems that this finally helped, and the memory usage in menu/pause mode now either doesn't increase at all, or goes up only a little and then stops.

This still needs a lot of testing before I can release an update though, and I'm sure there are edge cases where this caching mechanism won't work, e.g. if a continuous scrolling animation is in effect. This could be countered by disabling all HUD animations while the game is paused, if only there were a way to detect this in ZScript. I've found a feature suggestion thread but it's marked "duplicate" for some reason, although I couldn't find anything else related to this topic. It doesn't seem to be implemented as of now, but if someone else knows more about this, please tell me. Thank you very much.

Anyway, I wish to thank Graf for his earlier input in this thread, although I would still like to see "proper" handling of structs in ZScript someday... I guess we can all agree that using heap-based objects for such things is not a very good idea, as that was what caused this GC-related fuckup in the first place.

Re: [???] GC can't keep up while the game is paused

by Player701 » Wed Nov 24, 2021 9:22 am

I'm not sure but I don't think I actually saw the memory usage go down while paused, only after unpausing. I will test some more though, and report tomorrow with more detailed results.

Re: [???] GC can't keep up while the game is paused

by Graf Zahl » Wed Nov 24, 2021 9:03 am

That behavior is perfectly normal for a garbage collector. Its entire point is to accumulate some data before actually collecting it.
As long as the memory gets regularly collected and freed, it only tells us that the GC is doing its job.

Re: [???] GC can't keep up while the game is paused

by Player701 » Wed Nov 24, 2021 7:26 am

I've implemented some heavy optimizations in my mod, and now the memory usage does not seem to actively increase at all during gameplay. However, when the menu is opened, it still appears to go up about 3-4 MB every second. I don't know what else there is left to optimize, the only remaining thing is the stack of drawing operations where each frame stores rectangles signifying the borders of the current drawing area as well as its padding. It is a bit difficult to implement any caching there, especially considering the dynamic nature of the data structure, so there are still new objects that get created on every draw pass.

Is it certain that the GC process cannot be improved any further beyond its current implementation? I can also post the current test build of my mod if the devs would like to profile it and compare the results with the previous version. I of course cannot be 100% sure that I haven't missed anything during the rewrite, so maybe there is still some way to cut down on the number of allocations even further.

Re: [???] GC can't keep up while the game is paused

by Player701 » Tue Oct 05, 2021 8:58 am

Graf Zahl wrote:You are making comparisons with big professional languages.
Perhaps I am, and it is certainly my fault because I've worked quite a lot with some of them. But what I really want is to write clean code that is relatively easy to maintain, and having out parameters all over the place certainly does not contribute to maintainability. It would work the same as if structs were actually passed by value except that it would look much uglier. I guess if all else fails, I will have to settle for this option when the crash is fixed.

Top