KeyPathBenchmarks.cs 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  1. using BenchmarkDotNet.Attributes;
  2. namespace Apq.Cfg.Benchmarks;
  3. /// <summary>
  4. /// 键路径深度性能基准测试
  5. /// 测试不同深度的键路径解析性能
  6. /// </summary>
  7. [Config(typeof(BenchmarkConfig))]
  8. public class KeyPathBenchmarks : IDisposable
  9. {
  10. private readonly string _testDir;
  11. private ICfgRoot _cfg = null!;
  12. [Params(5)]
  13. public int PathDepth { get; set; }
  14. private string _deepKey = null!;
  15. private string _nonExistentDeepKey = null!;
  16. public KeyPathBenchmarks()
  17. {
  18. _testDir = Path.Combine(Path.GetTempPath(), $"ApqCfgBench_{Guid.NewGuid():N}");
  19. Directory.CreateDirectory(_testDir);
  20. }
  21. [GlobalSetup]
  22. public void Setup()
  23. {
  24. var jsonPath = Path.Combine(_testDir, "config.json");
  25. // 生成深层嵌套的 JSON 结构
  26. var content = GenerateNestedJson(PathDepth);
  27. File.WriteAllText(jsonPath, content);
  28. _cfg = new CfgBuilder()
  29. .AddJson(jsonPath, level: 0, writeable: true, isPrimaryWriter: true)
  30. .Build();
  31. // 生成对应深度的键路径
  32. _deepKey = GenerateKeyPath(PathDepth);
  33. _nonExistentDeepKey = GenerateKeyPath(PathDepth) + ":NonExistent";
  34. }
  35. private static string GenerateNestedJson(int depth)
  36. {
  37. if (depth <= 0) return "{}";
  38. var indent = new string(' ', 2);
  39. var result = "{\n";
  40. void AddLevel(int currentDepth, int indentLevel)
  41. {
  42. var currentIndent = new string(' ', indentLevel * 2);
  43. var levelName = $"Level{currentDepth}";
  44. if (currentDepth == depth)
  45. {
  46. result += $"{currentIndent}\"{levelName}\": {{\n";
  47. result += $"{currentIndent} \"Value\": \"DeepValue\",\n";
  48. result += $"{currentIndent} \"Number\": 12345,\n";
  49. result += $"{currentIndent} \"Boolean\": true\n";
  50. result += $"{currentIndent}}}";
  51. }
  52. else
  53. {
  54. result += $"{currentIndent}\"{levelName}\": {{\n";
  55. AddLevel(currentDepth + 1, indentLevel + 1);
  56. result += $"\n{currentIndent}}}";
  57. }
  58. }
  59. AddLevel(1, 1);
  60. result += "\n}";
  61. return result;
  62. }
  63. private static string GenerateKeyPath(int depth)
  64. {
  65. var parts = new string[depth + 1];
  66. for (int i = 0; i < depth; i++)
  67. {
  68. parts[i] = $"Level{i + 1}";
  69. }
  70. parts[depth] = "Value";
  71. return string.Join(":", parts);
  72. }
  73. [GlobalCleanup]
  74. public void Cleanup()
  75. {
  76. Dispose();
  77. }
  78. public void Dispose()
  79. {
  80. _cfg?.Dispose();
  81. if (Directory.Exists(_testDir))
  82. {
  83. Directory.Delete(_testDir, true);
  84. }
  85. }
  86. #region 深层键读取性能测试
  87. /// <summary>
  88. /// 读取深层嵌套的键
  89. /// </summary>
  90. [Benchmark(Baseline = true)]
  91. [BenchmarkCategory("DeepRead")]
  92. public string? Get_DeepKey()
  93. {
  94. return _cfg.Get(_deepKey);
  95. }
  96. /// <summary>
  97. /// 批量读取深层键
  98. /// </summary>
  99. [Benchmark]
  100. [BenchmarkCategory("DeepRead")]
  101. public void Get_DeepKey_Multiple()
  102. {
  103. for (int i = 0; i < 1000; i++)
  104. {
  105. _ = _cfg.Get(_deepKey);
  106. }
  107. }
  108. /// <summary>
  109. /// 读取深层键并转换类型
  110. /// </summary>
  111. [Benchmark]
  112. [BenchmarkCategory("DeepRead")]
  113. public int Get_DeepKey_Int()
  114. {
  115. var numberKey = _deepKey.Replace(":Value", ":Number");
  116. return _cfg.Get<int>(numberKey);
  117. }
  118. /// <summary>
  119. /// 读取深层键并转换为布尔值
  120. /// </summary>
  121. [Benchmark]
  122. [BenchmarkCategory("DeepRead")]
  123. public bool Get_DeepKey_Bool()
  124. {
  125. var boolKey = _deepKey.Replace(":Value", ":Boolean");
  126. return _cfg.Get<bool>(boolKey);
  127. }
  128. #endregion
  129. #region 深层键存在性检查
  130. /// <summary>
  131. /// 检查深层键是否存在
  132. /// </summary>
  133. [Benchmark]
  134. [BenchmarkCategory("DeepExists")]
  135. public bool Exists_DeepKey()
  136. {
  137. return _cfg.Exists(_deepKey);
  138. }
  139. /// <summary>
  140. /// 检查不存在的深层键
  141. /// </summary>
  142. [Benchmark]
  143. [BenchmarkCategory("DeepExists")]
  144. public bool Exists_NonExistentDeepKey()
  145. {
  146. return _cfg.Exists(_nonExistentDeepKey);
  147. }
  148. /// <summary>
  149. /// 批量检查深层键存在性
  150. /// </summary>
  151. [Benchmark]
  152. [BenchmarkCategory("DeepExists")]
  153. public void Exists_DeepKey_Multiple()
  154. {
  155. for (int i = 0; i < 1000; i++)
  156. {
  157. _ = _cfg.Exists(_deepKey);
  158. _ = _cfg.Exists(_nonExistentDeepKey);
  159. }
  160. }
  161. #endregion
  162. #region 深层键写入性能测试
  163. /// <summary>
  164. /// 写入深层键
  165. /// </summary>
  166. [Benchmark]
  167. [BenchmarkCategory("DeepWrite")]
  168. public void Set_DeepKey()
  169. {
  170. _cfg.Set(_deepKey, "NewDeepValue");
  171. }
  172. /// <summary>
  173. /// 批量写入深层键
  174. /// </summary>
  175. [Benchmark]
  176. [BenchmarkCategory("DeepWrite")]
  177. public void Set_DeepKey_Multiple()
  178. {
  179. for (int i = 0; i < 100; i++)
  180. {
  181. _cfg.Set(_deepKey, $"NewDeepValue{i}");
  182. }
  183. }
  184. /// <summary>
  185. /// 创建新的深层键
  186. /// </summary>
  187. [Benchmark]
  188. [BenchmarkCategory("DeepWrite")]
  189. public void Set_NewDeepKey()
  190. {
  191. for (int i = 0; i < 100; i++)
  192. {
  193. var newKey = _deepKey.Replace(":Value", $":NewKey{i}");
  194. _cfg.Set(newKey, $"NewValue{i}");
  195. }
  196. }
  197. #endregion
  198. #region 浅层 vs 深层对比
  199. /// <summary>
  200. /// 读取浅层键(1层)作为对比基准
  201. /// </summary>
  202. [Benchmark]
  203. [BenchmarkCategory("Comparison")]
  204. public string? Get_ShallowKey()
  205. {
  206. return _cfg.Get("Level1:Value");
  207. }
  208. /// <summary>
  209. /// 批量读取浅层键
  210. /// </summary>
  211. [Benchmark]
  212. [BenchmarkCategory("Comparison")]
  213. public void Get_ShallowKey_Multiple()
  214. {
  215. for (int i = 0; i < 1000; i++)
  216. {
  217. _ = _cfg.Get("Level1:Value");
  218. }
  219. }
  220. #endregion
  221. }