Skip to content

Commit 7a23245

Browse files
committed
wip: GrainStorage.AzureBlob.ReadState memory benchmark
1 parent cff1776 commit 7a23245

File tree

2 files changed

+161
-0
lines changed

2 files changed

+161
-0
lines changed
Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
using System;
2+
using System.Threading.Tasks;
3+
using Azure.Storage.Blobs;
4+
using BenchmarkDotNet.Attributes;
5+
using Microsoft.Extensions.DependencyInjection;
6+
using Microsoft.Extensions.Logging;
7+
using Microsoft.Extensions.Logging.Abstractions;
8+
using Orleans.Configuration;
9+
using Orleans.Runtime;
10+
using Orleans.Serialization;
11+
using Orleans.Serialization.Serializers;
12+
using Orleans.Storage;
13+
using TestExtensions;
14+
15+
namespace Benchmarks.GrainStorage;
16+
17+
[MemoryDiagnoser]
18+
public class AzureBlobReadStateBenchmark
19+
{
20+
private const int ReadIterations = 50;
21+
private ServiceProvider _serviceProvider = null!;
22+
private AzureBlobGrainStorage _nonPooledStorage = null!;
23+
private AzureBlobGrainStorage _pooledStorage = null!;
24+
private IGrainState<BenchmarkState> _nonPooledState = null!;
25+
private IGrainState<BenchmarkState> _pooledState = null!;
26+
private GrainId _grainId;
27+
private string _grainType = null!;
28+
private BlobContainerClient _containerClient = null!;
29+
30+
[Params(4096, 256 * 1024)]
31+
public int PayloadSize { get; set; }
32+
33+
[GlobalSetup]
34+
public async Task SetupAsync()
35+
{
36+
var client = CreateBlobServiceClient();
37+
_serviceProvider = new ServiceCollection()
38+
.AddLogging()
39+
.AddSerializer()
40+
.BuildServiceProvider();
41+
42+
var activatorProvider = _serviceProvider.GetRequiredService<IActivatorProvider>();
43+
var serializer = new OrleansGrainStorageSerializer(_serviceProvider.GetRequiredService<Serializer>());
44+
var containerName = $"bench-grainstate-{Guid.NewGuid():N}";
45+
_grainType = "bench-grain";
46+
_grainId = GrainId.Create("bench-grain", Guid.NewGuid().ToString("N"));
47+
48+
var nonPooledOptions = CreateOptions(client, serializer, containerName, usePooledReads: false);
49+
var pooledOptions = CreateOptions(client, serializer, containerName, usePooledReads: true);
50+
51+
(_nonPooledStorage, var nonPooledFactory) = CreateStorage("bench-nonpooled", nonPooledOptions, activatorProvider);
52+
(_pooledStorage, var pooledFactory) = CreateStorage("bench-pooled", pooledOptions, activatorProvider);
53+
54+
await nonPooledFactory.InitializeAsync(client);
55+
await pooledFactory.InitializeAsync(client);
56+
57+
var writeState = new GrainState<BenchmarkState>
58+
{
59+
State = BenchmarkState.Create(PayloadSize)
60+
};
61+
await _nonPooledStorage.WriteStateAsync(_grainType, _grainId, writeState);
62+
63+
_nonPooledState = new GrainState<BenchmarkState>();
64+
_pooledState = new GrainState<BenchmarkState>();
65+
_containerClient = client.GetBlobContainerClient(containerName);
66+
}
67+
68+
[GlobalCleanup]
69+
public async Task CleanupAsync()
70+
{
71+
if (_containerClient is not null)
72+
{
73+
await _containerClient.DeleteIfExistsAsync();
74+
}
75+
76+
_serviceProvider?.Dispose();
77+
}
78+
79+
[Benchmark(Baseline = true, OperationsPerInvoke = ReadIterations)]
80+
public async Task ReadStateNonPooledAsync()
81+
{
82+
for (var i = 0; i < ReadIterations; i++)
83+
{
84+
await _nonPooledStorage.ReadStateAsync(_grainType, _grainId, _nonPooledState);
85+
}
86+
}
87+
88+
[Benchmark(OperationsPerInvoke = ReadIterations)]
89+
public async Task ReadStatePooledAsync()
90+
{
91+
for (var i = 0; i < ReadIterations; i++)
92+
{
93+
await _pooledStorage.ReadStateAsync(_grainType, _grainId, _pooledState);
94+
}
95+
}
96+
97+
private static BlobServiceClient CreateBlobServiceClient()
98+
{
99+
if (TestDefaultConfiguration.UseAadAuthentication)
100+
{
101+
if (!TestDefaultConfiguration.GetValue(nameof(TestDefaultConfiguration.DataBlobUri), out var blobUriValue) ||
102+
string.IsNullOrWhiteSpace(blobUriValue))
103+
{
104+
throw new InvalidOperationException("DataBlobUri is required when UseAadAuthentication is true.");
105+
}
106+
107+
return new BlobServiceClient(new Uri(blobUriValue), TestDefaultConfiguration.TokenCredential);
108+
}
109+
110+
if (string.IsNullOrWhiteSpace(TestDefaultConfiguration.DataConnectionString))
111+
{
112+
throw new InvalidOperationException("OrleansDataConnectionString must be set for Azure Blob benchmarks.");
113+
}
114+
115+
return new BlobServiceClient(TestDefaultConfiguration.DataConnectionString);
116+
}
117+
118+
private static AzureBlobStorageOptions CreateOptions(
119+
BlobServiceClient client,
120+
IGrainStorageSerializer serializer,
121+
string containerName,
122+
bool usePooledReads)
123+
{
124+
return new AzureBlobStorageOptions
125+
{
126+
BlobServiceClient = client,
127+
ContainerName = containerName,
128+
GrainStorageSerializer = serializer,
129+
UsePooledBufferForReads = usePooledReads
130+
};
131+
}
132+
133+
private (AzureBlobGrainStorage Storage, IBlobContainerFactory Factory) CreateStorage(
134+
string name,
135+
AzureBlobStorageOptions options,
136+
IActivatorProvider activatorProvider)
137+
{
138+
var containerFactory = options.BuildContainerFactory(_serviceProvider, options);
139+
var logger = NullLoggerFactory.Instance.CreateLogger<AzureBlobGrainStorage>();
140+
var storage = new AzureBlobGrainStorage(name, options, containerFactory, activatorProvider, logger);
141+
return (storage, containerFactory);
142+
}
143+
144+
[GenerateSerializer]
145+
public sealed class BenchmarkState
146+
{
147+
[Id(0)]
148+
public byte[] Payload { get; set; } = Array.Empty<byte>();
149+
150+
public static BenchmarkState Create(int size)
151+
{
152+
var payload = new byte[size];
153+
Random.Shared.NextBytes(payload);
154+
return new BenchmarkState { Payload = payload };
155+
}
156+
}
157+
}

test/Benchmarks/Program.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,10 @@ internal class Program
260260
benchmark => benchmark.RunAsync().GetAwaiter().GetResult(),
261261
benchmark => benchmark.Teardown());
262262
},
263+
["GrainStorage.AzureBlob.ReadState"] = _ =>
264+
{
265+
BenchmarkRunner.Run<AzureBlobReadStateBenchmark>();
266+
},
263267
["GrainStorage.AdoNet"] = _ =>
264268
{
265269
RunBenchmark(

0 commit comments

Comments
 (0)