using BenchmarkDotNet.Attributes;
using Apq.Cfg.Ini;
using Apq.Cfg.Xml;
using Apq.Cfg.Yaml;
using Apq.Cfg.Toml;
namespace Apq.Cfg.Benchmarks;
///
/// 持久化性能基准测试
/// 测试 SaveAsync 在不同数据量下的性能
///
[Config(typeof(BenchmarkConfig))]
public class SaveBenchmarks : 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!;
private string _jsonPath = null!;
private string _iniPath = null!;
private string _xmlPath = null!;
private string _yamlPath = null!;
private string _tomlPath = null!;
[Params(50)]
public int ChangeCount { get; set; }
public SaveBenchmarks()
{
_testDir = Path.Combine(Path.GetTempPath(), $"ApqCfgBench_{Guid.NewGuid():N}");
Directory.CreateDirectory(_testDir);
}
[GlobalSetup]
public void Setup()
{
// 创建 JSON 配置文件
_jsonPath = Path.Combine(_testDir, "config.json");
File.WriteAllText(_jsonPath, """
{
"App": {
"Name": "BenchmarkApp"
}
}
""");
_jsonCfg = new CfgBuilder()
.AddJson(_jsonPath, level: 0, writeable: true, isPrimaryWriter: true)
.Build();
// 创建 INI 配置文件
_iniPath = Path.Combine(_testDir, "config.ini");
File.WriteAllText(_iniPath, """
[App]
Name=BenchmarkApp
""");
_iniCfg = new CfgBuilder()
.AddIni(_iniPath, level: 0, writeable: true, isPrimaryWriter: true)
.Build();
// 创建 XML 配置文件
_xmlPath = Path.Combine(_testDir, "config.xml");
File.WriteAllText(_xmlPath, """
BenchmarkApp
""");
_xmlCfg = new CfgBuilder()
.AddXml(_xmlPath, level: 0, writeable: true, isPrimaryWriter: true)
.Build();
// 创建 YAML 配置文件
_yamlPath = Path.Combine(_testDir, "config.yaml");
File.WriteAllText(_yamlPath, """
App:
Name: BenchmarkApp
""");
_yamlCfg = new CfgBuilder()
.AddYaml(_yamlPath, level: 0, writeable: true, isPrimaryWriter: true)
.Build();
// 创建 TOML 配置文件
_tomlPath = Path.Combine(_testDir, "config.toml");
File.WriteAllText(_tomlPath, """
[App]
Name = "BenchmarkApp"
""");
_tomlCfg = new CfgBuilder()
.AddToml(_tomlPath, level: 0, writeable: true, isPrimaryWriter: true)
.Build();
}
[IterationSetup]
public void IterationSetup()
{
// 每次迭代前重置配置文件,确保测试一致性
File.WriteAllText(_jsonPath, """
{
"App": {
"Name": "BenchmarkApp"
}
}
""");
File.WriteAllText(_iniPath, """
[App]
Name=BenchmarkApp
""");
File.WriteAllText(_xmlPath, """
BenchmarkApp
""");
File.WriteAllText(_yamlPath, """
App:
Name: BenchmarkApp
""");
File.WriteAllText(_tomlPath, """
[App]
Name = "BenchmarkApp"
""");
}
[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 SaveAsync 性能测试
[Benchmark(Baseline = true)]
[BenchmarkCategory("Save")]
public async Task Json_Save()
{
for (int i = 0; i < ChangeCount; i++)
{
_jsonCfg.Set($"Data:Key{i}", $"Value{i}");
}
await _jsonCfg.SaveAsync();
}
[Benchmark]
[BenchmarkCategory("Save")]
public async Task Ini_Save()
{
for (int i = 0; i < ChangeCount; i++)
{
_iniCfg.Set($"Data:Key{i}", $"Value{i}");
}
await _iniCfg.SaveAsync();
}
[Benchmark]
[BenchmarkCategory("Save")]
public async Task Xml_Save()
{
for (int i = 0; i < ChangeCount; i++)
{
_xmlCfg.Set($"Data:Key{i}", $"Value{i}");
}
await _xmlCfg.SaveAsync();
}
[Benchmark]
[BenchmarkCategory("Save")]
public async Task Yaml_Save()
{
for (int i = 0; i < ChangeCount; i++)
{
_yamlCfg.Set($"Data:Key{i}", $"Value{i}");
}
await _yamlCfg.SaveAsync();
}
[Benchmark]
[BenchmarkCategory("Save")]
public async Task Toml_Save()
{
for (int i = 0; i < ChangeCount; i++)
{
_tomlCfg.Set($"Data:Key{i}", $"Value{i}");
}
await _tomlCfg.SaveAsync();
}
#endregion
#region 大值保存测试
[Benchmark]
[BenchmarkCategory("SaveLargeValue")]
public async Task Json_SaveLargeValue()
{
var largeValue = new string('X', 10000);
for (int i = 0; i < ChangeCount / 10; i++)
{
_jsonCfg.Set($"LargeData:Key{i}", largeValue);
}
await _jsonCfg.SaveAsync();
}
[Benchmark]
[BenchmarkCategory("SaveLargeValue")]
public async Task Ini_SaveLargeValue()
{
var largeValue = new string('X', 10000);
for (int i = 0; i < ChangeCount / 10; i++)
{
_iniCfg.Set($"LargeData:Key{i}", largeValue);
}
await _iniCfg.SaveAsync();
}
#endregion
#region 频繁保存测试
[Benchmark]
[BenchmarkCategory("FrequentSave")]
public async Task Json_FrequentSave()
{
for (int i = 0; i < ChangeCount; i++)
{
_jsonCfg.Set($"Frequent:Key{i}", $"Value{i}");
if (i % 10 == 0)
{
await _jsonCfg.SaveAsync();
}
}
await _jsonCfg.SaveAsync();
}
[Benchmark]
[BenchmarkCategory("FrequentSave")]
public async Task Ini_FrequentSave()
{
for (int i = 0; i < ChangeCount; i++)
{
_iniCfg.Set($"Frequent:Key{i}", $"Value{i}");
if (i % 10 == 0)
{
await _iniCfg.SaveAsync();
}
}
await _iniCfg.SaveAsync();
}
#endregion
}