RemoveBenchmarks.cs 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330
  1. using BenchmarkDotNet.Attributes;
  2. using Apq.Cfg.Ini;
  3. using Apq.Cfg.Xml;
  4. using Apq.Cfg.Yaml;
  5. using Apq.Cfg.Toml;
  6. namespace Apq.Cfg.Benchmarks;
  7. /// <summary>
  8. /// 删除操作性能基准测试
  9. /// 测试 Remove 操作在不同场景下的性能
  10. /// </summary>
  11. [Config(typeof(BenchmarkConfig))]
  12. public class RemoveBenchmarks : IDisposable
  13. {
  14. private readonly string _testDir;
  15. private ICfgRoot _jsonCfg = null!;
  16. private ICfgRoot _iniCfg = null!;
  17. private ICfgRoot _xmlCfg = null!;
  18. private ICfgRoot _yamlCfg = null!;
  19. private ICfgRoot _tomlCfg = null!;
  20. private string _jsonPath = null!;
  21. private string _iniPath = null!;
  22. private string _xmlPath = null!;
  23. private string _yamlPath = null!;
  24. private string _tomlPath = null!;
  25. [Params(20)]
  26. public int KeyCount { get; set; }
  27. public RemoveBenchmarks()
  28. {
  29. _testDir = Path.Combine(Path.GetTempPath(), $"ApqCfgBench_{Guid.NewGuid():N}");
  30. Directory.CreateDirectory(_testDir);
  31. }
  32. [GlobalSetup]
  33. public void Setup()
  34. {
  35. _jsonPath = Path.Combine(_testDir, "config.json");
  36. _iniPath = Path.Combine(_testDir, "config.ini");
  37. _xmlPath = Path.Combine(_testDir, "config.xml");
  38. _yamlPath = Path.Combine(_testDir, "config.yaml");
  39. _tomlPath = Path.Combine(_testDir, "config.toml");
  40. ResetConfigFiles();
  41. CreateCfgInstances();
  42. }
  43. [IterationSetup]
  44. public void IterationSetup()
  45. {
  46. // 每次迭代前重置配置
  47. _jsonCfg?.Dispose();
  48. _iniCfg?.Dispose();
  49. _xmlCfg?.Dispose();
  50. _yamlCfg?.Dispose();
  51. _tomlCfg?.Dispose();
  52. ResetConfigFiles();
  53. CreateCfgInstances();
  54. }
  55. private void ResetConfigFiles()
  56. {
  57. // 生成包含多个键的 JSON 配置
  58. var jsonContent = "{\n";
  59. for (int i = 0; i < KeyCount; i++)
  60. {
  61. jsonContent += $" \"Key{i}\": \"Value{i}\"";
  62. if (i < KeyCount - 1) jsonContent += ",";
  63. jsonContent += "\n";
  64. }
  65. jsonContent += "}";
  66. File.WriteAllText(_jsonPath, jsonContent);
  67. // 生成 INI 配置
  68. var iniContent = "[Data]\n";
  69. for (int i = 0; i < KeyCount; i++)
  70. {
  71. iniContent += $"Key{i}=Value{i}\n";
  72. }
  73. File.WriteAllText(_iniPath, iniContent);
  74. // 生成 XML 配置
  75. var xmlContent = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<configuration>\n <Data>\n";
  76. for (int i = 0; i < KeyCount; i++)
  77. {
  78. xmlContent += $" <Key{i}>Value{i}</Key{i}>\n";
  79. }
  80. xmlContent += " </Data>\n</configuration>";
  81. File.WriteAllText(_xmlPath, xmlContent);
  82. // 生成 YAML 配置
  83. var yamlContent = "Data:\n";
  84. for (int i = 0; i < KeyCount; i++)
  85. {
  86. yamlContent += $" Key{i}: Value{i}\n";
  87. }
  88. File.WriteAllText(_yamlPath, yamlContent);
  89. // 生成 TOML 配置
  90. var tomlContent = "[Data]\n";
  91. for (int i = 0; i < KeyCount; i++)
  92. {
  93. tomlContent += $"Key{i} = \"Value{i}\"\n";
  94. }
  95. File.WriteAllText(_tomlPath, tomlContent);
  96. }
  97. private void CreateCfgInstances()
  98. {
  99. _jsonCfg = new CfgBuilder()
  100. .AddJson(_jsonPath, level: 0, writeable: true, isPrimaryWriter: true)
  101. .Build();
  102. _iniCfg = new CfgBuilder()
  103. .AddIni(_iniPath, level: 0, writeable: true, isPrimaryWriter: true)
  104. .Build();
  105. _xmlCfg = new CfgBuilder()
  106. .AddXml(_xmlPath, level: 0, writeable: true, isPrimaryWriter: true)
  107. .Build();
  108. _yamlCfg = new CfgBuilder()
  109. .AddYaml(_yamlPath, level: 0, writeable: true, isPrimaryWriter: true)
  110. .Build();
  111. _tomlCfg = new CfgBuilder()
  112. .AddToml(_tomlPath, level: 0, writeable: true, isPrimaryWriter: true)
  113. .Build();
  114. }
  115. [GlobalCleanup]
  116. public void Cleanup()
  117. {
  118. Dispose();
  119. }
  120. public void Dispose()
  121. {
  122. _jsonCfg?.Dispose();
  123. _iniCfg?.Dispose();
  124. _xmlCfg?.Dispose();
  125. _yamlCfg?.Dispose();
  126. _tomlCfg?.Dispose();
  127. if (Directory.Exists(_testDir))
  128. {
  129. Directory.Delete(_testDir, true);
  130. }
  131. }
  132. #region 单键删除性能测试
  133. [Benchmark(Baseline = true)]
  134. [BenchmarkCategory("RemoveSingle")]
  135. public void Json_RemoveSingle()
  136. {
  137. _jsonCfg.Remove("Key0");
  138. }
  139. [Benchmark]
  140. [BenchmarkCategory("RemoveSingle")]
  141. public void Ini_RemoveSingle()
  142. {
  143. _iniCfg.Remove("Data:Key0");
  144. }
  145. [Benchmark]
  146. [BenchmarkCategory("RemoveSingle")]
  147. public void Xml_RemoveSingle()
  148. {
  149. _xmlCfg.Remove("Data:Key0");
  150. }
  151. [Benchmark]
  152. [BenchmarkCategory("RemoveSingle")]
  153. public void Yaml_RemoveSingle()
  154. {
  155. _yamlCfg.Remove("Data:Key0");
  156. }
  157. [Benchmark]
  158. [BenchmarkCategory("RemoveSingle")]
  159. public void Toml_RemoveSingle()
  160. {
  161. _tomlCfg.Remove("Data:Key0");
  162. }
  163. #endregion
  164. #region 批量删除性能测试
  165. [Benchmark]
  166. [BenchmarkCategory("RemoveBatch")]
  167. public void Json_RemoveBatch()
  168. {
  169. for (int i = 0; i < KeyCount; i++)
  170. {
  171. _jsonCfg.Remove($"Key{i}");
  172. }
  173. }
  174. [Benchmark]
  175. [BenchmarkCategory("RemoveBatch")]
  176. public void Ini_RemoveBatch()
  177. {
  178. for (int i = 0; i < KeyCount; i++)
  179. {
  180. _iniCfg.Remove($"Data:Key{i}");
  181. }
  182. }
  183. [Benchmark]
  184. [BenchmarkCategory("RemoveBatch")]
  185. public void Xml_RemoveBatch()
  186. {
  187. for (int i = 0; i < KeyCount; i++)
  188. {
  189. _xmlCfg.Remove($"Data:Key{i}");
  190. }
  191. }
  192. [Benchmark]
  193. [BenchmarkCategory("RemoveBatch")]
  194. public void Yaml_RemoveBatch()
  195. {
  196. for (int i = 0; i < KeyCount; i++)
  197. {
  198. _yamlCfg.Remove($"Data:Key{i}");
  199. }
  200. }
  201. [Benchmark]
  202. [BenchmarkCategory("RemoveBatch")]
  203. public void Toml_RemoveBatch()
  204. {
  205. for (int i = 0; i < KeyCount; i++)
  206. {
  207. _tomlCfg.Remove($"Data:Key{i}");
  208. }
  209. }
  210. #endregion
  211. #region 删除不存在的键
  212. [Benchmark]
  213. [BenchmarkCategory("RemoveNonExistent")]
  214. public void Json_RemoveNonExistent()
  215. {
  216. for (int i = 0; i < KeyCount; i++)
  217. {
  218. _jsonCfg.Remove($"NonExistent:Key{i}");
  219. }
  220. }
  221. [Benchmark]
  222. [BenchmarkCategory("RemoveNonExistent")]
  223. public void Ini_RemoveNonExistent()
  224. {
  225. for (int i = 0; i < KeyCount; i++)
  226. {
  227. _iniCfg.Remove($"NonExistent:Key{i}");
  228. }
  229. }
  230. #endregion
  231. #region 删除后保存
  232. [Benchmark]
  233. [BenchmarkCategory("RemoveAndSave")]
  234. public async Task Json_RemoveAndSave()
  235. {
  236. for (int i = 0; i < KeyCount / 2; i++)
  237. {
  238. _jsonCfg.Remove($"Key{i}");
  239. }
  240. await _jsonCfg.SaveAsync();
  241. }
  242. [Benchmark]
  243. [BenchmarkCategory("RemoveAndSave")]
  244. public async Task Ini_RemoveAndSave()
  245. {
  246. for (int i = 0; i < KeyCount / 2; i++)
  247. {
  248. _iniCfg.Remove($"Data:Key{i}");
  249. }
  250. await _iniCfg.SaveAsync();
  251. }
  252. [Benchmark]
  253. [BenchmarkCategory("RemoveAndSave")]
  254. public async Task Xml_RemoveAndSave()
  255. {
  256. for (int i = 0; i < KeyCount / 2; i++)
  257. {
  258. _xmlCfg.Remove($"Data:Key{i}");
  259. }
  260. await _xmlCfg.SaveAsync();
  261. }
  262. [Benchmark]
  263. [BenchmarkCategory("RemoveAndSave")]
  264. public async Task Yaml_RemoveAndSave()
  265. {
  266. for (int i = 0; i < KeyCount / 2; i++)
  267. {
  268. _yamlCfg.Remove($"Data:Key{i}");
  269. }
  270. await _yamlCfg.SaveAsync();
  271. }
  272. [Benchmark]
  273. [BenchmarkCategory("RemoveAndSave")]
  274. public async Task Toml_RemoveAndSave()
  275. {
  276. for (int i = 0; i < KeyCount / 2; i++)
  277. {
  278. _tomlCfg.Remove($"Data:Key{i}");
  279. }
  280. await _tomlCfg.SaveAsync();
  281. }
  282. #endregion
  283. }