Skip to content

Commit

Permalink
- Bumped version to 1.21
Browse files Browse the repository at this point in the history
- New performance / KSP bugfix patch : [PQSCoroutineLeak](#85) (issue discovered by @Gameslinx)
- Fixed the ToolbarShowHide patch partially failing due to an ambigious match exception when searching the no args `ApplicationLauncher.ShouldItHide()` method overload.
  • Loading branch information
gotmachine committed Aug 21, 2022
1 parent af1dfc5 commit e663e18
Show file tree
Hide file tree
Showing 6 changed files with 141 additions and 2 deletions.
2 changes: 1 addition & 1 deletion GameData/KSPCommunityFixes/KSPCommunityFixes.version
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"NAME": "KSPCommunityFixes",
"URL": "https://raw.githubusercontent.com/KSPModdingLibs/KSPCommunityFixes/master/GameData/KSPCommunityFixes/KSPCommunityFixes.version",
"DOWNLOAD": "https://github.com/KSPModdingLibs/KSPCommunityFixes/releases",
"VERSION": {"MAJOR": 1, "MINOR": 20, "PATCH": 4, "BUILD": 0},
"VERSION": {"MAJOR": 1, "MINOR": 21, "PATCH": 0, "BUILD": 0},
"KSP_VERSION": {"MAJOR": 1, "MINOR": 12, "PATCH": 3},
"KSP_VERSION_MIN": {"MAJOR": 1, "MINOR": 8, "PATCH": 0},
"KSP_VERSION_MAX": {"MAJOR": 1, "MINOR": 12, "PATCH": 3}
Expand Down
4 changes: 4 additions & 0 deletions GameData/KSPCommunityFixes/Settings.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,10 @@ KSP_COMMUNITY_FIXES
// when moving around near a body surface
PQSUpdateNoMemoryAlloc = true

// Prevent KSP from spawning multiple PQS update coroutines for the same PQS after scene switches and
// and on other occasions, wasting a ton of CPU processing time.
PQSCoroutineLeak = true

// Remove unused ProgressTracking update handlers. Provides a very noticeable performance uplift in
// career games having a large amount of celestial bodies and/or vessels.
ProgressTrackingSpeedBoost = true
Expand Down
1 change: 1 addition & 0 deletions KSPCommunityFixes/KSPCommunityFixes.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@
<Compile Include="Modding\OnSymmetryFieldChanged.cs" />
<Compile Include="Modding\ReflectionTypeLoadExceptionHandler.cs" />
<Compile Include="Performance\FewerSaves.cs" />
<Compile Include="Performance\PQSCoroutineLeak.cs" />
<Compile Include="Performance\PQSUpdateNoMemoryAlloc.cs" />
<Compile Include="Performance\ProgressTrackingSpeedBoost.cs" />
<Compile Include="QoL\AutostrutActions.cs" />
Expand Down
129 changes: 129 additions & 0 deletions KSPCommunityFixes/Performance/PQSCoroutineLeak.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
// See https://github.com/KSPModdingLibs/KSPCommunityFixes/issues/85

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

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

protected override void ApplyPatches(List<PatchInfo> patches)
{
patches.Add(new PatchInfo(
PatchMethodType.Transpiler,
AccessTools.Method(typeof(PQS), nameof(PQS.StartSphere)),
this));

patches.Add(new PatchInfo(
PatchMethodType.Transpiler,
AccessTools.Method(typeof(PQS), nameof(PQS.ResetAndWait)),
this));
}

// StartCoroutine(UpdateSphere());
//IL_0391: ldarg.0
//IL_0392: ldarg.0
//IL_0393: call instance class [mscorlib] System.Collections.IEnumerator PQS::UpdateSphere()
//IL_0398: dup
//IL_0399: pop
//IL_039a: call instance class [UnityEngine.CoreModule] UnityEngine.Coroutine[UnityEngine.CoreModule] UnityEngine.MonoBehaviour::StartCoroutine(class [mscorlib] System.Collections.IEnumerator)
//IL_039f: dup
//IL_03a0: pop

static IEnumerable<CodeInstruction> PQS_StartSphere_Transpiler(IEnumerable<CodeInstruction> instructions)
{
MethodInfo m_UpdateSphere = AccessTools.Method(typeof(PQS), nameof(PQS.UpdateSphere));
MethodInfo m_StartCoroutine_String = AccessTools.Method(typeof(MonoBehaviour), nameof(MonoBehaviour.StartCoroutine), new Type[] {typeof(string)});
MethodInfo m_StartCoroutine_IEnumerator = AccessTools.Method(typeof(MonoBehaviour), nameof(MonoBehaviour.StartCoroutine), new Type[] {typeof(IEnumerator)});
MethodInfo m_StopCoroutine_String = AccessTools.Method(typeof(MonoBehaviour), nameof(MonoBehaviour.StopCoroutine), new Type[] { typeof(string) });

List<CodeInstruction> code = new List<CodeInstruction>(instructions);

for (int i = code.Count - 1; i >= 0; i--)
{
if (code[i].opcode == OpCodes.Call && ReferenceEquals(code[i].operand, m_StartCoroutine_IEnumerator))
{
code[i].operand = m_StartCoroutine_String;
int j;
bool found = false;
for (j = i - 1; j >= i - 4; j--)
{
if (code[j].opcode == OpCodes.Call && ReferenceEquals(code[j].operand, m_UpdateSphere))
{
code[j].opcode = OpCodes.Ldstr;
code[j].operand = nameof(PQS.UpdateSphere);
found = true;
break;
}
}

if (!found)
throw new Exception("PQS.StartSphere transpiler patch failed, UpdateSphere() call not found");

if (code[j - 1].opcode == OpCodes.Ldarg_0 && code[j - 2].opcode == OpCodes.Ldarg_0)
{
int k = j - 1;
code.Insert(k, new CodeInstruction(OpCodes.Ldstr, nameof(PQS.UpdateSphere)));
code.Insert(k + 1, new CodeInstruction(OpCodes.Call, m_StopCoroutine_String));
}
else
{
throw new Exception("PQS.StartSphere transpiler patch failed, unexpected IL pattern");
}

break;
}
}

return code;
}

static IEnumerable<CodeInstruction> PQS_ResetAndWait_Transpiler(IEnumerable<CodeInstruction> instructions)
{
MethodInfo m_UpdateSphere = AccessTools.Method(typeof(PQS), nameof(PQS.ResetAndWaitCoroutine));
MethodInfo m_StartCoroutine_String = AccessTools.Method(typeof(MonoBehaviour), nameof(MonoBehaviour.StartCoroutine), new Type[] { typeof(string) });
MethodInfo m_StartCoroutine_IEnumerator = AccessTools.Method(typeof(MonoBehaviour), nameof(MonoBehaviour.StartCoroutine), new Type[] { typeof(IEnumerator) });

List<CodeInstruction> code = new List<CodeInstruction>(instructions);

for (int i = code.Count - 1; i >= 0; i--)
{
if (code[i].opcode == OpCodes.Call && ReferenceEquals(code[i].operand, m_StartCoroutine_IEnumerator))
{
code[i].operand = m_StartCoroutine_String;
int j;
bool found = false;
for (j = i - 1; j >= i - 4; j--)
{
if (code[j].opcode == OpCodes.Call && ReferenceEquals(code[j].operand, m_UpdateSphere))
{
code[j].opcode = OpCodes.Ldstr;
code[j].operand = nameof(PQS.ResetAndWaitCoroutine);
found = true;
break;
}
}

if (!found)
throw new Exception("PQS.ResetAndWait transpiler patch failed, UpdateSphere() call not found");

if (code[j - 1].opcode == OpCodes.Ldarg_0 && code[j - 2].opcode == OpCodes.Ldarg_0)
code[j - 2].opcode = OpCodes.Nop;
else
throw new Exception("PQS.ResetAndWait transpiler patch failed, unexpected IL pattern");

break;
}
}

return code;
}
}
}
2 changes: 1 addition & 1 deletion KSPCommunityFixes/QoL/ToolbarShowHide.cs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ protected override void ApplyPatches(List<PatchInfo> patches)

patches.Add(new PatchInfo(
PatchMethodType.Prefix,
AccessTools.Method(typeof(ApplicationLauncher), nameof(ApplicationLauncher.ShouldItHide)),
AccessTools.Method(typeof(ApplicationLauncher), nameof(ApplicationLauncher.ShouldItHide), Type.EmptyTypes),
this));

patches.Add(new PatchInfo(
Expand Down
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ User options are available from the "ESC" in-game settings menu :<br/><img src="
- **OnDemandPartBuoyancy** [KSP 1.8.0 - 1.12.3]<br/>Prevent the part buoyancy integrator from running when not needed. Improves performance for large part count vessels while in the SOI of a body that has an ocean (Kerbin, Eve, Laythe...)
- **TextureLoaderOptimizations** [KSP 1.10.0 - 1.12.3]<br/> Speedup loading time by caching on disk the PNG textures KSP converts to DXT5 on every launch. Also make PNG `@thumbs` cargo part textures non-readable to free some RAM. This patch has no entry in `settings.cfg`, but is opt-in (a popup is shown on first KSP launch) and can be disabled latter in the in-game settings menu.
- **PQSUpdateNoMemoryAlloc** [KSP 1.11.0 - 1.12.3]<br/> Prevent huge memory allocations and resulting occasional stutter on PQS creation happening when moving around near a body surface.
- [**PQSCoroutineLeak**](https://github.com/KSPModdingLibs/KSPCommunityFixes/issues/85) [KSP 1.8.0 - 1.12.3]<br/>Prevent KSP from spawning multiple PQS update coroutines for the same PQS after scene switches and on other occasions, wasting a ton of CPU processing time.
- [**MemoryLeaks**](https://github.com/KSPModdingLibs/KSPCommunityFixes/issues/49) [KSP 1.12.0 - 1.12.3]<br/>Fix a bunch of managed memory leaks, mainly by proactively removing `GameEvents` delegates originating from destroyed `UnityEngine.Object` instances on scene switches. Will log detected leaks and memory usage. Also see`Settings.cfg` to enable advanced logging options that can be useful to hunt down memory leaks in mods.
- [**ProgressTrackingSpeedBoost**](https://github.com/KSPModdingLibs/KSPCommunityFixes/pull/57) [KSP 1.12.0 - 1.12.3]<br/>Remove unused ProgressTracking update handlers. Provides a very noticeable performance uplift in career games having a large amount of celestial bodies and/or vessels.
- [**DisableMapUpdateInFlight**](https://github.com/KSPModdingLibs/KSPCommunityFixes/issues/59) [KSP 1.8.0 - 1.12.3]<br/>Disable the update of orbit lines and markers in flight when the map view isn't shown. Provides decent performance gains in games having a large amount of celestial bodies and/or vessels.
Expand Down Expand Up @@ -150,6 +151,10 @@ If doing so in the `Debug` configuration and if your KSP install is modified to

### Changelog

##### 1.21.0
- New performance / KSP bugfix patch : [PQSCoroutineLeak](https://github.com/KSPModdingLibs/KSPCommunityFixes/issues/85) (issue discovered by @Gameslinx)
- Fixed the ToolbarShowHide patch partially failing due to an ambigious match exception when searching the no args `ApplicationLauncher.ShouldItHide()` method overload.

##### 1.20.4
- Restrict UpgradeBugs to KSP 1.12+ since it is compiled against the new combined editor class.
- New KSP bufix : [MapSOCorrectWrapping](https://github.com/KSPModdingLibs/KSPCommunityFixes/pull/83) (contributed by @RCrockford)
Expand Down

0 comments on commit e663e18

Please sign in to comment.