using BenchmarkDotNet.Attributes; using Apq.Cfg.Ini; using Apq.Cfg.Xml; using Apq.Cfg.Yaml; using Apq.Cfg.Toml; namespace Apq.Cfg.Benchmarks; /// /// 多源合并性能基准测试 /// 测试多个配置源叠加时的查询性能 /// [Config(typeof(BenchmarkConfig))] public class MultiSourceBenchmarks : IDisposable { private readonly string _testDir; private ICfgRoot _cfg = null!; [Params(3)] public int SourceCount { get; set; } public MultiSourceBenchmarks() { _testDir = Path.Combine(Path.GetTempPath(), $"ApqCfgBench_{Guid.NewGuid():N}"); Directory.CreateDirectory(_testDir); } [GlobalSetup] public void Setup() { var builder = new CfgBuilder(); // 根据 SourceCount 添加不同数量的配置源 for (int i = 0; i < SourceCount; i++) { var jsonPath = Path.Combine(_testDir, $"config{i}.json"); var content = $$""" { "Source{{i}}": { "Name": "Source{{i}}", "Level": {{i}} }, "Shared": { "Key": "ValueFromSource{{i}}", "Priority": {{i}} }, "Data": { "Key1": "Value1_Source{{i}}", "Key2": "Value2_Source{{i}}", "Key3": "Value3_Source{{i}}", "Key4": "Value4_Source{{i}}", "Key5": "Value5_Source{{i}}" } } """; File.WriteAllText(jsonPath, content); // 每层只有一个配置源,最高层级设为可写(作为该层的主写入源) var isHighestLevel = i == SourceCount - 1; builder.AddJson(jsonPath, level: i, writeable: isHighestLevel, isPrimaryWriter: isHighestLevel); } _cfg = builder.Build(); } [GlobalCleanup] public void Cleanup() { Dispose(); } public void Dispose() { _cfg?.Dispose(); if (Directory.Exists(_testDir)) { Directory.Delete(_testDir, true); } } #region 读取性能测试 /// /// 读取最高优先级源的键 /// [Benchmark(Baseline = true)] [BenchmarkCategory("Read")] public string? Read_HighPriorityKey() { return _cfg.Get("Source0:Name"); } /// /// 读取最低优先级源的键 /// [Benchmark] [BenchmarkCategory("Read")] public string? Read_LowPriorityKey() { var key = $"Source{SourceCount - 1}:Name"; return _cfg.Get(key); } /// /// 读取被覆盖的共享键(测试优先级合并) /// [Benchmark] [BenchmarkCategory("Read")] public string? Read_SharedKey() { return _cfg.Get("Shared:Key"); } /// /// 批量读取多个键 /// [Benchmark] [BenchmarkCategory("Read")] public void Read_MultipleKeys() { for (int i = 0; i < 100; i++) { _ = _cfg.Get("Data:Key1"); _ = _cfg.Get("Data:Key2"); _ = _cfg.Get("Data:Key3"); _ = _cfg.Get("Data:Key4"); _ = _cfg.Get("Data:Key5"); } } #endregion #region Exists 性能测试 [Benchmark] [BenchmarkCategory("Exists")] public bool Exists_HighPriorityKey() { return _cfg.Exists("Source0:Name"); } [Benchmark] [BenchmarkCategory("Exists")] public bool Exists_LowPriorityKey() { var key = $"Source{SourceCount - 1}:Name"; return _cfg.Exists(key); } [Benchmark] [BenchmarkCategory("Exists")] public bool Exists_NonExistentKey() { return _cfg.Exists("NonExistent:Key"); } [Benchmark] [BenchmarkCategory("Exists")] public void Exists_MultipleKeys() { for (int i = 0; i < 100; i++) { _ = _cfg.Exists("Data:Key1"); _ = _cfg.Exists("Data:Key2"); _ = _cfg.Exists("NonExistent:Key"); } } #endregion #region 写入性能测试 [Benchmark] [BenchmarkCategory("Write")] public void Write_NewKey() { for (int i = 0; i < 100; i++) { _cfg.Set($"NewData:Key{i}", $"Value{i}"); } } [Benchmark] [BenchmarkCategory("Write")] public void Write_OverrideKey() { for (int i = 0; i < 100; i++) { _cfg.Set("Shared:Key", $"NewValue{i}"); } } #endregion #region 类型转换性能测试 [Benchmark] [BenchmarkCategory("TypeConversion")] public int Get_Int() { return _cfg.Get("Shared:Priority"); } [Benchmark] [BenchmarkCategory("TypeConversion")] public void Get_Int_Multiple() { for (int i = 0; i < 100; i++) { _ = _cfg.Get("Shared:Priority"); } } #endregion }