diff --git a/1.6/Assemblies/PerformanceFish.dll b/1.6/Assemblies/PerformanceFish.dll
index 1798725..4ac7526 100644
Binary files a/1.6/Assemblies/PerformanceFish.dll and b/1.6/Assemblies/PerformanceFish.dll differ
diff --git a/1.6/Assemblies/PerformanceFish.pdb b/1.6/Assemblies/PerformanceFish.pdb
index bdc70d0..6d57270 100644
Binary files a/1.6/Assemblies/PerformanceFish.pdb and b/1.6/Assemblies/PerformanceFish.pdb differ
diff --git a/NuGet.Config b/NuGet.Config
new file mode 100644
index 0000000..95e879e
--- /dev/null
+++ b/NuGet.Config
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/Source/PerformanceFish/1.6.csproj b/Source/PerformanceFish/1.6.csproj
index 1478547..6b34b57 100644
--- a/Source/PerformanceFish/1.6.csproj
+++ b/Source/PerformanceFish/1.6.csproj
@@ -3,6 +3,7 @@
..\..\1.6\Assemblies\
Copyright (c) 2026 Bradson
+ false
$(MSBuildThisFileDirectory)..\..\..\Fishery
$(MSBuildThisFileDirectory)..\..\..\Fishery-clean
@@ -13,8 +14,13 @@
V1_5;V1_6
-
+
+
+
+
+
+
$(FisheryRepoRoot)\1.6\Assemblies\1Fishery.dll
False
diff --git a/Source/PerformanceFish/Cache/Utility.cs b/Source/PerformanceFish/Cache/Utility.cs
index 112d86a..51b6add 100644
--- a/Source/PerformanceFish/Cache/Utility.cs
+++ b/Source/PerformanceFish/Cache/Utility.cs
@@ -59,27 +59,33 @@ public static class Utility
return;
_gcInProgress = true;
-
- if (_cachesToProcessForGC is null || _currentGCProgress >= _cachesToProcessForGC.Length)
+ try
{
- _cachesToProcessForGC = All.ToArray();
- _gcRate = GenDate.TicksPerTwelfth / _cachesToProcessForGC.CountNonEmpty();
- _currentGCProgress = 0;
- _destroyedThingCounter = 0;
- }
+ if (_cachesToProcessForGC is null || _currentGCProgress >= _cachesToProcessForGC.Length)
+ {
+ _cachesToProcessForGC = All.ToArray();
+ var nonEmptyCount = _cachesToProcessForGC.CountNonEmpty();
+ _gcRate = nonEmptyCount > 0 ? GenDate.TicksPerTwelfth / nonEmptyCount : 1000;
+ _currentGCProgress = 0;
+ _destroyedThingCounter = 0;
+ if (nonEmptyCount == 0)
+ return;
+ }
- while (_cachesToProcessForGC[_currentGCProgress].Count == 0
- && _cachesToProcessForGC.Length - _currentGCProgress > 1)
+ while (_currentGCProgress < _cachesToProcessForGC.Length
+ && _cachesToProcessForGC[_currentGCProgress].Count == 0)
+ {
+ _currentGCProgress++;
+ }
+
+ if (_currentGCProgress < _cachesToProcessForGC.Length)
+ _cachesToProcessForGC[_currentGCProgress++].Clear();
+ }
+ finally
{
- _currentGCProgress++;
+ _lastGCTick = TickHelper.TicksGame;
+ _gcInProgress = false;
}
-
- if (_currentGCProgress < _cachesToProcessForGC.Length)
- _cachesToProcessForGC[_currentGCProgress++].Clear();
-
- _lastGCTick = TickHelper.TicksGame;
-
- _gcInProgress = false;
}
}
@@ -414,4 +420,4 @@ public sealed class CollectionRef(AccessTools.FieldRef fieldRef) : ICleara
}
private delegate void ClearInvoker(ref T collectionRef);
-}
\ No newline at end of file
+}
diff --git a/Source/PerformanceFish/GeneTrackerOptimization.cs b/Source/PerformanceFish/GeneTrackerOptimization.cs
index 88ca881..b5702cb 100644
--- a/Source/PerformanceFish/GeneTrackerOptimization.cs
+++ b/Source/PerformanceFish/GeneTrackerOptimization.cs
@@ -61,7 +61,15 @@ public sealed class GeneTrackerOptimization : ClassWithFishPrepatches
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool Dirty(Pawn_GeneTracker instance, List genesToTick)
+#if V1_6
+ {
+ ref var versions = ref instance.GeneListVersions();
+ return !versions.Initialized || versions.Xenogenes != instance.xenogenes._version
+ || versions.Endogenes != instance.endogenes._version;
+ }
+#else
=> GetListVersion(instance) != genesToTick._version;
+#endif
[MethodImpl(MethodImplOptions.NoInlining)]
public static void Update(Pawn_GeneTracker instance, List genesToTick)
@@ -71,12 +79,21 @@ public sealed class GeneTrackerOptimization : ClassWithFishPrepatches
AddTickableGenes(genesToTick, instance.xenogenes);
AddTickableGenes(genesToTick, instance.endogenes);
+#if V1_6
+ ref var versions = ref instance.GeneListVersions();
+ versions.Xenogenes = instance.xenogenes._version;
+ versions.Endogenes = instance.endogenes._version;
+ versions.Initialized = true;
+#else
genesToTick._version = GetListVersion(instance);
+#endif
}
+#if !V1_6
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static int GetListVersion(Pawn_GeneTracker instance)
=> (instance.xenogenes._version << 16) | (instance.endogenes._version & 0b1111_1111_1111_1111);
+#endif
private static void AddTickableGenes(List genesToTick, List genes)
{
@@ -115,6 +132,15 @@ public sealed class GeneTrackerOptimization : ClassWithFishPrepatches
}
}
+#if V1_6
+ public struct GeneListVersionState
+ {
+ public int Xenogenes;
+ public int Endogenes;
+ public bool Initialized;
+ }
+#endif
+
public sealed class GeneTrackerTickIntervalPatch : FishPrepatch
{
// i am iffy about this
diff --git a/Source/PerformanceFish/GetCompCaching.cs b/Source/PerformanceFish/GetCompCaching.cs
index 20ebb5a..1630d31 100644
--- a/Source/PerformanceFish/GetCompCaching.cs
+++ b/Source/PerformanceFish/GetCompCaching.cs
@@ -53,11 +53,13 @@ public sealed class GetCompCaching : ClassWithFishPrepatches
public record struct CacheValue() where T : ThingComp
{
+ private List? _listReference;
private int _listVersion = -2;
public T? Comp;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public bool IsDirty(List comps) => comps._version != _listVersion;
+ public bool IsDirty(List comps)
+ => !ReferenceEquals(comps, _listReference) || comps._version != _listVersion;
[MethodImpl(MethodImplOptions.NoInlining)]
public void Update(ThingWithComps thing, T? comp)
@@ -65,6 +67,7 @@ public sealed class GetCompCaching : ClassWithFishPrepatches
if (thing.thingIDNumber < 0)
return;
+ _listReference = thing.comps;
_listVersion = thing.comps._version;
Comp = comp;
}
@@ -113,11 +116,13 @@ public sealed class GetCompCaching : ClassWithFishPrepatches
public record struct CacheValue() where T : CompProperties
{
+ private List? _listReference;
private int _listVersion = -2;
public T? Comp;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public bool IsDirty(List comps) => comps._version != _listVersion;
+ public bool IsDirty(List comps)
+ => !ReferenceEquals(comps, _listReference) || comps._version != _listVersion;
[MethodImpl(MethodImplOptions.NoInlining)]
public void Update(ThingDef thingDef, T? comp)
@@ -125,6 +130,7 @@ public sealed class GetCompCaching : ClassWithFishPrepatches
if (thingDef.shortHash == default)
return;
+ _listReference = thingDef.comps;
_listVersion = thingDef.comps._version;
Comp = comp;
}
@@ -174,11 +180,13 @@ public sealed class GetCompCaching : ClassWithFishPrepatches
public record struct CacheValue()
{
+ private List? _listReference;
private int _listVersion = -2;
public bool HasComp;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public bool IsDirty(List comps) => comps._version != _listVersion;
+ public bool IsDirty(List comps)
+ => !ReferenceEquals(comps, _listReference) || comps._version != _listVersion;
[MethodImpl(MethodImplOptions.NoInlining)]
public void Update(ThingDef thingDef, bool hasComp)
@@ -186,6 +194,7 @@ public sealed class GetCompCaching : ClassWithFishPrepatches
if (thingDef.shortHash == default)
return;
+ _listReference = thingDef.comps;
_listVersion = thingDef.comps._version;
HasComp = hasComp;
}
@@ -236,11 +245,13 @@ public sealed class GetCompCaching : ClassWithFishPrepatches
public record struct CacheValue() where T : ThingComp
{
+ private List? _listReference;
private int _listVersion = -2;
public bool HasComp;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public bool IsDirty(List comps) => comps._version != _listVersion;
+ public bool IsDirty(List comps)
+ => !ReferenceEquals(comps, _listReference) || comps._version != _listVersion;
[MethodImpl(MethodImplOptions.NoInlining)]
public void Update(ThingDef thingDef, bool hasComp)
@@ -248,6 +259,7 @@ public sealed class GetCompCaching : ClassWithFishPrepatches
if (thingDef.shortHash == default)
return;
+ _listReference = thingDef.comps;
_listVersion = thingDef.comps._version;
HasComp = hasComp;
}
@@ -296,11 +308,13 @@ public sealed class GetCompCaching : ClassWithFishPrepatches
public record struct CacheValue() where T : HediffComp
{
+ private List? _listReference;
private int _listVersion = -2;
public T? Comp;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public bool IsDirty(List comps) => comps._version != _listVersion;
+ public bool IsDirty(List comps)
+ => !ReferenceEquals(comps, _listReference) || comps._version != _listVersion;
[MethodImpl(MethodImplOptions.NoInlining)]
public void Update(HediffWithComps hediff, T? comp)
@@ -308,6 +322,7 @@ public sealed class GetCompCaching : ClassWithFishPrepatches
if (hediff.loadID < 0)
return;
+ _listReference = hediff.comps;
_listVersion = hediff.comps._version;
Comp = comp;
}
@@ -355,11 +370,13 @@ public sealed class GetCompCaching : ClassWithFishPrepatches
public record struct CacheValue() where T : HediffCompProperties
{
+ private List? _listReference;
private int _listVersion = -2;
public T? Comp;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public bool IsDirty(List comps) => comps._version != _listVersion;
+ public bool IsDirty(List comps)
+ => !ReferenceEquals(comps, _listReference) || comps._version != _listVersion;
[MethodImpl(MethodImplOptions.NoInlining)]
public void Update(HediffDef hediffDef, T? comp)
@@ -367,6 +384,7 @@ public sealed class GetCompCaching : ClassWithFishPrepatches
if (hediffDef.shortHash == 0)
return;
+ _listReference = hediffDef.comps;
_listVersion = hediffDef.comps._version;
Comp = comp;
}
@@ -414,11 +432,13 @@ public sealed class GetCompCaching : ClassWithFishPrepatches
public record struct CacheValue() where T : AbilityComp
{
+ private List? _listReference;
private int _listVersion = -2;
public T? Comp;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public bool IsDirty(List comps) => comps._version != _listVersion;
+ public bool IsDirty(List comps)
+ => !ReferenceEquals(comps, _listReference) || comps._version != _listVersion;
[MethodImpl(MethodImplOptions.NoInlining)]
public void Update(Ability ability, T? comp)
@@ -426,6 +446,7 @@ public sealed class GetCompCaching : ClassWithFishPrepatches
if (ability.Id < 0)
return;
+ _listReference = ability.comps;
_listVersion = ability.comps._version;
Comp = comp;
}
@@ -468,11 +489,13 @@ public sealed class GetCompCaching : ClassWithFishPrepatches
public record struct CacheValue() where T : WorldObjectComp
{
+ private List? _listReference;
private int _listVersion = -2;
public T? Comp;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public bool IsDirty(List comps) => comps._version != _listVersion;
+ public bool IsDirty(List comps)
+ => !ReferenceEquals(comps, _listReference) || comps._version != _listVersion;
[MethodImpl(MethodImplOptions.NoInlining)]
public void Update(WorldObject worldObject, T? comp)
@@ -480,6 +503,7 @@ public sealed class GetCompCaching : ClassWithFishPrepatches
if (worldObject.ID < 0)
return;
+ _listReference = worldObject.comps;
_listVersion = worldObject.comps._version;
Comp = comp;
}
@@ -522,11 +546,13 @@ public sealed class GetCompCaching : ClassWithFishPrepatches
public record struct CacheValue() where T : MapComponent
{
+ private List? _listReference;
private int _listVersion = -2;
public T? Comp;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public bool IsDirty(List comps) => comps._version != _listVersion;
+ public bool IsDirty(List comps)
+ => !ReferenceEquals(comps, _listReference) || comps._version != _listVersion;
[MethodImpl(MethodImplOptions.NoInlining)]
public void Update(Map map, T? comp)
@@ -534,6 +560,7 @@ public sealed class GetCompCaching : ClassWithFishPrepatches
if (map.uniqueID < 0)
return;
+ _listReference = map.components;
_listVersion = map.components._version;
Comp = comp;
}
@@ -641,4 +668,4 @@ public sealed class GetCompCaching : ClassWithFishPrepatches
}
}
}
-}
\ No newline at end of file
+}
diff --git a/Source/PerformanceFish/NeedsTrackerCaching.cs b/Source/PerformanceFish/NeedsTrackerCaching.cs
index df4f8ff..f7bac6f 100644
--- a/Source/PerformanceFish/NeedsTrackerCaching.cs
+++ b/Source/PerformanceFish/NeedsTrackerCaching.cs
@@ -16,6 +16,8 @@ public sealed class NeedsTrackerCaching : ClassWithFishPrepatches
{
public sealed class TryGetNeedPatch : FishPrepatch
{
+ public override bool DefaultState => true;
+
public override string? Description { get; }
= "Caches generic need lookups behind the needs list version.";
@@ -30,6 +32,8 @@ public sealed class NeedsTrackerCaching : ClassWithFishPrepatches
public sealed class TryGetNeedOutPatch : FishPrepatch
{
+ public override bool DefaultState => true;
+
public override string? Description { get; }
= "Caches generic need lookups behind the needs list version.";
@@ -55,18 +59,18 @@ public sealed class NeedsTrackerCaching : ClassWithFishPrepatches
return cache.Found;
}
- return UpdateCache(instance, typeof(T), out need, ref cache);
+ return UpdateCache(instance, out need, ref cache);
}
[MethodImpl(MethodImplOptions.NoInlining)]
- private static bool UpdateCache(Pawn_NeedsTracker instance, Type needType, out T? need, ref CacheValue cache)
+ private static bool UpdateCache(Pawn_NeedsTracker instance, out T? need, ref CacheValue cache)
where T : Need
{
var needs = instance.needs;
for (var i = 0; i < needs.Count; i++)
{
var candidate = needs[i];
- if (candidate.GetType() != needType)
+ if (candidate.GetType() != typeof(T))
continue;
need = (T)candidate;
diff --git a/Source/PerformanceFish/OnAssembliesLoaded.cs b/Source/PerformanceFish/OnAssembliesLoaded.cs
index 48d0b40..911cf03 100644
--- a/Source/PerformanceFish/OnAssembliesLoaded.cs
+++ b/Source/PerformanceFish/OnAssembliesLoaded.cs
@@ -39,7 +39,7 @@ public static class OnAssembliesLoaded
PerformanceFishMod.AllPatchClasses = PerformanceFishMod.InitializeAllPatchClasses();
PerformanceFishMod.AllPrepatchClasses ??= PerformanceFishMod.InitializeAllPatchClasses();
- TryInitialize(AnalyzerFixes.Patch, true);
+ TryInitialize(AnalyzerFixes.Patch);
_ = FishSettings.Instance;
@@ -109,14 +109,11 @@ public static class OnAssembliesLoaded
}
}
- private static async void TryInitialize(Action action, bool async = false)
+ private static void TryInitialize(Action action)
{
try
{
- if (async)
- await Task.Run(action).ConfigureAwait(false);
- else
- action();
+ action();
}
catch (Exception ex)
{
diff --git a/Source/PerformanceFish/Patching/FishPatch.cs b/Source/PerformanceFish/Patching/FishPatch.cs
index 84d3ae5..e6aa2e5 100644
--- a/Source/PerformanceFish/Patching/FishPatch.cs
+++ b/Source/PerformanceFish/Patching/FishPatch.cs
@@ -90,6 +90,7 @@ public abstract class FishPatch : SingletonFactory, IExposable, IHasD
public List BenchmarkHarmonyMethodInfos { get; } = [];
private bool Patched { get; set; }
private bool ShouldBePatched { get; set; }
+ private readonly HashSet _patchedTargets = [];
public virtual string? Name => null;
@@ -190,15 +191,16 @@ public abstract class FishPatch : SingletonFactory, IExposable, IHasD
protected virtual void ApplyPatch()
{
- Patched = true;
- foreach (var method in TargetMethodInfos)
+ var targets = TargetMethodInfos.ToArray();
+ foreach (var method in targets)
{
+ if (_patchedTargets.Contains(method))
+ continue;
+
try
{
if (IsBenchmarking)
{
- Patched = false;
-
if (AccessTools.EnumeratorMoveNext(method) is { } moveNext)
{
BenchmarkHarmonyMethodInfos.Add(PerformanceFishMod.Harmony!.Patch(moveNext,
@@ -229,6 +231,7 @@ public abstract class FishPatch : SingletonFactory, IExposable, IHasD
transpiler: TryMakeHarmonyMethod(TranspilerMethodInfo, TranspilerMethodPriority),
finalizer: TryMakeHarmonyMethod(FinalizerMethodInfo, FinalizerMethodPriority)));
}
+ _patchedTargets.Add(method);
}
}
@@ -240,6 +243,7 @@ public abstract class FishPatch : SingletonFactory, IExposable, IHasD
FinalizerMethodInfo.FullDescription()}:\n{e}");
}
}
+ Patched = !IsBenchmarking && targets.All(_patchedTargets.Contains);
}
private static HarmonyMethod? TryMakeHarmonyMethod(MethodInfo? method, int priority = -1, string[]? before = null,
@@ -249,7 +253,7 @@ public abstract class FishPatch : SingletonFactory, IExposable, IHasD
public virtual void TryUnpatch()
{
ShouldBePatched = false;
- if ( /*!Enabled &&*/ Patched)
+ if (Patched || _patchedTargets.Count != 0)
ApplyUnpatching();
}
@@ -269,6 +273,7 @@ public abstract class FishPatch : SingletonFactory, IExposable, IHasD
});
}
}
+ _patchedTargets.Clear();
}
private static void TryUnpatchMethod(MethodBase targetMethod, MethodInfo? patchMethod)
diff --git a/Source/PerformanceFish/Planet/WorldObjectsOptimization.cs b/Source/PerformanceFish/Planet/WorldObjectsOptimization.cs
index eefb747..b746a5b 100644
--- a/Source/PerformanceFish/Planet/WorldObjectsOptimization.cs
+++ b/Source/PerformanceFish/Planet/WorldObjectsOptimization.cs
@@ -15,16 +15,21 @@ public sealed class WorldObjectsOptimization : ClassWithFishPrepatches
{
public sealed class WorldObjectsHolderTickPatch : FishPrepatch
{
+ public override bool DefaultState => true;
+
private static FishTable _skippableCompTypes = null!;
private static FishTable _skippableWorldObjectTypes = null!;
private static readonly List _tmpThingHolders = [];
+ private static readonly List _skippedWorldObjects = [];
+ private static List? _cachedWorldObjectsReference;
+ private static List