Skip to content

Commit

Permalink
New KSP performance patch : IMGUIOptimization [KSP 1.8.0 - 1.12.5], e…
Browse files Browse the repository at this point in the history
…liminate structural GC allocations and reduce performance overhead of OnGUI() methods. Can provide significant performance gains when having many mods using IMGUI heavily.
  • Loading branch information
gotmachine committed Dec 6, 2023
1 parent 0a1d385 commit 1c2d0ef
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 0 deletions.
4 changes: 4 additions & 0 deletions GameData/KSPCommunityFixes/Settings.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,10 @@ KSP_COMMUNITY_FIXES
// (and other cases), causing a significant perf hit when there are many kerbals in the vessel.
DisableHiddenPortraits = true
// Eliminate structural GC allocations and reduce performance overhead of OnGUI() methods.
// Can provide significant performance gains when having many mods using IMGUI heavily.
IMGUIOptimization = true
// ##########################
// Modding
// ##########################
Expand Down
11 changes: 11 additions & 0 deletions KSPCommunityFixes/KSPCommunityFixes.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,16 @@
<DoNotPublicize Include="Assembly-CSharp:BaseField`1.OnValueModified" />
<DoNotPublicize Include="Assembly-CSharp:SaveUpgradePipeline.SaveUpgradePipeline.OnSetCfgNodeVersion" />
<Publicize Include="UnityEngine.CoreModule:UnityEngine.Object.m_CachedPtr" />
<Publicize Include="UnityEngine.IMGUIModule:UnityEngine.GUILayoutUtility" />
<Publicize Include="UnityEngine.IMGUIModule:UnityEngine.GUILayoutUtility.current" />
<Publicize Include="UnityEngine.IMGUIModule:UnityEngine.GUILayoutUtility.Begin" />
<Publicize Include="UnityEngine.IMGUIModule:UnityEngine.GUILayoutUtility.SelectIDList" />
<Publicize Include="UnityEngine.IMGUIModule:UnityEngine.GUILayoutUtility+LayoutCache" />
<Publicize Include="UnityEngine.IMGUIModule:UnityEngine.GUILayoutUtility+LayoutCache.topLevel" />
<Publicize Include="UnityEngine.IMGUIModule:UnityEngine.GUILayoutUtility+LayoutCache.layoutGroups" />
<Publicize Include="UnityEngine.IMGUIModule:UnityEngine.GUILayoutUtility+LayoutCache.windows" />
<Publicize Include="UnityEngine.IMGUIModule:UnityEngine.GUILayoutEntry" />
<Publicize Include="UnityEngine.IMGUIModule:UnityEngine.GUILayoutGroup" />
<Publicize Include="mscorlib:System.IO.MonoIO" />
<Publicize Include="mscorlib:System.IO.MonoIOError" />
<Publicize Include="mscorlib:System.IO.MonoIOStat" />
Expand Down Expand Up @@ -130,6 +140,7 @@
<Compile Include="Performance\DisableMapUpdateInFlight.cs" />
<Compile Include="Performance\DragCubeGeneration.cs" />
<Compile Include="Performance\FastLoader.cs" />
<Compile Include="Performance\IMGUIOptimization.cs" />
<Compile Include="Performance\LocalizerPerf.cs" />
<Compile Include="Performance\MemoryLeaks.cs" />
<Compile Include="BugFixes\RescaledRoboticParts.cs" />
Expand Down
53 changes: 53 additions & 0 deletions KSPCommunityFixes/Performance/IMGUIOptimization.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// Copypasted from https://forum.unity.com/threads/garbage-collector-spikes-because-of-gui.60217/page-2#post-6317280
// Basically, every OnGUI() method implies a call to GUILayout.Repaint(), itself calling GUILayoutUtility.Begin(),
// which does a bunch of allocations (even if the OnGUI() method does nothing). This replacement method reuse the
// existing objects instead of instantiating new ones, which both reduce GC pressure (about 0.36 KB/frame per OnGUI()
// method) and slightly reduce CPU usage. This can sum up to a significant improvement, especially for plugins
// having an OnGUI() method on PartModules. An example of such a plugin is PAWS, which spam a such a partmodule on
// every part. In that (worst case) scenario, with a stock dynawing (~130 parts), this patch reduce GC pressure by
// 52 KB/frame and reduce CPU time by about 0.3ms.

using System;
using System.Collections.Generic;
using HarmonyLib;
using UnityEngine;

namespace KSPCommunityFixes.Performance
{
class IMGUIOptimization : BasePatch
{
protected override Version VersionMin => new Version(1, 8, 0);

protected override void ApplyPatches(List<PatchInfo> patches)
{
patches.Add(new PatchInfo(
PatchMethodType.Prefix,
AccessTools.Method(typeof(GUILayoutUtility), nameof(GUILayoutUtility.Begin)),
this));
}

static bool GUILayoutUtility_Begin_Prefix(int instanceID)
{
GUILayoutUtility.LayoutCache layoutCache = GUILayoutUtility.SelectIDList(instanceID, false);
if (Event.current.type == EventType.Layout)
{
if (layoutCache.topLevel == null)
layoutCache.topLevel = new GUILayoutGroup();
if (layoutCache.windows == null)
layoutCache.windows = new GUILayoutGroup();

layoutCache.topLevel.entries.Clear();
layoutCache.windows.entries.Clear();

GUILayoutUtility.current.topLevel = layoutCache.topLevel;
GUILayoutUtility.current.layoutGroups.Clear();
GUILayoutUtility.current.layoutGroups.Push(GUILayoutUtility.current.topLevel);
return false;
}
GUILayoutUtility.current.topLevel = layoutCache.topLevel;
GUILayoutUtility.current.layoutGroups = layoutCache.layoutGroups;
GUILayoutUtility.current.windows = layoutCache.windows;
return false;
}
}
}
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ User options are available from the "ESC" in-game settings menu :<br/><img src="
- [**DragCubeGeneration**](https://github.com/KSPModdingLibs/KSPCommunityFixes/pull/139) [KSP 1.12.0 - 1.12.5]<br/> Faster and more reliable implementation of drag cube generation. Improves overall loading times (both game load and scene/vessel/ship load times), prevent occasional lag spikes (in the editor mostly) and fix some issues causing incorrect drag cubes to be generated (notable examples are the stock inflatable heat shield, the 1.25m and 2.5m nose cones and the Mainsail shroud). Note that by design, this patch results in a small deviation from the stock behavior for buyoancy, aerodynamics and thermodynamics, as the generated drag cubes will be slightly different.
- **LocalizerPerf** [KSP 1.8.0 - 1.12.5]<br/>Faster and minimal-allocation replacements for the `Localizer.Format()` methods, can provide significant speedup for GUI-heavy mods using localized strings.
- [**DisableHiddenPortraits**](https://github.com/KSPModdingLibs/KSPCommunityFixes/issues/84) [KSP 1.8.0 - 1.12.5]<br/>Prevent non-visible crew portraits from being rendered after a switch back from the map view (and other cases), causing a significant perf hit when there are many kerbals in the vessel.
- **IMGUIOptimization** [KSP 1.8.0 - 1.12.5]<br/>Eliminate structural GC allocations and reduce performance overhead of OnGUI() methods. Can provide significant performance gains when having many mods using IMGUI heavily.

#### API and modding tools
- **MultipleModuleInPartAPI** [KSP 1.8.0 - 1.12.5]<br/>This API allow other plugins to implement PartModules that can exist in multiple occurrence in a single part and won't suffer "module indexing mismatch" persistent data losses following part configuration changes. [See documentation on the wiki](https://github.com/KSPModdingLibs/KSPCommunityFixes/wiki/MultipleModuleInPartAPI).
Expand Down Expand Up @@ -183,6 +184,7 @@ If doing so in the `Debug` configuration and if your KSP install is modified to
- New KSP bugfix : [**ModuleAnimateGenericCrewModSpawnIVA**](https://github.com/KSPModdingLibs/KSPCommunityFixes/issues/169) [KSP 1.8.0 - 1.12.5], fix IVA & crew portrait not spawning/despawning when ModuleAnimateGeneric is used to change the part crew capacity. Notably affect the stock inflatable airlock.
- New KSP bugfix : [**PropellantFlowDescription**](https://github.com/KSPModdingLibs/KSPCommunityFixes/pull/165) [KSP 1.8.0 - KSP 1.12.5], fix printing the resource's base flow mode instead of the (potentially overridden) propellant's flow mode when printing propellants in an engine's info panel in the Part Tooltip.
- Fix KSP [issue #153](https://github.com/KSPModdingLibs/KSPCommunityFixes/issues/153), prevent flight related events to be registered from ModuleScienceExperiment on the prefabs and in other scenes. This was added to the **MemoryLeaks** patch, since that patch already handle a bunch of GameEvents related issues/leaks.
- New KSP performance patch : **IMGUIOptimization** [KSP 1.8.0 - 1.12.5], eliminate structural GC allocations and reduce performance overhead of OnGUI() methods. Can provide significant performance gains when having many mods using IMGUI heavily.
- **ConfigNodePerf** : fixed [issue #167](https://github.com/KSPModdingLibs/KSPCommunityFixes/issues/167), incorrect parsing of config files using `cr` only (old Mac style) line endings.

##### 1.31.1
Expand Down

0 comments on commit 1c2d0ef

Please sign in to comment.