Skip to content

Commit bff6015

Browse files
committed
benchmarks: add governance version resolution
1 parent 59df430 commit bff6015

3 files changed

Lines changed: 211 additions & 0 deletions

File tree

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
using BenchmarkDotNet.Attributes;
2+
using ModularityKit.Mutator.Governance.Abstractions.Resolution.Model;
3+
using ModularityKit.Mutator.Governance.Abstractions.Resolution.Strategies;
4+
using ModularityKit.Mutator.Benchmarks.Governance.Resolution.Support;
5+
6+
namespace ModularityKit.Mutator.Benchmarks.Governance.Resolution;
7+
8+
/// <summary>
9+
/// Benchmarks governance version resolution paths in the governance runtime.
10+
/// </summary>
11+
[BenchmarkCategory("Governance")]
12+
[MemoryDiagnoser]
13+
[InProcess]
14+
public class GovernanceVersionResolutionBenchmarks
15+
{
16+
private const string MatchingRequestId = "governance-resolution-matching";
17+
private const string StaleRequestId = "governance-resolution-stale";
18+
private const string RevalidateRequestId = "governance-resolution-revalidate";
19+
20+
private GovernanceVersionResolutionBenchmarkSupport.GovernanceVersionResolutionBenchmarkFixture _matchingFixture = null!;
21+
private GovernanceVersionResolutionBenchmarkSupport.GovernanceVersionResolutionBenchmarkFixture _staleFixture = null!;
22+
private GovernanceVersionResolutionBenchmarkSupport.GovernanceVersionResolutionBenchmarkFixture _revalidateFixture = null!;
23+
24+
/// <summary>
25+
/// Prepares fresh fixtures for each benchmark iteration.
26+
/// </summary>
27+
[IterationSetup]
28+
public void Setup()
29+
{
30+
_matchingFixture = GovernanceVersionResolutionBenchmarkSupport.CreateFixture(
31+
MatchingRequestId,
32+
expectedStateVersion: "v10",
33+
currentStateVersion: "v10");
34+
35+
_staleFixture = GovernanceVersionResolutionBenchmarkSupport.CreateFixture(
36+
StaleRequestId,
37+
expectedStateVersion: "v10",
38+
currentStateVersion: "v15");
39+
40+
_revalidateFixture = GovernanceVersionResolutionBenchmarkSupport.CreateFixture(
41+
RevalidateRequestId,
42+
expectedStateVersion: "v10",
43+
currentStateVersion: "v15");
44+
}
45+
46+
/// <summary>
47+
/// Measures version comparison when approved request matches the current state version.
48+
/// </summary>
49+
[Benchmark(Baseline = true)]
50+
public async Task ResolveApproved_MatchingVersion()
51+
{
52+
var result = await _matchingFixture.ResolutionManager.ResolveAndStore(
53+
_matchingFixture.Request.RequestId,
54+
currentStateVersion: _matchingFixture.CurrentStateVersion,
55+
resolutionContext: _matchingFixture.ResolutionContext,
56+
strategy: VersionedRequestResolutionStrategy.RejectStale).ConfigureAwait(false);
57+
58+
GC.KeepAlive(result);
59+
}
60+
61+
/// <summary>
62+
/// Measures stale request detection and classification during version resolution.
63+
/// </summary>
64+
[Benchmark]
65+
public async Task ResolveApproved_RejectStale()
66+
{
67+
var result = await _staleFixture.ResolutionManager.ResolveAndStore(
68+
_staleFixture.Request.RequestId,
69+
currentStateVersion: _staleFixture.CurrentStateVersion,
70+
resolutionContext: _staleFixture.ResolutionContext,
71+
strategy: VersionedRequestResolutionStrategy.RejectStale).ConfigureAwait(false);
72+
73+
GC.KeepAlive(result);
74+
}
75+
76+
/// <summary>
77+
/// Measures revalidation-driven request resolution against the latest state version.
78+
/// </summary>
79+
[Benchmark]
80+
public async Task ResolveApproved_Revalidate()
81+
{
82+
var result = await _revalidateFixture.ResolutionManager.ResolveAndStore(
83+
_revalidateFixture.Request.RequestId,
84+
currentStateVersion: _revalidateFixture.CurrentStateVersion,
85+
resolutionContext: _revalidateFixture.ResolutionContext,
86+
strategy: VersionedRequestResolutionStrategy.RevalidateOnLatestState).ConfigureAwait(false);
87+
88+
GC.KeepAlive(result);
89+
}
90+
}
Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
using ModularityKit.Mutator.Abstractions;
2+
using ModularityKit.Mutator.Abstractions.Changes;
3+
using ModularityKit.Mutator.Abstractions.Context;
4+
using ModularityKit.Mutator.Abstractions.Engine;
5+
using ModularityKit.Mutator.Abstractions.Intent;
6+
using ModularityKit.Mutator.Abstractions.Results;
7+
using ModularityKit.Mutator.Benchmarks.Engine;
8+
using ModularityKit.Mutator.Governance.Abstractions.Execution.Contracts;
9+
using ModularityKit.Mutator.Governance.Abstractions.Requests.Factory;
10+
using ModularityKit.Mutator.Governance.Abstractions.Requests.Model;
11+
using ModularityKit.Mutator.Governance.Runtime.Resolution.Execution;
12+
using ModularityKit.Mutator.Governance.Runtime.Storage;
13+
14+
namespace ModularityKit.Mutator.Benchmarks.Governance.Resolution.Support;
15+
16+
/// <summary>
17+
/// Builds repeatable governance version resolution benchmark fixtures.
18+
/// </summary>
19+
internal static class GovernanceVersionResolutionBenchmarkSupport
20+
{
21+
public const string StateId = "governance-benchmark:resolution";
22+
23+
/// <summary>
24+
/// Creates a fresh resolution fixture for a single scenario run.
25+
/// </summary>
26+
public static GovernanceVersionResolutionBenchmarkFixture CreateFixture(
27+
string requestId,
28+
string expectedStateVersion,
29+
string currentStateVersion)
30+
{
31+
_ = MutationEngineBenchmarkSupport.BuildEngine(MutationEngineOptions.Strict);
32+
33+
var store = new InMemoryMutationRequestStore();
34+
var resolver = new MutationRequestVersionResolver();
35+
var resolutionManager = new MutationRequestVersionResolutionManager(store, resolver);
36+
var request = store.Create(CreateApprovedRequest<GovernanceVersionResolutionState, NoOpGovernanceResolutionMutation>(
37+
requestId,
38+
expectedStateVersion))
39+
.GetAwaiter()
40+
.GetResult();
41+
42+
return new GovernanceVersionResolutionBenchmarkFixture(
43+
ResolutionManager: resolutionManager,
44+
Request: request,
45+
CurrentStateVersion: currentStateVersion,
46+
ResolutionContext: MutationContext.System("governance-resolution-benchmark"));
47+
}
48+
49+
/// <summary>
50+
/// Creates the approved request used by governance version resolution benchmarks.
51+
/// </summary>
52+
private static MutationRequest CreateApprovedRequest<TState, TMutation>(
53+
string requestId,
54+
string expectedStateVersion)
55+
where TMutation : IMutation<TState>
56+
=> MutationRequestFactory.Approved<TState, TMutation>(
57+
stateId: StateId,
58+
intent: CreateIntent(),
59+
context: MutationContext.User("requester", "Requester", "Need governed version resolution"),
60+
expectedStateVersion: expectedStateVersion)
61+
with
62+
{
63+
RequestId = requestId
64+
};
65+
66+
/// <summary>
67+
/// Creates the intent used by governance version resolution scenarios.
68+
/// </summary>
69+
private static MutationIntent CreateIntent()
70+
=> new()
71+
{
72+
OperationName = "ResolveGovernedVersion",
73+
Category = "Governance",
74+
Description = "Resolve governance request version against the current state snapshot",
75+
RiskLevel = MutationRiskLevel.Low,
76+
IsReversible = true
77+
};
78+
79+
/// <summary>
80+
/// Minimal versioned state used by governance version resolution benchmarks.
81+
/// </summary>
82+
/// <param name="StateId">Stable state identifier.</param>
83+
/// <param name="Version">Current state version.</param>
84+
internal sealed record GovernanceVersionResolutionState(string StateId, string Version) : IVersionedState;
85+
86+
/// <summary>
87+
/// Minimal mutation type used to anchor governed request metadata for version resolution benchmarks.
88+
/// </summary>
89+
internal sealed class NoOpGovernanceResolutionMutation : IMutation<GovernanceVersionResolutionState>
90+
{
91+
public MutationIntent Intent { get; } = new()
92+
{
93+
OperationName = "NoOpGovernanceResolution",
94+
Category = "Governance",
95+
Description = "Anchor request metadata for governed version resolution benchmarks",
96+
RiskLevel = MutationRiskLevel.Low,
97+
IsReversible = true
98+
};
99+
100+
public MutationContext Context { get; } = MutationContext.System("governance-resolution-benchmark");
101+
102+
public MutationResult<GovernanceVersionResolutionState> Apply(GovernanceVersionResolutionState state)
103+
=> MutationResult<GovernanceVersionResolutionState>.Success(
104+
state,
105+
ChangeSet.Empty);
106+
107+
public ValidationResult Validate(GovernanceVersionResolutionState state) => ValidationResult.Success();
108+
109+
public MutationResult<GovernanceVersionResolutionState> Simulate(GovernanceVersionResolutionState state) => Apply(state);
110+
}
111+
112+
/// <summary>
113+
/// Shared fixture for a governance version resolution scenario.
114+
/// </summary>
115+
internal sealed record GovernanceVersionResolutionBenchmarkFixture(
116+
MutationRequestVersionResolutionManager ResolutionManager,
117+
MutationRequest Request,
118+
string CurrentStateVersion,
119+
MutationContext ResolutionContext);
120+
}

Benchmarks/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ This folder contains BenchmarkDotNet measurements for `ModularityKit.Mutator`.
1717
- governance approval workflow overhead in the governance runtime
1818
- governance request lifecycle overhead in the governance runtime
1919
- governance execution orchestration overhead in the governance runtime
20+
- governance version resolution overhead in the governance runtime
2021

2122
The throughput benchmarks use cloned array backed state so state size effects remain visible in the
2223
actual mutation path rather than being hidden behind an artificial inner loop.

0 commit comments

Comments
 (0)