Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
b743f1f
wip
ledjon-behluli Jan 5, 2025
3ef396c
wip
ledjon-behluli Feb 10, 2025
5edcd60
wip
ledjon-behluli Feb 16, 2025
07d045b
working
ledjon-behluli Mar 4, 2025
be05aae
convert tun_test back to ConcurrentPing and reorder benchmark stats
ledjon-behluli Mar 4, 2025
e7d6dca
introduced cooldown cycles
ledjon-behluli Mar 5, 2025
b4e7c37
anti-windup for integral + stop timer on deactivation of the SW + sim…
ledjon-behluli Mar 6, 2025
b9efc3e
introduced WorkerCollector and externalized from the SW
ledjon-behluli Mar 8, 2025
cea5171
lowered period from 500 -> 100 ms
ledjon-behluli Mar 9, 2025
1521841
StatelessWokerOptions
ledjon-behluli Mar 10, 2025
de45456
Merge branch 'main' into sw-adaptive
ledjon-behluli Mar 10, 2025
8846fbb
nits
ledjon-behluli Mar 10, 2025
3f16ad1
remove gitignore entries
ledjon-behluli Mar 10, 2025
c07a4ef
Update src/Orleans.Core.Abstractions/Placement/StatelessWorkerPlaceme…
ledjon-behluli Mar 10, 2025
d09508f
Update src/Orleans.Core.Abstractions/Placement/StatelessWorkerPlaceme…
ledjon-behluli Mar 10, 2025
79ffaf5
addressed comments + thread-safety on the sw context
ledjon-behluli Mar 11, 2025
8f4bc1d
made feature opt-out
ledjon-behluli Mar 14, 2025
3a15403
set RemoveIdleWorkers to 'true' by default
ledjon-behluli Mar 14, 2025
7ffe82b
attempt to fix flaky test
ledjon-behluli Mar 15, 2025
ff875b1
Fix flaky PersistenceProvider_Memory_FixedLatency_WriteRead test
ReubenBond Mar 16, 2025
c288d11
Minor fixups
ReubenBond Mar 16, 2025
ccc191c
removed backoff period and moved inspection period and idle cycles to…
ledjon-behluli Mar 17, 2025
6f8c146
moved PID logic in the main message loop
ledjon-behluli Mar 18, 2025
d7c4481
moved logic into a timer instead of task.delay
ledjon-behluli Mar 19, 2025
cab2df8
nits
ledjon-behluli Mar 19, 2025
8a298ff
cleanup
ledjon-behluli Mar 19, 2025
ca78a56
Review feedback
ReubenBond Mar 20, 2025
6d4e4cb
remove unused using
ReubenBond Mar 20, 2025
fd8f591
fix
ReubenBond Mar 20, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using Orleans.Runtime;
using System;
using System.Collections.Generic;
using System.Globalization;

namespace Orleans.Concurrency
{
Expand Down Expand Up @@ -57,14 +58,21 @@ public sealed class StatelessWorkerAttribute : PlacementAttribute, IGrainPropert
/// <summary>
/// Initializes a new instance of the <see cref="StatelessWorkerAttribute"/> class.
/// </summary>
/// <param name="maxLocalWorkers">
/// The maximum local workers.
/// </param>
/// <param name="maxLocalWorkers">The maximum local workers.</param>
public StatelessWorkerAttribute(int maxLocalWorkers)
: base(new StatelessWorkerPlacement(maxLocalWorkers))
{
}

/// <summary>
/// Initializes a new instance of the <see cref="StatelessWorkerAttribute"/> class.
/// </summary>
/// <param name="maxLocalWorkers">The maximum local workers.</param>
public StatelessWorkerAttribute(int maxLocalWorkers, bool removeIdleWorkers)
: base(new StatelessWorkerPlacement(maxLocalWorkers, removeIdleWorkers))
{
}

/// <summary>
/// Initializes a new instance of the <see cref="StatelessWorkerAttribute"/> class.
/// </summary>
Expand Down
7 changes: 6 additions & 1 deletion src/Orleans.Core.Abstractions/Core/IGrainBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -290,14 +290,19 @@ public enum DeactivationReasonCode : byte
ApplicationError,

/// <summary>
/// The application requested that this activation deactivate.
/// The application requested to deactivate this activation.
/// </summary>
ApplicationRequested,

/// <summary>
/// This activation is migrating to a new location.
/// </summary>
Migrating,

/// <summary>
/// The runtime requested to deactivate this activation.
/// </summary>
RuntimeRequested
}

internal static class DeactivationReasonCodeExtensions
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ namespace Orleans.Runtime
internal sealed class StatelessWorkerPlacement : PlacementStrategy
{
private const string MaxLocalPropertyKey = "max-local-instances";
private const string RemoveIdleWorkersPropertyKey = "remove-idle-workers";

private static readonly int DefaultMaxStatelessWorkers = Environment.ProcessorCount;

/// <inheritdoc/>
Expand All @@ -23,17 +25,38 @@ internal sealed class StatelessWorkerPlacement : PlacementStrategy
[Id(0)]
public int MaxLocal { get; private set; }

/// <summary>
/// When set to <see langword="true"/>, idle workers will be proactively deactivated by the runtime.
/// Otherwise if <see langword="false"/>, than the workers will be deactivated according to collection age.
/// </summary>
[Id(1)]
public bool RemoveIdleWorkers { get; private set; } = true;

/// <summary>
/// Initializes a new instance of the <see cref="StatelessWorkerPlacement"/> class.
/// </summary>
/// <param name="maxLocal">
/// The maximum number of local instances which can be simultaneously active for a given grain.
/// </param>
internal StatelessWorkerPlacement(int maxLocal) : this(maxLocal, true)
{
}

/// <summary>
/// Initializes a new instance of the <see cref="StatelessWorkerPlacement"/> class.
/// </summary>
/// <param name="maxLocal">
/// The maximum number of local instances which can be simultaneously active for a given grain.
/// </param>
internal StatelessWorkerPlacement(int maxLocal)
/// <param name="removeIdleWorkers">
/// Whether idle workers will be proactively deactivated by the runtime instead of only being deactivated according to collection age.
/// </param>
internal StatelessWorkerPlacement(int maxLocal, bool removeIdleWorkers)
{
// If maxLocal was not specified on the StatelessWorkerAttribute,
// we will use the defaultMaxStatelessWorkers, which is System.Environment.ProcessorCount.
this.MaxLocal = maxLocal > 0 ? maxLocal : DefaultMaxStatelessWorkers;
this.RemoveIdleWorkers = removeIdleWorkers;
}

/// <summary>
Expand All @@ -44,28 +67,39 @@ public StatelessWorkerPlacement() : this(-1)
}

/// <inheritdoc/>
public override string ToString() => $"StatelessWorkerPlacement(max={MaxLocal})";
public override string ToString() => $"StatelessWorkerPlacement(MaxLocal={MaxLocal}, RemoveIdleWorkers={RemoveIdleWorkers})";

/// <inheritdoc/>
public override void Initialize(GrainProperties properties)
{
base.Initialize(properties);
if (properties.Properties.TryGetValue(MaxLocalPropertyKey, out var value)
&& !string.IsNullOrWhiteSpace(value))

if (properties.Properties.TryGetValue(MaxLocalPropertyKey, out var maxLocalValue) &&
!string.IsNullOrWhiteSpace(maxLocalValue))
{
if (int.TryParse(maxLocalValue, out var maxLocal))
{
MaxLocal = maxLocal;
}
}

if (properties.Properties.TryGetValue(RemoveIdleWorkersPropertyKey, out var removeIdleValue) &&
!string.IsNullOrWhiteSpace(removeIdleValue))
{
if (int.TryParse(value, out var maxLocal))
if (bool.TryParse(removeIdleValue, out var removeIdle))
{
this.MaxLocal = maxLocal;
RemoveIdleWorkers = removeIdle;
}
}
}

/// <inheritdoc/>
public override void PopulateGrainProperties(IServiceProvider services, Type grainClass, GrainType grainType, Dictionary<string, string> properties)
{
properties[MaxLocalPropertyKey] = this.MaxLocal.ToString(CultureInfo.InvariantCulture);
properties[MaxLocalPropertyKey] = MaxLocal.ToString(CultureInfo.InvariantCulture);
properties[RemoveIdleWorkersPropertyKey] = RemoveIdleWorkers.ToString(CultureInfo.InvariantCulture);

base.PopulateGrainProperties(services, grainClass, grainType, properties);
}
}
}
}
20 changes: 14 additions & 6 deletions src/Orleans.Persistence.Memory/Storage/MemoryStorageWithLatency.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,9 @@ public MemoryGrainStorageWithLatency(
MemoryStorageWithLatencyOptions options,
ILoggerFactory loggerFactory,
IGrainFactory grainFactory,
IGrainStorageSerializer defaultGrainStorageSerialzier)
IGrainStorageSerializer defaultGrainStorageSerializer)
{
this.baseGranStorage = new MemoryGrainStorage(name, options, loggerFactory.CreateLogger<MemoryGrainStorage>(), grainFactory, defaultGrainStorageSerialzier);
this.baseGranStorage = new MemoryGrainStorage(name, options, loggerFactory.CreateLogger<MemoryGrainStorage>(), grainFactory, defaultGrainStorageSerializer);
this.options = options;
}

Expand Down Expand Up @@ -101,16 +101,24 @@ private async Task MakeFixedLatencyCall(Func<Task> action)
error = exc;
}

if (sw.Elapsed < this.options.Latency)
do
{
// Work out the remaining time to wait so that this operation exceeds the required Latency.
// Also adds an extra fudge factor to account for any system clock resolution edge cases.
var extraDelay = TimeSpan.FromTicks(
this.options.Latency.Ticks - sw.Elapsed.Ticks + TimeSpan.TicksPerMillisecond /* round up */ );
5 * TimeSpan.TicksPerMillisecond + this.options.Latency.Ticks - sw.Elapsed.Ticks);

await Task.Delay(extraDelay);
}
if (extraDelay > TimeSpan.Zero)
{
await Task.Delay(extraDelay);
}
else
{
break;
}
} while (true);

Debug.Assert(sw.Elapsed >= this.options.Latency, "sw.Elapsed >= this.options.Latency");
if (error != null)
{
// Wrap in AggregateException so that the original error stack trace is preserved.
Expand Down
7 changes: 7 additions & 0 deletions src/Orleans.Runtime/Catalog/GrainTypeSharedContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ public GrainTypeSharedContext(
IOptions<SiloMessagingOptions> messagingOptions,
IOptions<GrainCollectionOptions> collectionOptions,
IOptions<SchedulingOptions> schedulingOptions,
IOptions<StatelessWorkerOptions> statelessWorkerOptions,
IGrainRuntime grainRuntime,
ILoggerFactory loggerFactory,
GrainReferenceActivator grainReferenceActivator,
Expand All @@ -56,6 +57,7 @@ public GrainTypeSharedContext(
var grainDirectoryResolver = serviceProvider.GetRequiredService<GrainDirectoryResolver>();
GrainDirectory = PlacementStrategy.IsUsingGrainDirectory ? grainDirectoryResolver.Resolve(grainType) : null;
SchedulingOptions = schedulingOptions.Value;
StatelessWorkerOptions = statelessWorkerOptions.Value;
Runtime = grainRuntime;
MigrationManager = _serviceProvider.GetService<IActivationMigrationManager>();

Expand Down Expand Up @@ -181,6 +183,11 @@ public void SetComponent<TComponent>(TComponent? instance)
/// </summary>
public SchedulingOptions SchedulingOptions { get; }

/// <summary>
/// Gets the stateless worker options.
/// </summary>
public StatelessWorkerOptions StatelessWorkerOptions { get; }

/// <summary>
/// Gets the grain runtime.
/// </summary>
Expand Down
Loading