[REQUEST] Official Support For Manual GC Calls In NW.js

  • This request is mainly about some changes that could further improve the general user experience with NWjs.

    The majority of advanced users require desktop games to do things on demand and not based on "automated" systems. I would like to request an update to the NW.js plugin and package.json files (manifest), which would make it possible to force the built-in Garbage Collector to unload unused audio or similar objects instantly on user demand.

    I'm sure that the automated garbage collector is considered to be "perfect" by the most web developers but coming from a native-tech background, my opinion still and will always stand: it's flawed and will always be flawed regardless of how many updates and tweaks it gets.

    Putting any personal bias aside, this request doesn't take GC away and would just add an option to trigger it on demand. This could be tremendously useful for larger games with for example: selfmade loading screens and would prevent any GC related "jank", that may occur on an active layout caused by automatic garbage collection.

    Requirements for

    Construct 2 implementation:

    • Forced replacement update of manifest files*
    • Always exposed GC by adding simple js-flag (Screenshot)
    • NW.js Plugin new action "Push Garbage Collector" which executes js: "global.gc();"[/code:3qcombfs]

    *I would suggest publishing a beta update announcing the upcoming changes so that users with customized manifest files can do a backup.

    Requirements for

    Construct 3 implementation:

    • Always exposed GC by adding simple js-flag (Screenshot)
    • NW.js Plugin new action "Push Garbage Collector" which executes js: "global.gc();"[/code:3qcombfs]
  • Do you have any actual problems that would be solved by this, or evidence that jank is actually caused by GC? I've never been a huge fan of garbage collectors but browser's modern GCs are pretty good and do generally slice work in to small (non-janking) updates and concurrent collection. I haven't seen GC obviously causing jank for some time now. Most jank issues seem to come down to some kind of system v-sync timing issue, and the last other cause I saw in the forum, was forcing synchronous texture loading during gameplay.

    Exposing this also has some downsides: modern browsers have multiple tiers of collection, ranging from nursery collection (with negligible performance overhead) to full heap collections (which can jank hard). The GC is designed to as far as possible only use the lower levels of GC and avoid expensive full heap collections, and even then if it has to, it tries to do it concurrently and in small time slices. The "gc()" command is a real sledgehammer that immediately hits the full heap collection. Also I'm not sure but it might even force it to be synchronous (no time slicing/concurrent work). Browser GCs are also generally pretty good at scheduling these only when it's needed, so if you force one ahead of time, chances are it's not needed and there's not much point doing the work. So, in fact, adding this could make jank problems worse, not better.

  • Do you have any actual problems that would be solved by this, or evidence that jank is actually caused by GC? I've never been a huge fan of garbage collectors but browser's modern GCs are pretty good and do generally slice work in to small (non-janking) updates and concurrent collection. I haven't seen GC obviously causing jank for some time now. Most jank issues seem to come down to some kind of system v-sync timing issue, and the last other cause I saw in the forum, was forcing synchronous texture loading during gameplay.

    That's indeed the case for the most jank reported on the forum, Vsynctester in my opinion the best proof for v-sync timing issues and jank but that's another topic for another day and I'm aware of synchronous texture loading during gameplay jank, that's why I proposed a new memory management system on the C3 ideas website.

    I've slightly modified an example that demonstrates force unloading. Please note that this is incredibly difficult to reproduce on systems with 8gb+ memory, however not impossible since I managed to reproduce it a couple of times myself.

    Download example & Steps to reproduce:

    • Launch example in NW.js (tested in v0.28.0)
    • Load stuff into memory by clicking "load all audio files into memory" button (about 1gb total)
    • Tell GC to unload stuff by clicking the button
    • Switch to the "game" layout by clicking the button on the top-right corner
    • Observe GC unloading memory "mid-game" causing major jank (this process happens at random, sometimes immediately, sometimes delayed)

    Repeating myself here but despite GC being considerably great for the most part, the main issue persists: control.

    I'm sure you know this already since you've worked on native software yourself but an important thing to software and game Dev's alike is to have control over memory usage. While having an unpredictable automated GC system like this in place can be an amazing thing, it doesn't always work out with every project and having an optional method to manually manage memory would be tremendously useful for those projects, regardless of them being a small minority in comparison to others that don't need it.

    The GC is designed to as far as possible only use the lower levels of GC and avoid expensive full heap collections, and even then if it has to, it tries to do it concurrently...

    My example proves this to be wrong. If executed correctly, you will be able to see that GC pretty much unloads everything at once, same as when it's being forced.

    Also I'm not sure but it might even force it to be synchronous (no time slicing/concurrent work). Browser GCs are also generally pretty good at scheduling these only when it's needed, so if you force one ahead of time, chances are it's not needed and there's not much point doing the work. So, in fact, adding this could make jank problems worse, not better.

    I've been told that this feature is exactly like pressing the "bin" icon in Dev-tools. Would you mind providing some sort of proof that it's indeed causing those problems? I'm using it in my project for a while now and I've never experienced any issues with jank getting worse or GC not working correctly after manually forcing it, even if it would cause GC to stop doing things automatically, I would consider that be a good thing and not necessarily a bad thing.

  • I don't think this quite qualifies as proof the jank is caused by GC. Could you try taking a performance profile over the time that causes jank? Press F12 to open dev tools in NW.js, and then start a recording in the Performance tab and try to capture the jank. If the performance profile measures the jank and actually tags the time period spent as some kind of GC, that would prove it. Until then, best not to jump to conclusions! I tried this myself but couldn't see any issue (over 30 seconds it spent <10ms in GC), but I do have a lot of memory on this system. I also tried pressing the "collect garbage" button in dev tools while the performance profile was recording, and again no significant GC time was measured.

    Even if it is GC, I think it would be better to file a Chrome bug to optimise this aspect of the GC. It looks like it only needs to unload 5 tracks, and freeing memory should essentially be a matter of tagging some memory regions as free instead of in use, i.e. very little work. So I'm not sure what it could be doing that would take any noticable amount of time. If there is a problem and it gets fixed, then it also improves all games everywhere else the Chromium engine is used, e.g. in the Chrome browser, all Cordova games on Android, etc. So this would improve all platforms, which is a much better end result, rather than providing a hack to work around a GC performance issue in just one variant of the Chromium engine.

  • I don't think this quite qualifies as proof the jank is caused by GC. Could you try taking a performance profile over the time that causes jank? Press F12 to open dev tools in NW.js, and then start a recording in the Performance tab and try to capture the jank. If the performance profile measures the jank and actually tags the time period spent as some kind of GC, that would prove it. Until then, best not to jump to conclusions! I tried this myself but couldn't see any issue (over 30 seconds it spent <10ms in GC), but I do have a lot of memory on this system. I also tried pressing the "collect garbage" button in dev tools while the performance profile was recording, and again no significant GC time was measured.

    I could reproduce "jank" on two different tests, here are the results:

    Full version (recording after memory loaded): Download

    Cut version (recording after layout switch): Download

    Even if it is GC, I think it would be better to file a Chrome bug to optimise this aspect of the GC. It looks like it only needs to unload 5 tracks, and freeing memory should essentially be a matter of tagging some memory regions as free instead of in use, i.e. very little work. So I'm not sure what it could be doing that would take any noticable amount of time. If there is a problem and it gets fixed, then it also improves all games everywhere else the Chromium engine is used, e.g. in the Chrome browser, all Cordova games on Android, etc. So this would improve all platforms, which is a much better end result, rather than providing a hack to work around a GC performance issue in just one variant of the Chromium engine.

    This is where we have to find a compromise. I don't believe that any fix provided by the Chromium Team (given they do something about it at all) will fix this. Even if GC would do this in smaller chunks to avoid expensive full heap collections, it would probably just result in multiple smaller "janks" and make it worse.

    I also have no clue how I would report this to them with next to no knowledge about their whole GC system. I could only provide them vague assumption based conclusions like I did here, which they would probably ignore and won't bother looking into.

  • Try Construct 3

    Develop games in your browser. Powerful, performant & highly capable.

    Try Now Construct 3 users don't see these ads
  • Only the "full" version points at GC (labelled "DOM GC (complete sweep)" - not sure why it's doing that...). The "cut" version just shows a long tick but unfortunately doesn't seem to indicate why that is.

    You can definitely file this as an issue with Chrome. Nobody needs to have any knowledge of the internals to file a bug, just make a web repro, attach the trace you recorded, and say the issue is it spends too long in "DOM GC (complete sweep)". I've seen them fix similar issues in the past too, no need to assume that it's impossible.

  • Only the "full" version points at GC (labelled "DOM GC (complete sweep)" - not sure why it's doing that...). The "cut" version just shows a long tick but unfortunately doesn't seem to indicate why that is.

    You can definitely file this as an issue with Chrome. Nobody needs to have any knowledge of the internals to file a bug, just make a web repro, attach the trace you recorded, and say the issue is it spends too long in "DOM GC (complete sweep)". I've seen them fix similar issues in the past too, no need to assume that it's impossible.

    Great can't wait to report this over and over again...

    What about my request towards manual GC, would you be interested in implementing it?

  • I'd prefer to see how the bug reports go first. We have to support a range of platforms, not just NW.js, so I'm most interested in the broadest fix possible. Even if we added this to NW.js, if there really is an issue with the GC performance, it'd only be a matter of time before it came up again with Chrome or Cordova apps on Android, so this seems to be the best approach to start with. Also if it doesn't happen in other browsers, that is good evidence it's fixable.

  • I'd prefer to see how the bug reports go first. We have to support a range of platforms, not just NW.js, so I'm most interested in the broadest fix possible. Even if we added this to NW.js, if there really is an issue with the GC performance, it'd only be a matter of time before it came up again with Chrome or Cordova apps on Android, so this seems to be the best approach to start with. Also if it doesn't happen in other browsers, that is good evidence it's fixable.

    I'm alright with this approach, I've reported the issue. (Link)

    Hope that everything is alright with my report and that they'll respond soon.

    Thanks for your time and I guess the rest will be done over there!

  • Thanks, I'm following that issue and will answer any engine details if they come up.

Jump to:
Active Users
There are 1 visitors browsing this topic (0 users and 1 guests)