GetSectionBenchmarks.cs 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337
  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. /// GetSection 性能基准测试
  9. /// 测试不同配置源的 GetSection/GetChildKeys 操作性能
  10. /// </summary>
  11. [Config(typeof(BenchmarkConfig))]
  12. public class GetSectionBenchmarks : 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. public GetSectionBenchmarks()
  21. {
  22. _testDir = Path.Combine(Path.GetTempPath(), $"ApqCfgBench_{Guid.NewGuid():N}");
  23. Directory.CreateDirectory(_testDir);
  24. }
  25. [GlobalSetup]
  26. public void Setup()
  27. {
  28. // 创建 JSON 配置文件(包含多层嵌套)
  29. var jsonPath = Path.Combine(_testDir, "config.json");
  30. File.WriteAllText(jsonPath, """
  31. {
  32. "Database": {
  33. "Connection": {
  34. "Host": "localhost",
  35. "Port": 5432,
  36. "Name": "testdb"
  37. },
  38. "Pool": {
  39. "MinSize": 5,
  40. "MaxSize": 100
  41. }
  42. },
  43. "App": {
  44. "Name": "BenchmarkApp",
  45. "Version": "1.0.0",
  46. "Settings": {
  47. "MaxRetries": 3,
  48. "Timeout": 30,
  49. "Enabled": true
  50. }
  51. },
  52. "Logging": {
  53. "Level": "Info",
  54. "Output": "Console"
  55. }
  56. }
  57. """);
  58. _jsonCfg = new CfgBuilder()
  59. .AddJson(jsonPath, level: 0, writeable: false)
  60. .Build();
  61. // 创建 INI 配置文件
  62. var iniPath = Path.Combine(_testDir, "config.ini");
  63. File.WriteAllText(iniPath, """
  64. [Database:Connection]
  65. Host=localhost
  66. Port=5432
  67. Name=testdb
  68. [Database:Pool]
  69. MinSize=5
  70. MaxSize=100
  71. [App]
  72. Name=BenchmarkApp
  73. Version=1.0.0
  74. [App:Settings]
  75. MaxRetries=3
  76. Timeout=30
  77. Enabled=true
  78. [Logging]
  79. Level=Info
  80. Output=Console
  81. """);
  82. _iniCfg = new CfgBuilder()
  83. .AddIni(iniPath, level: 0, writeable: false)
  84. .Build();
  85. // 创建 XML 配置文件
  86. var xmlPath = Path.Combine(_testDir, "config.xml");
  87. File.WriteAllText(xmlPath, """
  88. <?xml version="1.0" encoding="utf-8"?>
  89. <configuration>
  90. <Database>
  91. <Connection>
  92. <Host>localhost</Host>
  93. <Port>5432</Port>
  94. <Name>testdb</Name>
  95. </Connection>
  96. <Pool>
  97. <MinSize>5</MinSize>
  98. <MaxSize>100</MaxSize>
  99. </Pool>
  100. </Database>
  101. <App>
  102. <Name>BenchmarkApp</Name>
  103. <Version>1.0.0</Version>
  104. <Settings>
  105. <MaxRetries>3</MaxRetries>
  106. <Timeout>30</Timeout>
  107. <Enabled>true</Enabled>
  108. </Settings>
  109. </App>
  110. <Logging>
  111. <Level>Info</Level>
  112. <Output>Console</Output>
  113. </Logging>
  114. </configuration>
  115. """);
  116. _xmlCfg = new CfgBuilder()
  117. .AddXml(xmlPath, level: 0, writeable: false)
  118. .Build();
  119. // 创建 YAML 配置文件
  120. var yamlPath = Path.Combine(_testDir, "config.yaml");
  121. File.WriteAllText(yamlPath, """
  122. Database:
  123. Connection:
  124. Host: localhost
  125. Port: 5432
  126. Name: testdb
  127. Pool:
  128. MinSize: 5
  129. MaxSize: 100
  130. App:
  131. Name: BenchmarkApp
  132. Version: 1.0.0
  133. Settings:
  134. MaxRetries: 3
  135. Timeout: 30
  136. Enabled: true
  137. Logging:
  138. Level: Info
  139. Output: Console
  140. """);
  141. _yamlCfg = new CfgBuilder()
  142. .AddYaml(yamlPath, level: 0, writeable: false)
  143. .Build();
  144. // 创建 TOML 配置文件
  145. var tomlPath = Path.Combine(_testDir, "config.toml");
  146. File.WriteAllText(tomlPath, """
  147. [Database.Connection]
  148. Host = "localhost"
  149. Port = 5432
  150. Name = "testdb"
  151. [Database.Pool]
  152. MinSize = 5
  153. MaxSize = 100
  154. [App]
  155. Name = "BenchmarkApp"
  156. Version = "1.0.0"
  157. [App.Settings]
  158. MaxRetries = 3
  159. Timeout = 30
  160. Enabled = true
  161. [Logging]
  162. Level = "Info"
  163. Output = "Console"
  164. """);
  165. _tomlCfg = new CfgBuilder()
  166. .AddToml(tomlPath, level: 0, writeable: false)
  167. .Build();
  168. }
  169. [GlobalCleanup]
  170. public void Cleanup()
  171. {
  172. Dispose();
  173. }
  174. public void Dispose()
  175. {
  176. _jsonCfg?.Dispose();
  177. _iniCfg?.Dispose();
  178. _xmlCfg?.Dispose();
  179. _yamlCfg?.Dispose();
  180. _tomlCfg?.Dispose();
  181. if (Directory.Exists(_testDir))
  182. {
  183. Directory.Delete(_testDir, true);
  184. }
  185. }
  186. #region GetSection 性能测试
  187. [Benchmark(Baseline = true)]
  188. [BenchmarkCategory("GetSection")]
  189. public ICfgSection Json_GetSection() => _jsonCfg.GetSection("Database");
  190. [Benchmark]
  191. [BenchmarkCategory("GetSection")]
  192. public ICfgSection Ini_GetSection() => _iniCfg.GetSection("Database");
  193. [Benchmark]
  194. [BenchmarkCategory("GetSection")]
  195. public ICfgSection Xml_GetSection() => _xmlCfg.GetSection("Database");
  196. [Benchmark]
  197. [BenchmarkCategory("GetSection")]
  198. public ICfgSection Yaml_GetSection() => _yamlCfg.GetSection("Database");
  199. [Benchmark]
  200. [BenchmarkCategory("GetSection")]
  201. public ICfgSection Toml_GetSection() => _tomlCfg.GetSection("Database");
  202. #endregion
  203. #region GetSection 嵌套访问性能测试
  204. [Benchmark]
  205. [BenchmarkCategory("GetSectionNested")]
  206. public ICfgSection Json_GetSection_Nested() => _jsonCfg.GetSection("Database").GetSection("Connection");
  207. [Benchmark]
  208. [BenchmarkCategory("GetSectionNested")]
  209. public ICfgSection Ini_GetSection_Nested() => _iniCfg.GetSection("Database").GetSection("Connection");
  210. [Benchmark]
  211. [BenchmarkCategory("GetSectionNested")]
  212. public ICfgSection Xml_GetSection_Nested() => _xmlCfg.GetSection("Database").GetSection("Connection");
  213. [Benchmark]
  214. [BenchmarkCategory("GetSectionNested")]
  215. public ICfgSection Yaml_GetSection_Nested() => _yamlCfg.GetSection("Database").GetSection("Connection");
  216. [Benchmark]
  217. [BenchmarkCategory("GetSectionNested")]
  218. public ICfgSection Toml_GetSection_Nested() => _tomlCfg.GetSection("Database").GetSection("Connection");
  219. #endregion
  220. #region GetSection + Get 组合性能测试
  221. [Benchmark]
  222. [BenchmarkCategory("GetSectionThenGet")]
  223. public string? Json_GetSection_ThenGet() => _jsonCfg.GetSection("Database:Connection").Get("Host");
  224. [Benchmark]
  225. [BenchmarkCategory("GetSectionThenGet")]
  226. public string? Ini_GetSection_ThenGet() => _iniCfg.GetSection("Database:Connection").Get("Host");
  227. [Benchmark]
  228. [BenchmarkCategory("GetSectionThenGet")]
  229. public string? Xml_GetSection_ThenGet() => _xmlCfg.GetSection("Database:Connection").Get("Host");
  230. [Benchmark]
  231. [BenchmarkCategory("GetSectionThenGet")]
  232. public string? Yaml_GetSection_ThenGet() => _yamlCfg.GetSection("Database:Connection").Get("Host");
  233. [Benchmark]
  234. [BenchmarkCategory("GetSectionThenGet")]
  235. public string? Toml_GetSection_ThenGet() => _tomlCfg.GetSection("Database:Connection").Get("Host");
  236. #endregion
  237. #region GetChildKeys 性能测试
  238. [Benchmark]
  239. [BenchmarkCategory("GetChildKeys")]
  240. public string[] Json_GetChildKeys() => _jsonCfg.GetChildKeys().ToArray();
  241. [Benchmark]
  242. [BenchmarkCategory("GetChildKeys")]
  243. public string[] Ini_GetChildKeys() => _iniCfg.GetChildKeys().ToArray();
  244. [Benchmark]
  245. [BenchmarkCategory("GetChildKeys")]
  246. public string[] Xml_GetChildKeys() => _xmlCfg.GetChildKeys().ToArray();
  247. [Benchmark]
  248. [BenchmarkCategory("GetChildKeys")]
  249. public string[] Yaml_GetChildKeys() => _yamlCfg.GetChildKeys().ToArray();
  250. [Benchmark]
  251. [BenchmarkCategory("GetChildKeys")]
  252. public string[] Toml_GetChildKeys() => _tomlCfg.GetChildKeys().ToArray();
  253. #endregion
  254. #region Section GetChildKeys 性能测试
  255. [Benchmark]
  256. [BenchmarkCategory("SectionGetChildKeys")]
  257. public string[] Json_Section_GetChildKeys() => _jsonCfg.GetSection("Database").GetChildKeys().ToArray();
  258. [Benchmark]
  259. [BenchmarkCategory("SectionGetChildKeys")]
  260. public string[] Ini_Section_GetChildKeys() => _iniCfg.GetSection("Database").GetChildKeys().ToArray();
  261. [Benchmark]
  262. [BenchmarkCategory("SectionGetChildKeys")]
  263. public string[] Xml_Section_GetChildKeys() => _xmlCfg.GetSection("Database").GetChildKeys().ToArray();
  264. [Benchmark]
  265. [BenchmarkCategory("SectionGetChildKeys")]
  266. public string[] Yaml_Section_GetChildKeys() => _yamlCfg.GetSection("Database").GetChildKeys().ToArray();
  267. [Benchmark]
  268. [BenchmarkCategory("SectionGetChildKeys")]
  269. public string[] Toml_Section_GetChildKeys() => _tomlCfg.GetSection("Database").GetChildKeys().ToArray();
  270. #endregion
  271. #region 直接 Get vs GetSection+Get 对比
  272. [Benchmark]
  273. [BenchmarkCategory("DirectVsSection")]
  274. public string? Json_DirectGet() => _jsonCfg.Get("Database:Connection:Host");
  275. [Benchmark]
  276. [BenchmarkCategory("DirectVsSection")]
  277. public string? Json_SectionGet() => _jsonCfg.GetSection("Database:Connection").Get("Host");
  278. #endregion
  279. }