using BenchmarkDotNet.Attributes;
using Apq.Cfg.Ini;
using Apq.Cfg.Xml;
using Apq.Cfg.Yaml;
using Apq.Cfg.Toml;
namespace Apq.Cfg.Benchmarks;
///
/// GetSection 性能基准测试
/// 测试不同配置源的 GetSection/GetChildKeys 操作性能
///
[Config(typeof(BenchmarkConfig))]
public class GetSectionBenchmarks : IDisposable
{
private readonly string _testDir;
private ICfgRoot _jsonCfg = null!;
private ICfgRoot _iniCfg = null!;
private ICfgRoot _xmlCfg = null!;
private ICfgRoot _yamlCfg = null!;
private ICfgRoot _tomlCfg = null!;
public GetSectionBenchmarks()
{
_testDir = Path.Combine(Path.GetTempPath(), $"ApqCfgBench_{Guid.NewGuid():N}");
Directory.CreateDirectory(_testDir);
}
[GlobalSetup]
public void Setup()
{
// 创建 JSON 配置文件(包含多层嵌套)
var jsonPath = Path.Combine(_testDir, "config.json");
File.WriteAllText(jsonPath, """
{
"Database": {
"Connection": {
"Host": "localhost",
"Port": 5432,
"Name": "testdb"
},
"Pool": {
"MinSize": 5,
"MaxSize": 100
}
},
"App": {
"Name": "BenchmarkApp",
"Version": "1.0.0",
"Settings": {
"MaxRetries": 3,
"Timeout": 30,
"Enabled": true
}
},
"Logging": {
"Level": "Info",
"Output": "Console"
}
}
""");
_jsonCfg = new CfgBuilder()
.AddJson(jsonPath, level: 0, writeable: false)
.Build();
// 创建 INI 配置文件
var iniPath = Path.Combine(_testDir, "config.ini");
File.WriteAllText(iniPath, """
[Database:Connection]
Host=localhost
Port=5432
Name=testdb
[Database:Pool]
MinSize=5
MaxSize=100
[App]
Name=BenchmarkApp
Version=1.0.0
[App:Settings]
MaxRetries=3
Timeout=30
Enabled=true
[Logging]
Level=Info
Output=Console
""");
_iniCfg = new CfgBuilder()
.AddIni(iniPath, level: 0, writeable: false)
.Build();
// 创建 XML 配置文件
var xmlPath = Path.Combine(_testDir, "config.xml");
File.WriteAllText(xmlPath, """
localhost
5432
testdb
5
100
BenchmarkApp
1.0.0
3
30
true
Info
""");
_xmlCfg = new CfgBuilder()
.AddXml(xmlPath, level: 0, writeable: false)
.Build();
// 创建 YAML 配置文件
var yamlPath = Path.Combine(_testDir, "config.yaml");
File.WriteAllText(yamlPath, """
Database:
Connection:
Host: localhost
Port: 5432
Name: testdb
Pool:
MinSize: 5
MaxSize: 100
App:
Name: BenchmarkApp
Version: 1.0.0
Settings:
MaxRetries: 3
Timeout: 30
Enabled: true
Logging:
Level: Info
Output: Console
""");
_yamlCfg = new CfgBuilder()
.AddYaml(yamlPath, level: 0, writeable: false)
.Build();
// 创建 TOML 配置文件
var tomlPath = Path.Combine(_testDir, "config.toml");
File.WriteAllText(tomlPath, """
[Database.Connection]
Host = "localhost"
Port = 5432
Name = "testdb"
[Database.Pool]
MinSize = 5
MaxSize = 100
[App]
Name = "BenchmarkApp"
Version = "1.0.0"
[App.Settings]
MaxRetries = 3
Timeout = 30
Enabled = true
[Logging]
Level = "Info"
Output = "Console"
""");
_tomlCfg = new CfgBuilder()
.AddToml(tomlPath, level: 0, writeable: false)
.Build();
}
[GlobalCleanup]
public void Cleanup()
{
Dispose();
}
public void Dispose()
{
_jsonCfg?.Dispose();
_iniCfg?.Dispose();
_xmlCfg?.Dispose();
_yamlCfg?.Dispose();
_tomlCfg?.Dispose();
if (Directory.Exists(_testDir))
{
Directory.Delete(_testDir, true);
}
}
#region GetSection 性能测试
[Benchmark(Baseline = true)]
[BenchmarkCategory("GetSection")]
public ICfgSection Json_GetSection() => _jsonCfg.GetSection("Database");
[Benchmark]
[BenchmarkCategory("GetSection")]
public ICfgSection Ini_GetSection() => _iniCfg.GetSection("Database");
[Benchmark]
[BenchmarkCategory("GetSection")]
public ICfgSection Xml_GetSection() => _xmlCfg.GetSection("Database");
[Benchmark]
[BenchmarkCategory("GetSection")]
public ICfgSection Yaml_GetSection() => _yamlCfg.GetSection("Database");
[Benchmark]
[BenchmarkCategory("GetSection")]
public ICfgSection Toml_GetSection() => _tomlCfg.GetSection("Database");
#endregion
#region GetSection 嵌套访问性能测试
[Benchmark]
[BenchmarkCategory("GetSectionNested")]
public ICfgSection Json_GetSection_Nested() => _jsonCfg.GetSection("Database").GetSection("Connection");
[Benchmark]
[BenchmarkCategory("GetSectionNested")]
public ICfgSection Ini_GetSection_Nested() => _iniCfg.GetSection("Database").GetSection("Connection");
[Benchmark]
[BenchmarkCategory("GetSectionNested")]
public ICfgSection Xml_GetSection_Nested() => _xmlCfg.GetSection("Database").GetSection("Connection");
[Benchmark]
[BenchmarkCategory("GetSectionNested")]
public ICfgSection Yaml_GetSection_Nested() => _yamlCfg.GetSection("Database").GetSection("Connection");
[Benchmark]
[BenchmarkCategory("GetSectionNested")]
public ICfgSection Toml_GetSection_Nested() => _tomlCfg.GetSection("Database").GetSection("Connection");
#endregion
#region GetSection + Get 组合性能测试
[Benchmark]
[BenchmarkCategory("GetSectionThenGet")]
public string? Json_GetSection_ThenGet() => _jsonCfg.GetSection("Database:Connection").Get("Host");
[Benchmark]
[BenchmarkCategory("GetSectionThenGet")]
public string? Ini_GetSection_ThenGet() => _iniCfg.GetSection("Database:Connection").Get("Host");
[Benchmark]
[BenchmarkCategory("GetSectionThenGet")]
public string? Xml_GetSection_ThenGet() => _xmlCfg.GetSection("Database:Connection").Get("Host");
[Benchmark]
[BenchmarkCategory("GetSectionThenGet")]
public string? Yaml_GetSection_ThenGet() => _yamlCfg.GetSection("Database:Connection").Get("Host");
[Benchmark]
[BenchmarkCategory("GetSectionThenGet")]
public string? Toml_GetSection_ThenGet() => _tomlCfg.GetSection("Database:Connection").Get("Host");
#endregion
#region GetChildKeys 性能测试
[Benchmark]
[BenchmarkCategory("GetChildKeys")]
public string[] Json_GetChildKeys() => _jsonCfg.GetChildKeys().ToArray();
[Benchmark]
[BenchmarkCategory("GetChildKeys")]
public string[] Ini_GetChildKeys() => _iniCfg.GetChildKeys().ToArray();
[Benchmark]
[BenchmarkCategory("GetChildKeys")]
public string[] Xml_GetChildKeys() => _xmlCfg.GetChildKeys().ToArray();
[Benchmark]
[BenchmarkCategory("GetChildKeys")]
public string[] Yaml_GetChildKeys() => _yamlCfg.GetChildKeys().ToArray();
[Benchmark]
[BenchmarkCategory("GetChildKeys")]
public string[] Toml_GetChildKeys() => _tomlCfg.GetChildKeys().ToArray();
#endregion
#region Section GetChildKeys 性能测试
[Benchmark]
[BenchmarkCategory("SectionGetChildKeys")]
public string[] Json_Section_GetChildKeys() => _jsonCfg.GetSection("Database").GetChildKeys().ToArray();
[Benchmark]
[BenchmarkCategory("SectionGetChildKeys")]
public string[] Ini_Section_GetChildKeys() => _iniCfg.GetSection("Database").GetChildKeys().ToArray();
[Benchmark]
[BenchmarkCategory("SectionGetChildKeys")]
public string[] Xml_Section_GetChildKeys() => _xmlCfg.GetSection("Database").GetChildKeys().ToArray();
[Benchmark]
[BenchmarkCategory("SectionGetChildKeys")]
public string[] Yaml_Section_GetChildKeys() => _yamlCfg.GetSection("Database").GetChildKeys().ToArray();
[Benchmark]
[BenchmarkCategory("SectionGetChildKeys")]
public string[] Toml_Section_GetChildKeys() => _tomlCfg.GetSection("Database").GetChildKeys().ToArray();
#endregion
#region 直接 Get vs GetSection+Get 对比
[Benchmark]
[BenchmarkCategory("DirectVsSection")]
public string? Json_DirectGet() => _jsonCfg.Get("Database:Connection:Host");
[Benchmark]
[BenchmarkCategory("DirectVsSection")]
public string? Json_SectionGet() => _jsonCfg.GetSection("Database:Connection").Get("Host");
#endregion
}