Skip to content

Commit

Permalink
Remove ref passing, but keep devirtualizations
Browse files Browse the repository at this point in the history
  • Loading branch information
WorkingRobot committed Mar 16, 2024
1 parent 3223bdc commit ec77f1d
Show file tree
Hide file tree
Showing 48 changed files with 408 additions and 784 deletions.
26 changes: 21 additions & 5 deletions Benchmark/Bench.cs
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Diagnosers;
using BenchmarkDotNet.Diagnostics.dotTrace;
using BenchmarkDotNet.Jobs;
using Craftimizer.Simulator;
using Craftimizer.Solver;

namespace Craftimizer.Benchmark;

[SimpleJob(RuntimeMoniker.Net70, baseline: true)]
[SimpleJob(RuntimeMoniker.Net80)]
[SimpleJob(RuntimeMoniker.Net70)]
[SimpleJob(RuntimeMoniker.Net80, baseline: true)]
[MinColumn, Q1Column, Q3Column, MaxColumn]
[DotTraceDiagnoser]
//[DotTraceDiagnoser]
[MemoryDiagnoser]
[DisassemblyDiagnoser(maxDepth: 500, exportGithubMarkdown: false, exportHtml: true)]
public class Bench
{
public record struct HashWrapper<T>(T Data) where T : notnull
Expand Down Expand Up @@ -95,12 +98,25 @@ public override readonly string ToString() =>
[ParamsSource(nameof(Configs))]
public HashWrapper<SolverConfig> Config { get; set; }

[Benchmark]
public async Task<float> Solve()
// [Benchmark]
public async Task<float> SolveAsync()
{
var solver = new Solver.Solver(Config, State);
solver.Start();
var (_, s) = await solver.GetTask().ConfigureAwait(false);
return (float)s.Quality / s.Input.Recipe.MaxQuality;
}

[Benchmark]
public (float MaxScore, SolverSolution Solution) Solve()
{
var config = new MCTSConfig(Config.Data);

var solver = new MCTS(config, State);
var progress = 0;
solver.Search(Config.Data.Iterations, ref progress, CancellationToken.None);
var solution = solver.Solution();

return (solver.MaxScore, solution);
}
}
3 changes: 1 addition & 2 deletions Craftimizer/Windows/MacroEditor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -935,7 +935,6 @@ private void DrawActionHotbars()
using var _color3 = ImRaii.PushColor(ImGuiCol.ButtonHovered, Vector4.Zero);
using var _color2 = ImRaii.PushColor(ImGuiCol.ButtonActive, Vector4.Zero);
using var _alpha = ImRaii.PushStyle(ImGuiStyleVar.DisabledAlpha, ImGui.GetStyle().DisabledAlpha * .5f);
var cost = 0;
foreach (var category in Enum.GetValues<ActionCategory>())
{
if (category == ActionCategory.Combo)
Expand All @@ -953,7 +952,7 @@ private void DrawActionHotbars()
if (i < itemCount)
{
var actionBase = actions[i].Base();
var canUse = actionBase.CanUse(sim, ref cost);
var canUse = actionBase.CanUse(sim);
if (ImGui.ImageButton(actions[i].GetIcon(RecipeData!.ClassJob).ImGuiHandle, new(imageSize), default, Vector2.One, 0, default, !canUse ? new(1, 1, 1, ImGui.GetStyle().DisabledAlpha) : Vector4.One))
AddStep(actions[i]);
if (!canUse &&
Expand Down
29 changes: 6 additions & 23 deletions Simulator/Actions/AdvancedTouch.cs
Original file line number Diff line number Diff line change
@@ -1,27 +1,10 @@
namespace Craftimizer.Simulator.Actions;

internal sealed class AdvancedTouch : BaseAction
internal sealed class AdvancedTouch() : BaseAction(
ActionCategory.Quality, level: 84, actionId: 100411,
increasesQuality: true,
defaultCPCost: 46, defaultEfficiency: 150)
{
public int CostDefault = 46;
public int CostOptimal = 18;
public int EfficiencyDefault = 150;

public AdvancedTouch()
{
Category = ActionCategory.Quality;
Level = 84;
ActionId = 100411;
IncreasesQuality = true;
}


public override void CPCost(Simulator s, ref int cost)
{
cost = s.ActionStates.TouchComboIdx == 2 ? CostOptimal : CostDefault;
}

public override void Efficiency(Simulator s, ref int eff)
{
eff = EfficiencyDefault;
}
public override int CPCost(Simulator s) =>
s.ActionStates.TouchComboIdx == 2 ? 18 : 46;
}
7 changes: 4 additions & 3 deletions Simulator/Actions/AdvancedTouchCombo.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
namespace Craftimizer.Simulator.Actions;

internal sealed class AdvancedTouchCombo : BaseComboAction<StandardTouchCombo, AdvancedTouch>
internal sealed class AdvancedTouchCombo() : BaseComboAction<StandardTouchCombo, AdvancedTouch>(
ActionType.StandardTouchCombo, ActionType.AdvancedTouch, 18 * 3
)
{
public override ActionType ActionTypeA => ActionType.StandardTouchCombo;
public override ActionType ActionTypeB => ActionType.AdvancedTouch;

}
90 changes: 46 additions & 44 deletions Simulator/Actions/BaseAction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,39 +2,46 @@

namespace Craftimizer.Simulator.Actions;

public abstract class BaseAction
public abstract class BaseAction(
ActionCategory category, int level, uint actionId,
int macroWaitTime = 3,
bool increasesProgress = false, bool increasesQuality = false,
int durabilityCost = 10, bool increasesStepCount = true,
int defaultCPCost = 0,
int defaultEfficiency = 0,
float defaultSuccessRate = 1)
{
// Non-instanced properties

// Metadata
public ActionCategory Category;
public readonly ActionCategory Category = category;

public int Level;
public readonly int Level = level;
// Doesn't matter from which class, we'll use the sheet to extrapolate the rest
public uint ActionId;
public readonly uint ActionId = actionId;
// Seconds
public int MacroWaitTime = 3;
public readonly int MacroWaitTime = macroWaitTime;

// Action properties
public bool IncreasesProgress;
public bool IncreasesQuality;
public int DurabilityCost = 10;
public bool IncreasesStepCount = true;
public int EfficiencyFactor;
public float SuccessRateFactor = 1;
public readonly bool IncreasesProgress = increasesProgress;
public readonly bool IncreasesQuality = increasesQuality;
public readonly int DurabilityCost = durabilityCost;
public readonly bool IncreasesStepCount = increasesStepCount;

// Instanced properties
public abstract void CPCost(Simulator s, ref int cost);
public readonly int DefaultCPCost = defaultCPCost;
public readonly int DefaultEfficiency = defaultEfficiency;
public readonly float DefaultSuccessRate = defaultSuccessRate;

public virtual void Efficiency(Simulator s, ref int eff)
{
eff = EfficiencyFactor;
}
// Instanced properties
public virtual int CPCost(Simulator s) =>
DefaultCPCost;

public virtual void SuccessRate(Simulator s, ref float success)
{
success = SuccessRateFactor;
}
public virtual int Efficiency(Simulator s) =>
DefaultEfficiency;

public virtual float SuccessRate(Simulator s) =>
DefaultSuccessRate;

// Return true if it can be in the action pool now or in the future
// e.g. if Heart and Soul is already used, it is impossible to use it again
Expand All @@ -44,23 +51,18 @@ public virtual bool IsPossible(Simulator s) =>

// Return true if it can be used now
// This already assumes that IsPossible returns true *at some point before*
public virtual bool CouldUse(Simulator s, ref int cost)
{
CPCost(s, ref cost);
return s.CP >= cost;
}
public virtual bool CouldUse(Simulator s) =>
s.CP >= CPCost(s);

public bool CanUse(Simulator s, ref int cost) =>
IsPossible(s) && CouldUse(s, ref cost);
public bool CanUse(Simulator s) =>
IsPossible(s) && CouldUse(s);

public virtual void Use(Simulator s, ref int cost, ref float success, ref int eff)
public virtual void Use(Simulator s)
{
SuccessRate(s, ref success);
if (s.RollSuccess(success))
UseSuccess(s, ref eff);
CPCost(s, ref cost);
if (s.RollSuccess(SuccessRate(s)))
UseSuccess(s);

s.ReduceCP(cost);
s.ReduceCP(CPCost(s));
s.ReduceDurability(DurabilityCost);

if (s.Durability > 0)
Expand All @@ -79,9 +81,9 @@ public virtual void Use(Simulator s, ref int cost, ref float success, ref int ef
s.ActiveEffects.DecrementDuration();
}

public virtual void UseSuccess(Simulator s, ref int eff)
public virtual void UseSuccess(Simulator s)
{
Efficiency(s, ref eff);
var eff = Efficiency(s);
if (eff != 0)
{
if (IncreasesProgress)
Expand All @@ -93,28 +95,28 @@ public virtual void UseSuccess(Simulator s, ref int eff)

public virtual string GetTooltip(Simulator s, bool addUsability)
{
var cost = CPCost(s);
var eff = Efficiency(s);
var success = SuccessRate(s);

var builder = new StringBuilder();
int cost = 0;
float success = 1f;
if (addUsability && !CanUse(s, ref cost))
if (addUsability && !CanUse(s))
builder.AppendLine($"Cannot Use");
builder.AppendLine($"Level {Level}");
if (cost != 0)
builder.AppendLine($"-{s.CalculateCPCost(cost)} CP");
if (DurabilityCost != 0)
builder.AppendLine($"-{s.CalculateDurabilityCost(DurabilityCost)} Durability");
Efficiency(s, ref cost);
if (cost != 0)
if (eff != 0)
{
if (IncreasesProgress)
builder.AppendLine($"+{s.CalculateProgressGain(cost)} Progress");
builder.AppendLine($"+{s.CalculateProgressGain(eff)} Progress");
if (IncreasesQuality)
builder.AppendLine($"+{s.CalculateQualityGain(cost)} Quality");
builder.AppendLine($"+{s.CalculateQualityGain(eff)} Quality");
}
if (!IncreasesStepCount)
builder.AppendLine($"Does Not Increase Step Count");
SuccessRate(s, ref success);
if (Math.Abs(success - 1f) > float.Epsilon)
if (success != 1)
builder.AppendLine($"{s.CalculateSuccessRate(success) * 100:##}% Success Rate");
return builder.ToString();
}
Expand Down
28 changes: 18 additions & 10 deletions Simulator/Actions/BaseBuffAction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,27 @@

namespace Craftimizer.Simulator.Actions;

internal abstract class BaseBuffAction : BaseAction
internal abstract class BaseBuffAction(
ActionCategory category, int level, uint actionId,
EffectType effect, int duration,
int macroWaitTime = 2,
bool increasesProgress = false, bool increasesQuality = false,
int durabilityCost = 0, bool increasesStepCount = true,
int defaultCPCost = 0,
int defaultEfficiency = 0,
float defaultSuccessRate = 1) :
BaseAction(
category, level, actionId,
macroWaitTime,
increasesProgress, increasesQuality,
durabilityCost, increasesStepCount,
defaultCPCost, defaultEfficiency, defaultSuccessRate)
{
public BaseBuffAction()
{
MacroWaitTime = 2;
DurabilityCost = 0;
}

// Non-instanced properties
public EffectType Effect;
public int Duration = 1;
public readonly EffectType Effect = effect;
public readonly int Duration = duration;

public override void UseSuccess(Simulator s, ref int eff) =>
public override void UseSuccess(Simulator s) =>
s.AddEffect(Effect, Duration);

public override string GetTooltip(Simulator s, bool addUsability)
Expand Down
23 changes: 13 additions & 10 deletions Simulator/Actions/BaseComboAction.cs
Original file line number Diff line number Diff line change
@@ -1,17 +1,20 @@
namespace Craftimizer.Simulator.Actions;

public abstract class BaseComboAction : BaseAction
public abstract class BaseComboAction(
ActionType actionTypeA, ActionType actionTypeB,
BaseAction actionA, BaseAction actionB,
int? defaultCPCost = null) :
BaseAction(
ActionCategory.Combo, Math.Max(actionA.Level, actionA.Level), actionB.ActionId,
increasesProgress: actionA.IncreasesProgress || actionB.IncreasesProgress,
increasesQuality: actionA.IncreasesQuality || actionB.IncreasesQuality,
defaultCPCost: defaultCPCost ?? (actionA.DefaultCPCost + actionB.DefaultCPCost))
{
public abstract ActionType ActionTypeA { get; }
public abstract ActionType ActionTypeB { get; }
public readonly ActionType ActionTypeA = actionTypeA;
public readonly ActionType ActionTypeB = actionTypeB;

public BaseComboAction()
{
Category = ActionCategory.Combo;
}

protected bool BaseCouldUse(Simulator s, ref int cost) =>
base.CouldUse(s, ref cost);
protected bool BaseCouldUse(Simulator s) =>
base.CouldUse(s);

private static bool VerifyDurability2(int durabilityA, int durability, in Effects effects)
{
Expand Down
36 changes: 13 additions & 23 deletions Simulator/Actions/BaseComboActionImpl.cs
Original file line number Diff line number Diff line change
@@ -1,36 +1,26 @@
namespace Craftimizer.Simulator.Actions;

internal abstract class BaseComboAction<A, B> : BaseComboAction where A : BaseAction, new() where B : BaseAction, new()
internal abstract class BaseComboAction<A, B>(
ActionType actionTypeA, ActionType actionTypeB,
int? baseCPCost = null) :
BaseComboAction(
actionTypeA, actionTypeB,
ActionA, ActionB,
baseCPCost
) where A : BaseAction, new() where B : BaseAction, new()
{
protected static readonly A ActionA = new();
protected static readonly B ActionB = new();

protected BaseComboAction()
{
Level = ActionB.Level;
ActionId = ActionB.ActionId;
IncreasesProgress = ActionA.IncreasesProgress || ActionB.IncreasesProgress;
IncreasesQuality = ActionA.IncreasesQuality || ActionB.IncreasesQuality;
}

public override void CPCost(Simulator s, ref int cost)
{
var costTmp = 0;
ActionA.CPCost(s, ref costTmp);
cost += costTmp;
ActionB.CPCost(s, ref costTmp);
cost += costTmp;
}

public override bool IsPossible(Simulator s) => ActionA.IsPossible(s) && ActionB.IsPossible(s);

public override bool CouldUse(Simulator s, ref int cost) =>
BaseCouldUse(s, ref cost) && VerifyDurability2(s, ActionA.DurabilityCost);
public override bool CouldUse(Simulator s) =>
BaseCouldUse(s) && VerifyDurability2(s, ActionA.DurabilityCost);

public override void Use(Simulator s, ref int cost, ref float success, ref int eff)
public override void Use(Simulator s)
{
ActionA.Use(s, ref cost, ref success, ref eff);
ActionB.Use(s, ref cost, ref success, ref eff);
ActionA.Use(s);
ActionB.Use(s);
}

public override string GetTooltip(Simulator s, bool addUsability) =>
Expand Down
Loading

1 comment on commit ec77f1d

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Benchmark

Benchmark suite Current: ec77f1d Previous: ea963f9 Ratio
Craftimizer.Benchmark.Bench.Solve(State: 136BC376, Config: 89DD5AF7) 85193827.77777778 ns (± 862271.7969021155)
Craftimizer.Benchmark.Bench.Solve(State: 136BC376, Config: 89DD5AF7) 66711051.666666664 ns (± 839975.2011760669)
Craftimizer.Benchmark.Bench.Solve(State: 34AFBBA1, Config: 89DD5AF7) 124861286.66666667 ns (± 1204626.615604939)
Craftimizer.Benchmark.Bench.Solve(State: 34AFBBA1, Config: 89DD5AF7) 96176391.11111112 ns (± 709819.2961655739)

This comment was automatically generated by workflow using github-action-benchmark.

Please sign in to comment.