Skip to content

Commit 472a65d

Browse files
ShubhamChaturvedi7Shubham Chaturvedi
andauthored
feat: perf-test for net (#814)
Co-authored-by: Shubham Chaturvedi <[email protected]>
1 parent 1e4d0d0 commit 472a65d

File tree

8 files changed

+2232
-0
lines changed

8 files changed

+2232
-0
lines changed
Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
using System.Diagnostics;
5+
using System.Runtime;
6+
using System.Text.Json;
7+
using System.Security.Cryptography;
8+
using Microsoft.Extensions.Logging;
9+
using AWS.Cryptography.EncryptionSDK;
10+
using AWS.Cryptography.MaterialProviders;
11+
using YamlDotNet.Serialization;
12+
using YamlDotNet.Serialization.NamingConventions;
13+
using ShellProgressBar;
14+
using Newtonsoft.Json;
15+
16+
namespace EsdkBenchmark;
17+
18+
public partial class ESDKBenchmark
19+
{
20+
private readonly ILogger _logger;
21+
private readonly TestConfig _config;
22+
private readonly int _cpuCount;
23+
private readonly double _totalMemoryGb;
24+
private static readonly Random _random = new();
25+
private readonly List<BenchmarkResult> _results = new();
26+
27+
// Public properties to match Go structure
28+
public TestConfig Config => _config;
29+
public List<BenchmarkResult> Results => _results;
30+
31+
// ESDK components
32+
private MaterialProviders _materialProviders = null!;
33+
private ESDK _encryptionSdk = null!;
34+
private IKeyring _keyring = null!;
35+
36+
// Constants for memory testing
37+
private const int MemoryTestIterations = 5;
38+
private const int SamplingIntervalMs = 1;
39+
private const int GcSettleTimeMs = 5;
40+
private const int FinalSampleWaitMs = 2;
41+
42+
public ESDKBenchmark(string configPath, ILogger logger)
43+
{
44+
_logger = logger;
45+
_config = ConfigLoader.LoadConfig(configPath);
46+
47+
// Get system information
48+
_cpuCount = Environment.ProcessorCount;
49+
_totalMemoryGb = GetTotalMemoryGb();
50+
51+
// Configure GC for performance
52+
GCSettings.LatencyMode = GCLatencyMode.SustainedLowLatency;
53+
54+
// Setup ESDK
55+
var setupError = SetupEsdk();
56+
if (setupError != null)
57+
{
58+
throw new InvalidOperationException($"Failed to setup ESDK: {setupError}");
59+
}
60+
61+
_logger.LogInformation("Initialized ESDK Benchmark - CPU cores: {CpuCount}, Memory: {Memory:F1}GB",
62+
_cpuCount, _totalMemoryGb);
63+
}
64+
65+
private string? SetupEsdk()
66+
{
67+
try
68+
{
69+
_materialProviders = new MaterialProviders(new MaterialProvidersConfig());
70+
71+
// Create 256-bit AES key using .NET crypto
72+
var key = new byte[32];
73+
using (var rng = RandomNumberGenerator.Create())
74+
{
75+
rng.GetBytes(key);
76+
}
77+
78+
// Create raw AES keyring
79+
var createKeyringInput = new CreateRawAesKeyringInput
80+
{
81+
KeyNamespace = "esdk-performance-test",
82+
KeyName = "test-aes-256-key",
83+
WrappingKey = new MemoryStream(key),
84+
WrappingAlg = AesWrappingAlg.ALG_AES256_GCM_IV12_TAG16
85+
};
86+
_keyring = _materialProviders.CreateRawAesKeyring(createKeyringInput);
87+
88+
// Create ESDK client with commitment policy
89+
var esdkConfig = new AwsEncryptionSdkConfig
90+
{
91+
CommitmentPolicy = ESDKCommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT
92+
};
93+
_encryptionSdk = new ESDK(esdkConfig);
94+
95+
return null;
96+
}
97+
catch (Exception ex)
98+
{
99+
return ex.Message;
100+
}
101+
}
102+
103+
public static double GetTotalMemoryGb()
104+
{
105+
try
106+
{
107+
var gcMemoryInfo = GC.GetGCMemoryInfo();
108+
// Convert from bytes to GB
109+
return gcMemoryInfo.TotalAvailableMemoryBytes / (1024.0 * 1024.0 * 1024.0);
110+
}
111+
catch
112+
{
113+
// Fallback - estimate based on process memory
114+
return Environment.WorkingSet / (1024.0 * 1024.0 * 1024.0) * 4; // Rough estimate
115+
}
116+
}
117+
118+
private byte[] GenerateTestData(int size)
119+
{
120+
var data = new byte[size];
121+
_random.NextBytes(data);
122+
return data;
123+
}
124+
125+
126+
127+
public void RunAllBenchmarks()
128+
{
129+
_results.Clear();
130+
Console.WriteLine("Starting comprehensive ESDK benchmark suite");
131+
132+
// Combine all data sizes
133+
var dataSizes = _config.DataSizes.Small
134+
.Concat(_config.DataSizes.Medium)
135+
.Concat(_config.DataSizes.Large);
136+
137+
// Run test suites
138+
if (ConfigLoader.ShouldRunTestType(_config, "throughput"))
139+
{
140+
RunThroughputTests(dataSizes, _config.Iterations.Measurement);
141+
}
142+
else
143+
{
144+
Console.WriteLine("Skipping throughput tests (not in test_types)");
145+
}
146+
147+
if (ConfigLoader.ShouldRunTestType(_config, "memory"))
148+
{
149+
RunMemoryTests(dataSizes);
150+
}
151+
else
152+
{
153+
Console.WriteLine("Skipping memory tests (not in test_types)");
154+
}
155+
156+
if (ConfigLoader.ShouldRunTestType(_config, "concurrency"))
157+
{
158+
RunConcurrencyTests(dataSizes, _config.ConcurrencyLevels);
159+
}
160+
else
161+
{
162+
Console.WriteLine("Skipping concurrency tests (not in test_types)");
163+
}
164+
165+
Console.WriteLine($"Benchmark suite completed. Total results: {_results.Count}");
166+
}
167+
}
Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
using YamlDotNet.Serialization;
5+
using YamlDotNet.Serialization.NamingConventions;
6+
7+
namespace EsdkBenchmark;
8+
9+
public class TestConfig
10+
{
11+
[YamlMember(Alias = "data_sizes")]
12+
public DataSizes DataSizes { get; set; } = new();
13+
14+
[YamlMember(Alias = "iterations")]
15+
public IterationConfig Iterations { get; set; } = new();
16+
17+
[YamlMember(Alias = "concurrency_levels")]
18+
public List<int> ConcurrencyLevels { get; set; } = new();
19+
20+
[YamlMember(Alias = "quick_config")]
21+
public QuickConfig? QuickConfig { get; set; }
22+
}
23+
24+
public class DataSizes
25+
{
26+
[YamlMember(Alias = "small")]
27+
public List<int> Small { get; set; } = new();
28+
29+
[YamlMember(Alias = "medium")]
30+
public List<int> Medium { get; set; } = new();
31+
32+
[YamlMember(Alias = "large")]
33+
public List<int> Large { get; set; } = new();
34+
}
35+
36+
public class IterationConfig
37+
{
38+
[YamlMember(Alias = "warmup")]
39+
public int Warmup { get; set; }
40+
41+
[YamlMember(Alias = "measurement")]
42+
public int Measurement { get; set; }
43+
}
44+
45+
public class QuickConfig
46+
{
47+
[YamlMember(Alias = "data_sizes")]
48+
public QuickDataSizes DataSizes { get; set; } = new();
49+
50+
[YamlMember(Alias = "iterations")]
51+
public QuickIterationConfig Iterations { get; set; } = new();
52+
53+
[YamlMember(Alias = "concurrency_levels")]
54+
public List<int> ConcurrencyLevels { get; set; } = new();
55+
56+
[YamlMember(Alias = "test_types")]
57+
public List<string> TestTypes { get; set; } = new();
58+
}
59+
60+
public class QuickDataSizes
61+
{
62+
[YamlMember(Alias = "small")]
63+
public List<int> Small { get; set; } = new();
64+
}
65+
66+
public class QuickIterationConfig
67+
{
68+
[YamlMember(Alias = "warmup")]
69+
public int Warmup { get; set; }
70+
71+
[YamlMember(Alias = "measurement")]
72+
public int Measurement { get; set; }
73+
}
74+
75+
public static class ConfigLoader
76+
{
77+
public static TestConfig LoadConfig(string configPath)
78+
{
79+
if (!File.Exists(configPath))
80+
{
81+
throw new FileNotFoundException($"Config file not found: {configPath}");
82+
}
83+
84+
try
85+
{
86+
var yaml = File.ReadAllText(configPath);
87+
var deserializer = new DeserializerBuilder()
88+
.WithNamingConvention(UnderscoredNamingConvention.Instance)
89+
.IgnoreUnmatchedProperties()
90+
.Build();
91+
92+
return deserializer.Deserialize<TestConfig>(yaml);
93+
}
94+
catch (Exception ex)
95+
{
96+
throw new InvalidOperationException($"Failed to load config file: {ex.Message}", ex);
97+
}
98+
}
99+
100+
public static void AdjustForQuickTest(TestConfig config)
101+
{
102+
if (config.QuickConfig != null)
103+
{
104+
if (config.QuickConfig.DataSizes != null)
105+
{
106+
config.DataSizes.Small = config.QuickConfig.DataSizes.Small;
107+
config.DataSizes.Medium = new List<int>();
108+
config.DataSizes.Large = new List<int>();
109+
}
110+
111+
if (config.QuickConfig.Iterations != null)
112+
{
113+
config.Iterations.Warmup = config.QuickConfig.Iterations.Warmup;
114+
config.Iterations.Measurement = config.QuickConfig.Iterations.Measurement;
115+
}
116+
117+
if (config.QuickConfig.ConcurrencyLevels.Count > 0)
118+
{
119+
config.ConcurrencyLevels = config.QuickConfig.ConcurrencyLevels;
120+
}
121+
}
122+
}
123+
124+
public static bool ShouldRunTestType(TestConfig config, string testType)
125+
{
126+
if (config.QuickConfig != null && config.QuickConfig.TestTypes.Count > 0)
127+
{
128+
return config.QuickConfig.TestTypes.Contains(testType);
129+
}
130+
return true;
131+
}
132+
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<OutputType>Exe</OutputType>
5+
<TargetFramework>net9.0</TargetFramework>
6+
<LangVersion>13.0</LangVersion>
7+
<ImplicitUsings>enable</ImplicitUsings>
8+
<Nullable>enable</Nullable>
9+
<AssemblyName>EsdkBenchmark</AssemblyName>
10+
<RootNamespace>Amazon.Esdk.Benchmark</RootNamespace>
11+
<GenerateAssemblyInfo>true</GenerateAssemblyInfo>
12+
<AssemblyTitle>ESDK .NET Performance Benchmark</AssemblyTitle>
13+
<AssemblyDescription>Performance benchmark suite for AWS Encryption SDK .NET runtime</AssemblyDescription>
14+
<AssemblyCompany>Amazon Web Services</AssemblyCompany>
15+
<AssemblyProduct>AWS Encryption SDK</AssemblyProduct>
16+
<Copyright>Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.</Copyright>
17+
<Version>1.0.0</Version>
18+
</PropertyGroup>
19+
20+
<PropertyGroup Condition="'$(Configuration)'=='Release'">
21+
<Optimize>true</Optimize>
22+
<DebugType>portable</DebugType>
23+
<DebugSymbols>true</DebugSymbols>
24+
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
25+
</PropertyGroup>
26+
27+
<ItemGroup>
28+
<!-- ESDK and Material Providers -->
29+
<ProjectReference Include="../../../AwsEncryptionSDK/runtimes/net/ESDK.csproj" />
30+
31+
<!-- Command line parsing -->
32+
<PackageReference Include="CommandLineParser" Version="2.9.1" />
33+
34+
<!-- Configuration and serialization -->
35+
<PackageReference Include="YamlDotNet" Version="13.7.1" />
36+
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
37+
38+
<!-- Progress reporting -->
39+
<PackageReference Include="ShellProgressBar" Version="5.2.0" />
40+
41+
<!-- System information -->
42+
<PackageReference Include="System.Management" Version="6.0.0" />
43+
44+
<!-- Memory profiling -->
45+
<PackageReference Include="System.Diagnostics.PerformanceCounter" Version="6.0.0" />
46+
47+
<!-- Logging -->
48+
<PackageReference Include="Microsoft.Extensions.Logging" Version="6.0.0" />
49+
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="6.0.0" />
50+
51+
<!-- Statistics -->
52+
<PackageReference Include="MathNet.Numerics" Version="5.0.0" />
53+
54+
<!-- Async utilities -->
55+
<PackageReference Include="System.Threading.Tasks.Extensions" Version="4.5.4" />
56+
</ItemGroup>
57+
58+
<ItemGroup>
59+
<None Include="../../config/test-scenarios.yaml">
60+
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
61+
</None>
62+
</ItemGroup>
63+
64+
</Project>

0 commit comments

Comments
 (0)