ReadWriteBenchmarks.cs 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  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. /// 测试不同配置源的 Get/Set/Exists 操作性能
  10. /// </summary>
  11. [Config(typeof(BenchmarkConfig))]
  12. public class ReadWriteBenchmarks : 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 ReadWriteBenchmarks()
  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. "Host": "localhost",
  34. "Port": 5432,
  35. "Name": "testdb"
  36. },
  37. "App": {
  38. "Name": "BenchmarkApp",
  39. "Version": "1.0.0",
  40. "MaxRetries": 3,
  41. "Enabled": true
  42. }
  43. }
  44. """);
  45. _jsonCfg = new CfgBuilder()
  46. .AddJson(jsonPath, level: 0, writeable: true, isPrimaryWriter: true)
  47. .Build();
  48. // 创建 INI 配置文件
  49. var iniPath = Path.Combine(_testDir, "config.ini");
  50. File.WriteAllText(iniPath, """
  51. [Database]
  52. Host=localhost
  53. Port=5432
  54. Name=testdb
  55. [App]
  56. Name=BenchmarkApp
  57. Version=1.0.0
  58. MaxRetries=3
  59. Enabled=true
  60. """);
  61. _iniCfg = new CfgBuilder()
  62. .AddIni(iniPath, level: 0, writeable: true, isPrimaryWriter: true)
  63. .Build();
  64. // 创建 XML 配置文件
  65. var xmlPath = Path.Combine(_testDir, "config.xml");
  66. File.WriteAllText(xmlPath, """
  67. <?xml version="1.0" encoding="utf-8"?>
  68. <configuration>
  69. <Database>
  70. <Host>localhost</Host>
  71. <Port>5432</Port>
  72. <Name>testdb</Name>
  73. </Database>
  74. <App>
  75. <Name>BenchmarkApp</Name>
  76. <Version>1.0.0</Version>
  77. <MaxRetries>3</MaxRetries>
  78. <Enabled>true</Enabled>
  79. </App>
  80. </configuration>
  81. """);
  82. _xmlCfg = new CfgBuilder()
  83. .AddXml(xmlPath, level: 0, writeable: true, isPrimaryWriter: true)
  84. .Build();
  85. // 创建 YAML 配置文件
  86. var yamlPath = Path.Combine(_testDir, "config.yaml");
  87. File.WriteAllText(yamlPath, """
  88. Database:
  89. Host: localhost
  90. Port: 5432
  91. Name: testdb
  92. App:
  93. Name: BenchmarkApp
  94. Version: 1.0.0
  95. MaxRetries: 3
  96. Enabled: true
  97. """);
  98. _yamlCfg = new CfgBuilder()
  99. .AddYaml(yamlPath, level: 0, writeable: true, isPrimaryWriter: true)
  100. .Build();
  101. // 创建 TOML 配置文件
  102. var tomlPath = Path.Combine(_testDir, "config.toml");
  103. File.WriteAllText(tomlPath, """
  104. [Database]
  105. Host = "localhost"
  106. Port = 5432
  107. Name = "testdb"
  108. [App]
  109. Name = "BenchmarkApp"
  110. Version = "1.0.0"
  111. MaxRetries = 3
  112. Enabled = true
  113. """);
  114. _tomlCfg = new CfgBuilder()
  115. .AddToml(tomlPath, level: 0, writeable: true, isPrimaryWriter: true)
  116. .Build();
  117. }
  118. [GlobalCleanup]
  119. public void Cleanup()
  120. {
  121. Dispose();
  122. }
  123. public void Dispose()
  124. {
  125. _jsonCfg?.Dispose();
  126. _iniCfg?.Dispose();
  127. _xmlCfg?.Dispose();
  128. _yamlCfg?.Dispose();
  129. _tomlCfg?.Dispose();
  130. if (Directory.Exists(_testDir))
  131. {
  132. Directory.Delete(_testDir, true);
  133. }
  134. }
  135. #region Get 性能测试
  136. [Benchmark(Baseline = true)]
  137. [BenchmarkCategory("Get")]
  138. public string? Json_Get() => _jsonCfg.Get("Database:Host");
  139. [Benchmark]
  140. [BenchmarkCategory("Get")]
  141. public string? Ini_Get() => _iniCfg.Get("Database:Host");
  142. [Benchmark]
  143. [BenchmarkCategory("Get")]
  144. public string? Xml_Get() => _xmlCfg.Get("Database:Host");
  145. [Benchmark]
  146. [BenchmarkCategory("Get")]
  147. public string? Yaml_Get() => _yamlCfg.Get("Database:Host");
  148. [Benchmark]
  149. [BenchmarkCategory("Get")]
  150. public string? Toml_Get() => _tomlCfg.Get("Database:Host");
  151. #endregion
  152. #region Get<T> 类型转换性能测试
  153. [Benchmark]
  154. [BenchmarkCategory("GetTyped")]
  155. public int Json_GetInt() => _jsonCfg.Get<int>("Database:Port");
  156. [Benchmark]
  157. [BenchmarkCategory("GetTyped")]
  158. public int Ini_GetInt() => _iniCfg.Get<int>("Database:Port");
  159. [Benchmark]
  160. [BenchmarkCategory("GetTyped")]
  161. public int Xml_GetInt() => _xmlCfg.Get<int>("Database:Port");
  162. [Benchmark]
  163. [BenchmarkCategory("GetTyped")]
  164. public int Yaml_GetInt() => _yamlCfg.Get<int>("Database:Port");
  165. [Benchmark]
  166. [BenchmarkCategory("GetTyped")]
  167. public int Toml_GetInt() => _tomlCfg.Get<int>("Database:Port");
  168. #endregion
  169. #region Exists 性能测试
  170. [Benchmark]
  171. [BenchmarkCategory("Exists")]
  172. public bool Json_Exists() => _jsonCfg.Exists("Database:Host");
  173. [Benchmark]
  174. [BenchmarkCategory("Exists")]
  175. public bool Ini_Exists() => _iniCfg.Exists("Database:Host");
  176. [Benchmark]
  177. [BenchmarkCategory("Exists")]
  178. public bool Xml_Exists() => _xmlCfg.Exists("Database:Host");
  179. [Benchmark]
  180. [BenchmarkCategory("Exists")]
  181. public bool Yaml_Exists() => _yamlCfg.Exists("Database:Host");
  182. [Benchmark]
  183. [BenchmarkCategory("Exists")]
  184. public bool Toml_Exists() => _tomlCfg.Exists("Database:Host");
  185. #endregion
  186. #region Set 性能测试
  187. [Benchmark]
  188. [BenchmarkCategory("Set")]
  189. public void Json_Set() => _jsonCfg.Set("App:TempKey", "TempValue");
  190. [Benchmark]
  191. [BenchmarkCategory("Set")]
  192. public void Ini_Set() => _iniCfg.Set("App:TempKey", "TempValue");
  193. [Benchmark]
  194. [BenchmarkCategory("Set")]
  195. public void Xml_Set() => _xmlCfg.Set("App:TempKey", "TempValue");
  196. [Benchmark]
  197. [BenchmarkCategory("Set")]
  198. public void Yaml_Set() => _yamlCfg.Set("App:TempKey", "TempValue");
  199. [Benchmark]
  200. [BenchmarkCategory("Set")]
  201. public void Toml_Set() => _tomlCfg.Set("App:TempKey", "TempValue");
  202. #endregion
  203. }