Difference between revisions of "Garbage Reduction"
(Eliminated untrue and misleading advice re: short lived variables.) |
(Refined singleton advice.) |
||
Line 37: | Line 37: | ||
However if you want a hard and fast rule, "don't use foreach" is pretty simple. | However if you want a hard and fast rule, "don't use foreach" is pretty simple. | ||
− | === | + | === Singletons === |
− | + | Singletons are often designed to survive the life of the program's execution. This long life means they may hold references to objects long after they are useful which can result in the objects never being released (a memory leak), surviving long enough that they have to be considered by the garbage collector in a more expensive generation (slowing GC over time), or deallocated after a similar set of objects has been allocated in another spot on the heap (memory fragmentation). It is therefore important to carefully evaluate the objects a singleton can reference. This can include more than the immediate attributes of the singleton, i.e. those attributes may hold references to other objects. | |
===remove "using System.Linq"=== | ===remove "using System.Linq"=== |
Revision as of 19:58, 14 June 2018
Some of this information may be incorrect, speculative or out of date. Unity provides an in-depth tutorial with more up to date and accurate information. As of version 1.4, Kerbal Space Program runs on Unity 2017.1, which, for example, reduces the concern about foreach loops (problematic for Unity versions before 5.5). All advice is situational and the largest source of garbage collection issues in most user made plugins will be lack of/poor design.
Contents
What is garbage, and why is it bad?
C# is a garbage-collected language, which means that the programmer doesn't have to worry about deleting variables when done with them; the system will do it automatically.
However, the way it does this is by freezing the system and then walking through the list of variables and removing the unused ones ("garbage" variables). This can cause stutters, and the stutters will be more frequent and longer the more garbage there is.
Measuring garbage production
MemGraph can show you how much garbage KSP is creating. It is not broken down by mod, so to test a specific mod you'll need a copy of KSP with only that mod installed.
What does Squad say about garbage?
Best practices to avoid creating garbage
avoid foreach
Replace "foreach" with "for".
Less garbage, but goes through the list backwards:
for (int i = <something>.Length - 1; i >= 0; --i)
One extra variable, but goes through the list forwards:
int count = <something>.Length; // (or .Count or whatever works for the object concerned) for (int i = 0; i < count; ++i)
If you're using Visual Studio instead of MonoDevelop, replacing foreach is not strictly necessary in some cases:
However if you want a hard and fast rule, "don't use foreach" is pretty simple.
Singletons
Singletons are often designed to survive the life of the program's execution. This long life means they may hold references to objects long after they are useful which can result in the objects never being released (a memory leak), surviving long enough that they have to be considered by the garbage collector in a more expensive generation (slowing GC over time), or deallocated after a similar set of objects has been allocated in another spot on the heap (memory fragmentation). It is therefore important to carefully evaluate the objects a singleton can reference. This can include more than the immediate attributes of the singleton, i.e. those attributes may hold references to other objects.
remove "using System.Linq"
Linq creates a lot of garbage. Don't use it.
don't loop through all Parts/Resources/whatever every frame
Looping through every part on the ship is expensive. Don't do this every frame, but instead get notified when the ship changes and then re-scan it. Same for resources, or anything else that you can cache and then get notified when you need to act.
List<Part> partsICareAbout = new List<Part>(); Start() { rescanMethod(); // run this at startup GameEvents.onVesselChange.Add(rescanMethod); // onVesselChange - switching between vessels with [ or ] keys GameEvents.onVesselStandardModification.Add(rescanMethod); // onVesselStandardModification collects various vessel events and fires them off with a single one. // Specifically - onPartAttach,onPartRemove,onPartCouple,onPartDie,onPartUndock,onVesselWasModified,onVesselPartCountChanged } public void rescanMethod(Vessel gameEventVessel=null) { // scan the ship for the parts you need, and save them in partsICareAbout }