Implement scheduling system with parallel execution support and dummy job systems
This commit is contained in:
@@ -0,0 +1,47 @@
|
||||
using MoonTools.ECS;
|
||||
using Nerfed.Runtime.Scheduling;
|
||||
|
||||
namespace Nerfed.Runtime.Systems.Synthetic;
|
||||
|
||||
public sealed class DummyLongJobConsumerSystem : MoonTools.ECS.System, IParallelSystemMetadata
|
||||
{
|
||||
private readonly JobSystem jobs;
|
||||
private readonly DummyLongJobSharedState state;
|
||||
private readonly bool requireCompletion;
|
||||
|
||||
public DummyLongJobConsumerSystem(
|
||||
World world,
|
||||
DummyLongJobSharedState state,
|
||||
JobSystem jobs,
|
||||
bool requireCompletion) : base(world)
|
||||
{
|
||||
this.state = state;
|
||||
this.jobs = jobs;
|
||||
this.requireCompletion = requireCompletion;
|
||||
}
|
||||
|
||||
public string ScheduleName => nameof(DummyLongJobConsumerSystem);
|
||||
|
||||
// Consumer/apply stage is where structural world work should happen in real systems.
|
||||
public SystemAccessDeclaration AccessDeclaration => SystemAccessDeclaration.Empty;
|
||||
|
||||
public override void Update(TimeSpan delta)
|
||||
{
|
||||
JobHandle handle = state.InFlight;
|
||||
if (!handle.IsValid)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!requireCompletion && !jobs.IsCompleted(handle))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
jobs.Wait(handle);
|
||||
jobs.TryForget(handle);
|
||||
|
||||
state.InFlight = default;
|
||||
state.ConsumeCount++;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
using MoonTools.ECS;
|
||||
using Nerfed.Runtime.Scheduling;
|
||||
|
||||
namespace Nerfed.Runtime.Systems.Synthetic;
|
||||
|
||||
public sealed class DummyLongJobProducerSystem : MoonTools.ECS.System, IParallelSystemMetadata
|
||||
{
|
||||
private readonly JobSystem jobs;
|
||||
private readonly DummyLongJobSharedState state;
|
||||
private readonly TimeSpan duration;
|
||||
private readonly DummyWorkloadMode mode;
|
||||
private readonly JobDeadlineMode deadline;
|
||||
private int seed;
|
||||
|
||||
public DummyLongJobProducerSystem(
|
||||
World world,
|
||||
DummyLongJobSharedState state,
|
||||
JobSystem jobs,
|
||||
TimeSpan duration,
|
||||
DummyWorkloadMode mode,
|
||||
JobDeadlineMode deadline,
|
||||
int initialSeed = 1) : base(world)
|
||||
{
|
||||
this.state = state;
|
||||
this.jobs = jobs;
|
||||
this.duration = duration;
|
||||
this.mode = mode;
|
||||
this.deadline = deadline;
|
||||
seed = initialSeed;
|
||||
}
|
||||
|
||||
public string ScheduleName => nameof(DummyLongJobProducerSystem);
|
||||
|
||||
// Producer pattern: reads current world state and emits immutable job payload.
|
||||
public SystemAccessDeclaration AccessDeclaration => SystemAccessDeclaration.Empty;
|
||||
|
||||
public override void Update(TimeSpan delta)
|
||||
{
|
||||
if (state.InFlight.IsValid)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int capturedSeed = seed;
|
||||
state.InFlight = jobs.Submit(
|
||||
() => state.LastResult = DummyWorkloadRunner.Run(duration, mode, capturedSeed),
|
||||
deadline,
|
||||
nameof(DummyLongJobProducerSystem));
|
||||
|
||||
seed = unchecked(capturedSeed + 1);
|
||||
state.SubmitCount++;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
namespace Nerfed.Runtime.Systems.Synthetic;
|
||||
|
||||
public sealed class DummyLongJobSharedState
|
||||
{
|
||||
public JobHandle InFlight;
|
||||
public int LastResult;
|
||||
public int SubmitCount;
|
||||
public int ConsumeCount;
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
using MoonTools.ECS;
|
||||
using Nerfed.Runtime.Scheduling;
|
||||
|
||||
namespace Nerfed.Runtime.Systems.Synthetic;
|
||||
|
||||
public sealed class DummyMainThreadWorkSystem : MoonTools.ECS.System, IParallelSystemMetadata
|
||||
{
|
||||
private readonly TimeSpan duration;
|
||||
private readonly DummyWorkloadMode mode;
|
||||
private readonly string scheduleName;
|
||||
private int seed;
|
||||
|
||||
public DummyMainThreadWorkSystem(
|
||||
World world,
|
||||
TimeSpan duration,
|
||||
DummyWorkloadMode mode,
|
||||
string scheduleName,
|
||||
int initialSeed = 1) : base(world)
|
||||
{
|
||||
this.duration = duration;
|
||||
this.mode = mode;
|
||||
this.scheduleName = scheduleName;
|
||||
seed = initialSeed;
|
||||
}
|
||||
|
||||
public string ScheduleName => scheduleName;
|
||||
|
||||
public SystemAccessDeclaration AccessDeclaration => SystemAccessDeclaration.Empty;
|
||||
|
||||
public override void Update(TimeSpan delta)
|
||||
{
|
||||
seed = DummyWorkloadRunner.Run(duration, mode, seed);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
namespace Nerfed.Runtime.Systems.Synthetic;
|
||||
|
||||
public enum DummyWorkloadMode
|
||||
{
|
||||
Spin,
|
||||
Sleep,
|
||||
Compute,
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace Nerfed.Runtime.Systems.Synthetic;
|
||||
|
||||
internal static class DummyWorkloadRunner
|
||||
{
|
||||
public static int Run(TimeSpan duration, DummyWorkloadMode mode, int seed)
|
||||
{
|
||||
return mode switch
|
||||
{
|
||||
DummyWorkloadMode.Sleep => Sleep(duration, seed),
|
||||
DummyWorkloadMode.Compute => Compute(duration, seed),
|
||||
_ => Spin(duration, seed),
|
||||
};
|
||||
}
|
||||
|
||||
private static int Sleep(TimeSpan duration, int seed)
|
||||
{
|
||||
if (duration > TimeSpan.Zero)
|
||||
{
|
||||
Thread.Sleep(duration);
|
||||
}
|
||||
|
||||
return seed;
|
||||
}
|
||||
|
||||
private static int Spin(TimeSpan duration, int seed)
|
||||
{
|
||||
Stopwatch stopwatch = Stopwatch.StartNew();
|
||||
int value = seed;
|
||||
while (stopwatch.Elapsed < duration)
|
||||
{
|
||||
value = unchecked((value * 1664525) + 1013904223);
|
||||
Thread.SpinWait(128);
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
private static int Compute(TimeSpan duration, int seed)
|
||||
{
|
||||
Stopwatch stopwatch = Stopwatch.StartNew();
|
||||
int value = seed;
|
||||
while (stopwatch.Elapsed < duration)
|
||||
{
|
||||
for (int i = 0; i < 2048; i++)
|
||||
{
|
||||
value = unchecked((value << 5) - value + i);
|
||||
}
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user