Jump to content

Vessel Modules seem to run for inactive vessels now...


Recommended Posts

I've been playing around with the profiler to see why my modded KSP install is stuttering, and noticed that I get more than 500 calls per frame to OnGUI() - each creating a little bit (384 bytes) of garbage. After a little digging I could track this down to vessel modules running on vessels that are not loaded (including asteroids).

This of course made me curious about what's going on here, so I made a test mod that does nothing but print the vessels on which it is currently running:

using UnityEngine;
using KSP;

namespace Testmod
{
    public class Testmod : VesselModule
    {
       
        void Update()
        {
            Debug.Log("Testmod running for vessel: "+ GetComponent<Vessel>());
            this.enabled = false;
        }
    }
}

Sure enough, after adding it to a fresh KSP installation, starting a new Sandbox game, and launching a craft, the log started showing interesting things:

(Filename: /home/builduser/buildslave/unity/build/artifacts/generated/common/runtime/UnityEngineDebugBindings.gen.cpp Line: 42)

Testmod running for vessel: mk1pod (Vessel)
 
(Filename: /home/builduser/buildslave/unity/build/artifacts/generated/common/runtime/UnityEngineDebugBindings.gen.cpp Line: 42)

Testmod running for vessel: Ast. HSJ-227 (unloaded) (Vessel)
 
(Filename: /home/builduser/buildslave/unity/build/artifacts/generated/common/runtime/UnityEngineDebugBindings.gen.cpp Line: 42)

Testmod running for vessel: Ast. CMP-717 (unloaded) (Vessel)

But this was not all. I would have expected the vessel module to disable itself after one frame, but the log output went on, and on, and on... Obviously KSP keeps re-enabling all vessel modules every frame, so even disabling those beasts is not an option.

 

Long story short: I'm pretty certain that (at least with KSP 1.2.2) vessel modules are running for all vessels and cannot be disabled easily. One has to make sure not to place any code that causes garbage or heavy load into those classes, especially bad are functions that cause garbage whenever they are being called, even if they return immediately, like OnGUI().

Link to comment
Share on other sites

2 hours ago, soulsource said:

I've been playing around with the profiler to see why my modded KSP install is stuttering, and noticed that I get more than 500 calls per frame to OnGUI() - each creating a little bit (384 bytes) of garbage. After a little digging I could track this down to vessel modules running on vessels that are not loaded (including asteroids).

This of course made me curious about what's going on here, so I made a test mod that does nothing but print the vessels on which it is currently running:


using UnityEngine;
using KSP;

namespace Testmod
{
    public class Testmod : VesselModule
    {
       
        void Update()
        {
            Debug.Log("Testmod running for vessel: "+ GetComponent<Vessel>());
            this.enabled = false;
        }
    }
}

Sure enough, after adding it to a fresh KSP installation, starting a new Sandbox game, and launching a craft, the log started showing interesting things:


(Filename: /home/builduser/buildslave/unity/build/artifacts/generated/common/runtime/UnityEngineDebugBindings.gen.cpp Line: 42)

Testmod running for vessel: mk1pod (Vessel)
 
(Filename: /home/builduser/buildslave/unity/build/artifacts/generated/common/runtime/UnityEngineDebugBindings.gen.cpp Line: 42)

Testmod running for vessel: Ast. HSJ-227 (unloaded) (Vessel)
 
(Filename: /home/builduser/buildslave/unity/build/artifacts/generated/common/runtime/UnityEngineDebugBindings.gen.cpp Line: 42)

Testmod running for vessel: Ast. CMP-717 (unloaded) (Vessel)

But this was not all. I would have expected the vessel module to disable itself after one frame, but the log output went on, and on, and on... Obviously KSP keeps re-enabling all vessel modules every frame, so even disabling those beasts is not an option.

 

Long story short: I'm pretty certain that (at least with KSP 1.2.2) vessel modules are running for all vessels and cannot be disabled easily. One has to make sure not to place any code that causes garbage or heavy load into those classes, especially bad are functions that cause garbage whenever they are being called, even if they return immediately, like OnGUI().

As a mod user experiencing stutter, what can I do to prevent OnGui from having this effect?

How do I even identify which mods use this function?

Link to comment
Share on other sites

As a pure user, I'm afraid there is not much one can do, except to wait for mod authors to provide updates....

If you are willing to code a bit, you can of course work around the issue yourself, once you know which mod is causing it. If you are motivated to do this, the developers surely will be happy to accept pull requests for fixes on GitHub.

The way I found out which mods cause the issue was by profiling KSP with mods installed, and checking where all the garbage came from. If you are lucky the mod causing your issues is doing this not via OnGUI(), but via some of the numerous *Update() methods. In that case, the Unity Profiler will tell you which class is causing the problem, and which function, so it's rather easy to find. If you have problems caused by too many OnGUI() calls, the situation is different. Sadly, I did not (yet) manage to get more information out of the profiler than how much garbage all OnGUI() calls together are causing, and how many OnGUI() calls there are in total, and figuring out which mods caused them was then a matter of uninstalling them one by one...

Edited by soulsource
Link to comment
Share on other sites

This is concerning, I'm currently working on converting all my mods over to use VesselModule as it offers me some nice options.

Now I'm also moving to the new GUI when I do this so I won't be calling OnGUI, but is there any trick for determining code that will cause garbage? I don't want to get everything finished and the profiler show me I'm spilling memory everywhere.

D.

Link to comment
Share on other sites

On 26.2.2017 at 4:36 AM, Diazo said:

is there any trick for determining code that will cause garbage?

There are some tutorials on the internet, on which things to avoid in code, the rest comes with experience. A good starting point is the Unity Documentation about Memory Management, and the tutorial on Optimizing Garbage Collection in Unity Games.

In principle all sources for garbage are some kind of object creation, but many of them are not obvious, or happen under Unity's hood. Examples for non-obvious sources of garbage (apart from OnGUI() calls) are string concatenation, foreach loops, most LINQ-functions, and delegate creation.

Edit (2017-04-09): There is also a Visual Studio extension available through NuGet, which can highlight heap allocations in the code. Sadly I don't remember how it was called...

Edit (2017-04-10): I mixed up something. The tool I was thinking of was actually an extension to ReSharper, and it's called Heap Allocations Viewer.

Edited by soulsource
Link to comment
Share on other sites

First, yes they do. It was one of the documented feature of 1.2

As for the OnGUI they memory show up either under GUI.Repaint for those who do straight GUI.xxxx call or under the sub category GUI.CallWindowDelegate for those that uses GUILayout.Window.

Here is a screenshot of MJ uses with the profiling code enabled.

If you do not want OnGUI to be called from a VesselModule then you need to not add it (or disable the object but you stop the whole module from running). KSPAddon is a better choice than VesselModule for addon GUI, with VesselModule you could end up with 2 GUI overlapping when you have 2 ship nearby.

auzw7hy.png

Link to comment
Share on other sites

  • 2 weeks later...
On 2/25/2017 at 6:57 PM, soulsource said:

Long story short: I'm pretty certain that (at least with KSP 1.2.2) vessel modules are running for all vessels and cannot be disabled easily.

I notice that you can override 'GetActivation', but I don't think it makes any difference. As far as I can tell all vessels get a node in the persistence file to represent the vessel module as well. Should I consider those nodes negligible bloat, or is it best to stay clear of vessel modules for 'everyday vessel tracking'?

Sarbian mentioned "disable the object"; how would I do that?

Link to comment
Share on other sites

I'm just going to add a if(flightglobals.ActiveVessel == vesselmodule.vessel) check at the start of my logic and call it good enough.

That way the VesselModule only "runs" when it's attached to the focus vessel.

Alternatively, you can check against the OffRails state for VesselModules that you want to run on vessels that are loaded and within physics range.

Note you need to minimized the usage of the built-in Unity methods though, those still run every frame and you don't want to call them if you don't need to.

Compared to everything else running, a single IF statement isn't going to matter in terms of load.

D.

Link to comment
Share on other sites

8 hours ago, Rodhern said:

I notice that you can override 'GetActivation', but I don't think it makes any difference. As far as I can tell all vessels get a node in the persistence file to represent the vessel module as well. Should I consider those nodes negligible bloat, or is it best to stay clear of vessel modules for 'everyday vessel tracking'?

Sarbian mentioned "disable the object"; how would I do that?

 

If you start disabling stuff that is meant to run then you will start breaking stock and modded game. For example the whole comm network requires the vessel module to run for all vessels.

Link to comment
Share on other sites

  • 4 weeks later...
This thread is quite old. Please consider starting a new thread rather than reviving this one.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...