Skip to content

Commit 59df430

Browse files
committed
benchmarks: add governed execution orchestration
1 parent 99a8798 commit 59df430

3 files changed

Lines changed: 231 additions & 0 deletions

File tree

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
using BenchmarkDotNet.Attributes;
2+
using ModularityKit.Mutator.Governance.Abstractions.Execution.Model;
3+
using ModularityKit.Mutator.Governance.Abstractions.Resolution.Model;
4+
using ModularityKit.Mutator.Governance.Abstractions.Resolution.Strategies;
5+
using ModularityKit.Mutator.Benchmarks.Governance.Execution.Support;
6+
7+
namespace ModularityKit.Mutator.Benchmarks.Governance.Execution;
8+
9+
/// <summary>
10+
/// Benchmarks governed execution orchestration paths in the governance runtime.
11+
/// </summary>
12+
[BenchmarkCategory("Governance")]
13+
[MemoryDiagnoser]
14+
[InProcess]
15+
public class GovernedExecutionOrchestrationBenchmarks
16+
{
17+
private const string ApprovedRequestId = "governance-execution-approved";
18+
private const string StaleRequestId = "governance-execution-stale";
19+
private const string RevalidateRequestId = "governance-execution-revalidate";
20+
21+
private GovernedExecutionBenchmarkSupport.GovernedExecutionBenchmarkFixture _approvedFixture = null!;
22+
private GovernedExecutionBenchmarkSupport.GovernedExecutionBenchmarkFixture _staleFixture = null!;
23+
private GovernedExecutionBenchmarkSupport.GovernedExecutionBenchmarkFixture _revalidateFixture = null!;
24+
25+
/// <summary>
26+
/// Prepares fresh fixtures for each benchmark iteration.
27+
/// </summary>
28+
[IterationSetup]
29+
public void Setup()
30+
{
31+
_approvedFixture = GovernedExecutionBenchmarkSupport.CreateFixture(
32+
ApprovedRequestId,
33+
currentStateVersion: "v10",
34+
nextStateVersion: "v11");
35+
36+
_staleFixture = GovernedExecutionBenchmarkSupport.CreateFixture(
37+
StaleRequestId,
38+
currentStateVersion: "v15",
39+
nextStateVersion: "v16");
40+
41+
_revalidateFixture = GovernedExecutionBenchmarkSupport.CreateFixture(
42+
RevalidateRequestId,
43+
currentStateVersion: "v15",
44+
nextStateVersion: "v16");
45+
}
46+
47+
/// <summary>
48+
/// Measures an approved request executing through governed orchestration with matching state version.
49+
/// </summary>
50+
[Benchmark(Baseline = true)]
51+
public async Task ExecuteApproved_MatchingVersion()
52+
{
53+
var result = await _approvedFixture.ExecutionManager.ExecuteApproved(
54+
_approvedFixture.Request.RequestId,
55+
_approvedFixture.Mutation,
56+
_approvedFixture.State,
57+
governanceContext: _approvedFixture.Mutation.Context,
58+
strategy: VersionedRequestResolutionStrategy.RejectStale).ConfigureAwait(false);
59+
60+
GC.KeepAlive(result);
61+
}
62+
63+
/// <summary>
64+
/// Measures an approved request being rejected as stale before the core engine executes.
65+
/// </summary>
66+
[Benchmark]
67+
public async Task ExecuteApproved_RejectStale()
68+
{
69+
var result = await _staleFixture.ExecutionManager.ExecuteApproved(
70+
_staleFixture.Request.RequestId,
71+
_staleFixture.Mutation,
72+
_staleFixture.State,
73+
governanceContext: _staleFixture.Mutation.Context,
74+
strategy: VersionedRequestResolutionStrategy.RejectStale).ConfigureAwait(false);
75+
76+
GC.KeepAlive(result);
77+
}
78+
79+
/// <summary>
80+
/// Measures an approved request being revalidated against the latest state and then executed.
81+
/// </summary>
82+
[Benchmark]
83+
public async Task ExecuteApproved_RevalidateAndExecute()
84+
{
85+
var result = await _revalidateFixture.ExecutionManager.ExecuteApproved(
86+
_revalidateFixture.Request.RequestId,
87+
_revalidateFixture.Mutation,
88+
_revalidateFixture.State,
89+
governanceContext: _revalidateFixture.Mutation.Context,
90+
strategy: VersionedRequestResolutionStrategy.RevalidateOnLatestState).ConfigureAwait(false);
91+
92+
GC.KeepAlive(result);
93+
}
94+
}
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
using ModularityKit.Mutator.Abstractions.Changes;
2+
using ModularityKit.Mutator.Abstractions.Context;
3+
using ModularityKit.Mutator.Abstractions;
4+
using ModularityKit.Mutator.Abstractions.Engine;
5+
using ModularityKit.Mutator.Abstractions.Intent;
6+
using ModularityKit.Mutator.Abstractions.Policies;
7+
using ModularityKit.Mutator.Abstractions.Results;
8+
using ModularityKit.Mutator.Benchmarks.Engine;
9+
using ModularityKit.Mutator.Governance.Abstractions.Execution.Contracts;
10+
using ModularityKit.Mutator.Governance.Abstractions.Lifecycle.Model;
11+
using ModularityKit.Mutator.Governance.Abstractions.Requests.Factory;
12+
using ModularityKit.Mutator.Governance.Abstractions.Requests.Model;
13+
using ModularityKit.Mutator.Governance.Abstractions.Resolution.Strategies;
14+
using ModularityKit.Mutator.Governance.Runtime.Execution.Orchestration;
15+
using ModularityKit.Mutator.Governance.Runtime.Resolution.Execution;
16+
using ModularityKit.Mutator.Governance.Runtime.Storage;
17+
18+
namespace ModularityKit.Mutator.Benchmarks.Governance.Execution.Support;
19+
20+
/// <summary>
21+
/// Builds repeatable governed execution benchmark fixtures.
22+
/// </summary>
23+
internal static class GovernedExecutionBenchmarkSupport
24+
{
25+
public const string StateId = "governance-benchmark:execution";
26+
27+
/// <summary>
28+
/// Creates a fresh execution fixture for a single scenario run.
29+
/// </summary>
30+
public static GovernedExecutionBenchmarkFixture CreateFixture(
31+
string requestId,
32+
string currentStateVersion,
33+
string nextStateVersion)
34+
{
35+
var engine = MutationEngineBenchmarkSupport.BuildEngine(MutationEngineOptions.Strict);
36+
var store = new InMemoryMutationRequestStore();
37+
var resolutionManager = new MutationRequestVersionResolutionManager(store, new MutationRequestVersionResolver());
38+
var executionManager = new GovernanceExecutionManager(store, resolutionManager, engine);
39+
var request = store.Create(CreateApprovedRequest<GovernedExecutionState, IncrementValueMutation>(requestId))
40+
.GetAwaiter()
41+
.GetResult();
42+
43+
return new GovernedExecutionBenchmarkFixture(
44+
ExecutionManager: executionManager,
45+
Request: request,
46+
State: new GovernedExecutionState(StateId, 42, currentStateVersion),
47+
Mutation: new IncrementValueMutation(
48+
MutationContext.User("operator", "Operator", "Execute governed request"),
49+
nextStateVersion));
50+
}
51+
52+
/// <summary>
53+
/// Creates the approved request used by governed execution benchmarks.
54+
/// </summary>
55+
private static MutationRequest CreateApprovedRequest<TState, TMutation>(string requestId)
56+
where TMutation : IMutation<TState>
57+
=> MutationRequestFactory.Approved<TState, TMutation>(
58+
stateId: StateId,
59+
intent: CreateIntent(),
60+
context: MutationContext.User("requester", "Requester", "Need governed execution"),
61+
expectedStateVersion: "v10")
62+
with
63+
{
64+
RequestId = requestId
65+
};
66+
67+
/// <summary>
68+
/// Creates the intent used by governed execution scenarios.
69+
/// </summary>
70+
private static MutationIntent CreateIntent()
71+
=> new()
72+
{
73+
OperationName = "ExecuteGovernedRequest",
74+
Category = "Governance",
75+
Description = "Execute a governed request through orchestration",
76+
RiskLevel = MutationRiskLevel.Low,
77+
IsReversible = true
78+
};
79+
80+
/// <summary>
81+
/// Minimal versioned state used by governed execution benchmarks.
82+
/// </summary>
83+
/// <param name="StateId">Stable state identifier.</param>
84+
/// <param name="Value">Benchmark counter value.</param>
85+
/// <param name="Version">Current state version.</param>
86+
internal sealed record GovernedExecutionState(string StateId, int Value, string Version) : IVersionedState;
87+
88+
/// <summary>
89+
/// Minimal mutation used to measure governed execution orchestration.
90+
/// </summary>
91+
internal sealed class IncrementValueMutation(MutationContext context, string nextVersion)
92+
: IMutation<GovernedExecutionState>
93+
{
94+
public MutationIntent Intent { get; } = new()
95+
{
96+
OperationName = "IncrementGovernedValue",
97+
Category = "Governance",
98+
Description = "Increment a governed benchmark value",
99+
RiskLevel = MutationRiskLevel.Low,
100+
IsReversible = true
101+
};
102+
103+
public MutationContext Context { get; } = context;
104+
105+
public MutationResult<GovernedExecutionState> Apply(GovernedExecutionState state)
106+
{
107+
var next = state with
108+
{
109+
Value = state.Value + 1,
110+
Version = nextVersion
111+
};
112+
113+
return MutationResult<GovernedExecutionState>.Success(
114+
next,
115+
ChangeSet.Single(StateChange.Modified(nameof(GovernedExecutionState.Value), state.Value, next.Value)));
116+
}
117+
118+
public ValidationResult Validate(GovernedExecutionState state)
119+
{
120+
return state.Value < 0
121+
? ValidationResult.WithError(nameof(GovernedExecutionState.Value), "Value must be non-negative.")
122+
: ValidationResult.Success();
123+
}
124+
125+
public MutationResult<GovernedExecutionState> Simulate(GovernedExecutionState state) => Apply(state);
126+
}
127+
128+
/// <summary>
129+
/// Shared execution fixture for a benchmark scenario.
130+
/// </summary>
131+
internal sealed record GovernedExecutionBenchmarkFixture(
132+
GovernanceExecutionManager ExecutionManager,
133+
MutationRequest Request,
134+
GovernedExecutionState State,
135+
IncrementValueMutation Mutation);
136+
}

Benchmarks/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ This folder contains BenchmarkDotNet measurements for `ModularityKit.Mutator`.
1616
- mutation result creation and history/audit output materialization in the core runtime
1717
- governance approval workflow overhead in the governance runtime
1818
- governance request lifecycle overhead in the governance runtime
19+
- governance execution orchestration overhead in the governance runtime
1920

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

0 commit comments

Comments
 (0)