Lots of new optimizations utilizing prepatcher
To start, this mod now requires Prepatcher and Fishery. New optimizations include: gene ticking improvements, world object improvements, hediff optimizations, world pawn gc optimizations, better mothballing, dds support, ContentFinder caching, additions and changes to reflection caching, as well as various other additions. Multiplayer support has been improved too, but should be considered highly experimental. The WorkGiver_DoBill bug is fixed in this build. Multiple patches aiming to improve RimWorld's load time have been added too.
This commit is contained in:
@@ -1,24 +1,28 @@
|
||||
// Copyright (c) 2022 bradson
|
||||
// Copyright (c) 2023 bradson
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
|
||||
/*using System.Threading.Tasks;
|
||||
#if disabledForNow
|
||||
using System.Threading.Tasks;
|
||||
using Verse.AI;
|
||||
|
||||
namespace PerformanceFish.JobSystem;
|
||||
|
||||
public class GenClosestPatches : ClassWithFishPatches
|
||||
{*/
|
||||
#if disabledForNow
|
||||
{
|
||||
public class ClosestThing_Global_Patch : FishPatch
|
||||
{
|
||||
public override string Description => "Threading for job scanning. Disabled and unstable.";
|
||||
public override string Description { get; } = "Threading for job scanning. Disabled and unstable.";
|
||||
public override bool DefaultState => false;
|
||||
public static bool ThreadingEnabled { get; set; }
|
||||
public override Expression<Action> TargetMethod => () => GenClosest.ClosestThing_Global(default, null, default, null, null);
|
||||
|
||||
public override Expression<Action> TargetMethod { get; }
|
||||
= static () => GenClosest.ClosestThing_Global(default, null, default, null, null);
|
||||
|
||||
public static CodeInstructions Transpiler(CodeInstructions CodeInstructions)
|
||||
=> Reflection.MakeReplacementCall(ClosestThing_Global_Replacement);
|
||||
|
||||
private struct Variables
|
||||
{
|
||||
public IntVec3 center;
|
||||
@@ -27,18 +31,32 @@ public class GenClosestPatches : ClassWithFishPatches
|
||||
public float closestDistSquared;
|
||||
public Predicate<Thing>? validator;
|
||||
}
|
||||
public static Thing? ClosestThing_Global_Replacement(IntVec3 center, IEnumerable searchSet, float maxDistance = 99999f, Predicate<Thing>? validator = null, Func<Thing, float>? priorityGetter = null)
|
||||
|
||||
public static Thing? ClosestThing_Global_Replacement(IntVec3 center, IEnumerable? searchSet,
|
||||
float maxDistance = 99999f, Predicate<Thing>? validator = null, Func<Thing, float>? priorityGetter = null)
|
||||
{
|
||||
if (searchSet == null)
|
||||
return null;
|
||||
|
||||
var closestDistSquared = 2.14748365E+09f;
|
||||
Thing? chosen = null;
|
||||
var bestPrio = float.MinValue;
|
||||
//float maxDistanceSquared = maxDistance * maxDistance;
|
||||
Variables variables = new() { center = center, maxDistanceSquared = maxDistance * maxDistance, validator = validator, priorityGetter = priorityGetter, closestDistSquared = closestDistSquared };
|
||||
Variables variables = new()
|
||||
{
|
||||
center = center,
|
||||
maxDistanceSquared = maxDistance * maxDistance,
|
||||
validator = validator,
|
||||
priorityGetter = priorityGetter,
|
||||
closestDistSquared = closestDistSquared
|
||||
};
|
||||
|
||||
var predicate = GenClosest_Predicate.GetValidator(validator?.Target)?.Target ?? validator?.Target;
|
||||
if (ThreadingEnabled && validator != null && JobGiver_Work_Predicate.GetScanner(predicate) is WorkGiver_DoBill /*or WorkGiver_ConstructDeliverResources or WorkGiver_ConstructFinishFrames*/)
|
||||
if (ThreadingEnabled
|
||||
&& validator != null
|
||||
&& JobGiver_Work_Predicate.GetScanner(predicate) is WorkGiver_DoBill
|
||||
/*or WorkGiver_ConstructDeliverResources or WorkGiver_ConstructFinishFrames*/
|
||||
)
|
||||
{
|
||||
if (searchSet is IList<Thing> thingList)
|
||||
{
|
||||
@@ -47,15 +65,16 @@ public class GenClosestPatches : ClassWithFishPatches
|
||||
try
|
||||
{
|
||||
Parallel.For<(IList<Thing> list, Variables vars)>(0, thingList.Count,
|
||||
() => (thingList, variables),
|
||||
(i, loop, listAndVars) => (listAndVars.list, ProcessThreaded(listAndVars.list[i], listAndVars.vars)),
|
||||
_ => { });
|
||||
() => (thingList, variables),
|
||||
(i, loop, listAndVars) => (listAndVars.list,
|
||||
ProcessThreaded(listAndVars.list[i], listAndVars.vars)), static _ => { });
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
exception = ex;
|
||||
Log.Error($"Caught error while threading:\n{ex}");
|
||||
}
|
||||
|
||||
if (exception is null)
|
||||
Log.Message("Finished threading code without errors");
|
||||
|
||||
@@ -98,86 +117,112 @@ public class GenClosestPatches : ClassWithFishPatches
|
||||
}
|
||||
|
||||
return chosen;
|
||||
|
||||
void Process<T>(T t, Variables variables) where T : Thing
|
||||
{
|
||||
if (t.Spawned)
|
||||
if (!t.Spawned)
|
||||
return;
|
||||
|
||||
float num = (variables.center - t.Position).LengthHorizontalSquared;
|
||||
if (!(num > variables.maxDistanceSquared)
|
||||
&& (variables.priorityGetter != null || num < closestDistSquared)
|
||||
&& (variables.validator == null || variables.validator(t)))
|
||||
{
|
||||
float num = (variables.center - t.Position).LengthHorizontalSquared;
|
||||
if (!(num > variables.maxDistanceSquared)
|
||||
&& (variables.priorityGetter != null || num < closestDistSquared)
|
||||
&& (variables.validator == null || variables.validator(t)))
|
||||
var num2 = 0f;
|
||||
if (variables.priorityGetter != null)
|
||||
{
|
||||
var num2 = 0f;
|
||||
if (variables.priorityGetter != null)
|
||||
{
|
||||
num2 = variables.priorityGetter(t);
|
||||
if (num2 < bestPrio || (num2 == bestPrio && num >= closestDistSquared))
|
||||
return;
|
||||
}
|
||||
chosen = t;
|
||||
closestDistSquared = variables.closestDistSquared = num;
|
||||
bestPrio = num2;
|
||||
num2 = variables.priorityGetter(t);
|
||||
if (num2 < bestPrio || (Math.Abs(num2 - bestPrio) < 0.001f && num >= closestDistSquared))
|
||||
return;
|
||||
}
|
||||
|
||||
chosen = t;
|
||||
closestDistSquared = variables.closestDistSquared = num;
|
||||
bestPrio = num2;
|
||||
}
|
||||
}
|
||||
|
||||
Variables ProcessThreaded<T>(T t, Variables variables) where T : Thing
|
||||
{
|
||||
if (t.Spawned)
|
||||
if (!t.Spawned)
|
||||
return variables;
|
||||
|
||||
float num = (variables.center - t.Position).LengthHorizontalSquared;
|
||||
if (num > variables.maxDistanceSquared
|
||||
|| (variables.priorityGetter == null
|
||||
&& (!(num < variables.closestDistSquared)
|
||||
|| !(num < (variables.closestDistSquared = closestDistSquared))))
|
||||
|| (variables.validator != null && !variables.validator(t)))
|
||||
{
|
||||
float num = (variables.center - t.Position).LengthHorizontalSquared;
|
||||
if (!(num > variables.maxDistanceSquared)
|
||||
&& (variables.priorityGetter != null || (num < variables.closestDistSquared && num < (variables.closestDistSquared = closestDistSquared)))
|
||||
&& (variables.validator == null || variables.validator(t)))
|
||||
{
|
||||
lock (Lock)
|
||||
{
|
||||
var num2 = 0f;
|
||||
if (variables.priorityGetter != null)
|
||||
{
|
||||
num2 = variables.priorityGetter(t);
|
||||
if (num2 < bestPrio || (num2 == bestPrio && num >= closestDistSquared))
|
||||
return variables;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (num >= closestDistSquared)
|
||||
return variables;
|
||||
}
|
||||
chosen = t;
|
||||
closestDistSquared = variables.closestDistSquared = num;
|
||||
bestPrio = num2;
|
||||
}
|
||||
}
|
||||
return variables;
|
||||
}
|
||||
|
||||
lock (Lock)
|
||||
{
|
||||
var num2 = 0f;
|
||||
if (variables.priorityGetter != null)
|
||||
{
|
||||
num2 = variables.priorityGetter(t);
|
||||
if (num2 < bestPrio || (Math.Abs(num2 - bestPrio) < 0.001f && num >= closestDistSquared))
|
||||
return variables;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (num >= closestDistSquared)
|
||||
return variables;
|
||||
}
|
||||
|
||||
chosen = t;
|
||||
closestDistSquared = variables.closestDistSquared = num;
|
||||
bestPrio = num2;
|
||||
}
|
||||
|
||||
return variables;
|
||||
}
|
||||
}
|
||||
|
||||
private static object Lock { get; } = new();
|
||||
|
||||
private static Type JobGiverWorkPredicateType { get; } = AccessTools.FirstInner(typeof(JobGiver_Work),
|
||||
t => AccessTools.Field(t, "scanner") != null && AccessTools.FirstMethod(t, m => m.Name.Contains("TryIssueJobPackage")) != null);
|
||||
t => AccessTools.Field(t, "scanner") != null
|
||||
&& AccessTools.FirstMethod(t, m => m.Name.Contains("TryIssueJobPackage")) != null);
|
||||
|
||||
private static JobGiver_Work_PredicateAccess JobGiver_Work_Predicate { get; }
|
||||
= (JobGiver_Work_PredicateAccess)Activator.CreateInstance(typeof(JobGiver_Work_PredicateAccessImplementation<>).MakeGenericType(JobGiverWorkPredicateType));
|
||||
= (JobGiver_Work_PredicateAccess)Activator.CreateInstance(
|
||||
typeof(JobGiver_Work_PredicateAccessImplementation<>).MakeGenericType(JobGiverWorkPredicateType));
|
||||
|
||||
private static Type GenClosestPredicateType { get; } = AccessTools.FirstInner(typeof(GenClosest),
|
||||
t => AccessTools.Field(t, "validator") != null && AccessTools.FirstMethod(t, m => m.Name.Contains("ClosestThingReachable")) != null);
|
||||
t => AccessTools.Field(t, "validator") != null
|
||||
&& AccessTools.FirstMethod(t, m => m.Name.Contains("ClosestThingReachable")) != null);
|
||||
|
||||
private static GenClosest_PredicateAccess GenClosest_Predicate { get; }
|
||||
= (GenClosest_PredicateAccess)Activator.CreateInstance(typeof(GenClosest_PredicateAccessImplementation<>).MakeGenericType(GenClosestPredicateType));
|
||||
= (GenClosest_PredicateAccess)Activator.CreateInstance(
|
||||
typeof(GenClosest_PredicateAccessImplementation<>).MakeGenericType(GenClosestPredicateType));
|
||||
|
||||
private abstract class JobGiver_Work_PredicateAccess
|
||||
{
|
||||
public abstract WorkGiver_Scanner? GetScanner(object? obj);
|
||||
}
|
||||
|
||||
private class JobGiver_Work_PredicateAccessImplementation<T> : JobGiver_Work_PredicateAccess
|
||||
{
|
||||
public override WorkGiver_Scanner? GetScanner(object? obj) => obj is T t ? Scanner(t) : null;
|
||||
public static AccessTools.FieldRef<T, WorkGiver_Scanner> Scanner { get; } = AccessTools.FieldRefAccess<T, WorkGiver_Scanner>("scanner");
|
||||
|
||||
public static AccessTools.FieldRef<T, WorkGiver_Scanner> Scanner { get; }
|
||||
= AccessTools.FieldRefAccess<T, WorkGiver_Scanner>("scanner");
|
||||
}
|
||||
|
||||
private abstract class GenClosest_PredicateAccess
|
||||
{
|
||||
public abstract Predicate<Thing>? GetValidator(object? obj);
|
||||
}
|
||||
|
||||
private class GenClosest_PredicateAccessImplementation<T> : GenClosest_PredicateAccess
|
||||
{
|
||||
public override Predicate<Thing>? GetValidator(object? obj) => obj is T t ? Validator(t) : null;
|
||||
public static AccessTools.FieldRef<T, Predicate<Thing>> Validator { get; } = AccessTools.FieldRefAccess<T, Predicate<Thing>>("validator");
|
||||
|
||||
public static AccessTools.FieldRef<T, Predicate<Thing>> Validator { get; }
|
||||
= AccessTools.FieldRefAccess<T, Predicate<Thing>>("validator");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -187,8 +232,10 @@ public class GenClosestPatches : ClassWithFishPatches
|
||||
{
|
||||
protected CanReach_Patch() => FishSettings.ThreadingPatches.Add(this);
|
||||
public override bool DefaultState => false;
|
||||
public override string Description => "Lock for threading. Only needed with threading enabled and off by default";
|
||||
public override Expression<Action> TargetMethod => () => default(Reachability)!.CanReach(default, null, default, default);
|
||||
public override string Description { get; }
|
||||
= "Lock for threading. Only needed with threading enabled and off by default";
|
||||
public override Expression<Action> TargetMethod { get; }
|
||||
= static () => default(Reachability)!.CanReach(default, null, default, default);
|
||||
public static void Prefix()
|
||||
{
|
||||
if (FishSettings.ThreadingEnabled)
|
||||
|
||||
Reference in New Issue
Block a user