using Apq.Cfg.DependencyInjection;
using BenchmarkDotNet.Attributes;
namespace Apq.Cfg.Benchmarks;
///
/// 对象绑定性能测试
///
[MemoryDiagnoser]
[RankColumn]
public class ObjectBinderBenchmarks
{
private string _testDir = null!;
private ICfgRoot _cfg = null!;
private ICfgSection _simpleSection = null!;
private ICfgSection _nestedSection = null!;
private ICfgSection _arraySection = null!;
private ICfgSection _dictionarySection = null!;
private ICfgSection _complexSection = null!;
[GlobalSetup]
public void Setup()
{
_testDir = Path.Combine(Path.GetTempPath(), $"ApqCfgBinderBench_{Guid.NewGuid():N}");
Directory.CreateDirectory(_testDir);
var jsonPath = Path.Combine(_testDir, "config.json");
File.WriteAllText(jsonPath, """
{
"Simple": {
"Name": "TestApp",
"Port": 8080,
"Enabled": true,
"Timeout": 30.5,
"Id": "550e8400-e29b-41d4-a716-446655440000"
},
"Nested": {
"Name": "ParentApp",
"Database": {
"Host": "localhost",
"Port": 5432,
"Name": "testdb"
},
"Cache": {
"Host": "redis.local",
"Port": 6379
}
},
"Array": {
"Tags": {
"0": "tag1",
"1": "tag2",
"2": "tag3",
"3": "tag4",
"4": "tag5"
},
"Ports": {
"0": 80,
"1": 443,
"2": 8080,
"3": 8443
}
},
"Dictionary": {
"Settings": {
"Key1": "Value1",
"Key2": "Value2",
"Key3": "Value3",
"Key4": "Value4",
"Key5": "Value5"
}
},
"Complex": {
"Name": "ComplexApp",
"Endpoints": {
"0": {
"Host": "api1.local",
"Port": 8001
},
"1": {
"Host": "api2.local",
"Port": 8002
},
"2": {
"Host": "api3.local",
"Port": 8003
}
},
"Metadata": {
"version": "1.0.0",
"author": "test",
"description": "A complex configuration"
}
}
}
""");
_cfg = new CfgBuilder()
.AddJson(jsonPath, level: 0, writeable: false)
.Build();
_simpleSection = _cfg.GetSection("Simple");
_nestedSection = _cfg.GetSection("Nested");
_arraySection = _cfg.GetSection("Array");
_dictionarySection = _cfg.GetSection("Dictionary");
_complexSection = _cfg.GetSection("Complex");
}
[GlobalCleanup]
public void Cleanup()
{
(_cfg as IDisposable)?.Dispose();
if (Directory.Exists(_testDir))
{
try { Directory.Delete(_testDir, true); }
catch { }
}
}
// ========== 简单类型绑定 ==========
[Benchmark(Description = "Bind_SimpleTypes")]
public SimpleOptions Bind_SimpleTypes()
{
var options = new SimpleOptions();
ObjectBinder.BindSection(_simpleSection, options);
return options;
}
[Benchmark(Description = "Bind_SimpleTypes_100")]
public SimpleOptions Bind_SimpleTypes_100()
{
SimpleOptions options = null!;
for (int i = 0; i < 100; i++)
{
options = new SimpleOptions();
ObjectBinder.BindSection(_simpleSection, options);
}
return options;
}
// ========== 嵌套对象绑定 ==========
[Benchmark(Description = "Bind_NestedObject")]
public NestedOptions Bind_NestedObject()
{
var options = new NestedOptions();
ObjectBinder.BindSection(_nestedSection, options);
return options;
}
[Benchmark(Description = "Bind_NestedObject_100")]
public NestedOptions Bind_NestedObject_100()
{
NestedOptions options = null!;
for (int i = 0; i < 100; i++)
{
options = new NestedOptions();
ObjectBinder.BindSection(_nestedSection, options);
}
return options;
}
// ========== 数组/列表绑定 ==========
[Benchmark(Description = "Bind_Array")]
public ArrayOptions Bind_Array()
{
var options = new ArrayOptions();
ObjectBinder.BindSection(_arraySection, options);
return options;
}
[Benchmark(Description = "Bind_Array_100")]
public ArrayOptions Bind_Array_100()
{
ArrayOptions options = null!;
for (int i = 0; i < 100; i++)
{
options = new ArrayOptions();
ObjectBinder.BindSection(_arraySection, options);
}
return options;
}
// ========== 字典绑定 ==========
[Benchmark(Description = "Bind_Dictionary")]
public DictionaryOptions Bind_Dictionary()
{
var options = new DictionaryOptions();
ObjectBinder.BindSection(_dictionarySection, options);
return options;
}
[Benchmark(Description = "Bind_Dictionary_100")]
public DictionaryOptions Bind_Dictionary_100()
{
DictionaryOptions options = null!;
for (int i = 0; i < 100; i++)
{
options = new DictionaryOptions();
ObjectBinder.BindSection(_dictionarySection, options);
}
return options;
}
// ========== 复杂对象绑定 ==========
[Benchmark(Description = "Bind_ComplexObject")]
public ComplexOptions Bind_ComplexObject()
{
var options = new ComplexOptions();
ObjectBinder.BindSection(_complexSection, options);
return options;
}
[Benchmark(Description = "Bind_ComplexObject_100")]
public ComplexOptions Bind_ComplexObject_100()
{
ComplexOptions options = null!;
for (int i = 0; i < 100; i++)
{
options = new ComplexOptions();
ObjectBinder.BindSection(_complexSection, options);
}
return options;
}
// ========== 测试用选项类 ==========
public class SimpleOptions
{
public string? Name { get; set; }
public int Port { get; set; }
public bool Enabled { get; set; }
public double Timeout { get; set; }
public Guid Id { get; set; }
}
public class NestedOptions
{
public string? Name { get; set; }
public DatabaseOptions? Database { get; set; }
public CacheOptions? Cache { get; set; }
}
public class DatabaseOptions
{
public string? Host { get; set; }
public int Port { get; set; }
public string? Name { get; set; }
}
public class CacheOptions
{
public string? Host { get; set; }
public int Port { get; set; }
}
public class ArrayOptions
{
public string[]? Tags { get; set; }
public List? Ports { get; set; }
}
public class DictionaryOptions
{
public Dictionary? Settings { get; set; }
}
public class ComplexOptions
{
public string? Name { get; set; }
public List? Endpoints { get; set; }
public Dictionary? Metadata { get; set; }
}
public class EndpointOptions
{
public string? Host { get; set; }
public int Port { get; set; }
}
}