ReadWriteBenchmarks.cs 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278
  1. using BenchmarkDotNet.Attributes;
  2. using Apq.Cfg.Env;
  3. using Apq.Cfg.Ini;
  4. using Apq.Cfg.Xml;
  5. using Apq.Cfg.Yaml;
  6. using Apq.Cfg.Toml;
  7. namespace Apq.Cfg.Benchmarks;
  8. /// <summary>
  9. /// 读写性能基准测试
  10. /// 测试不同配置源的 Get/Set/Exists 操作性能
  11. /// </summary>
  12. [Config(typeof(BenchmarkConfig))]
  13. public class ReadWriteBenchmarks : IDisposable
  14. {
  15. private readonly string _testDir;
  16. private ICfgRoot _jsonCfg = null!;
  17. private ICfgRoot _envCfg = null!;
  18. private ICfgRoot _iniCfg = null!;
  19. private ICfgRoot _xmlCfg = null!;
  20. private ICfgRoot _yamlCfg = null!;
  21. private ICfgRoot _tomlCfg = null!;
  22. public ReadWriteBenchmarks()
  23. {
  24. _testDir = Path.Combine(Path.GetTempPath(), $"ApqCfgBench_{Guid.NewGuid():N}");
  25. Directory.CreateDirectory(_testDir);
  26. }
  27. [GlobalSetup]
  28. public void Setup()
  29. {
  30. // 创建 JSON 配置文件
  31. var jsonPath = Path.Combine(_testDir, "config.json");
  32. File.WriteAllText(jsonPath, """
  33. {
  34. "Database": {
  35. "Host": "localhost",
  36. "Port": 5432,
  37. "Name": "testdb"
  38. },
  39. "App": {
  40. "Name": "BenchmarkApp",
  41. "Version": "1.0.0",
  42. "MaxRetries": 3,
  43. "Enabled": true
  44. }
  45. }
  46. """);
  47. _jsonCfg = new CfgBuilder()
  48. .AddJson(jsonPath, level: 0, writeable: true, isPrimaryWriter: true)
  49. .Build();
  50. // 创建 .env 配置文件
  51. var envPath = Path.Combine(_testDir, ".env");
  52. File.WriteAllText(envPath, """
  53. DATABASE_HOST=localhost
  54. DATABASE_PORT=5432
  55. DATABASE_NAME=testdb
  56. APP_NAME=BenchmarkApp
  57. APP_VERSION=1.0.0
  58. APP_MAXRETRIES=3
  59. APP_ENABLED=true
  60. """);
  61. _envCfg = new CfgBuilder()
  62. .AddEnv(envPath, level: 0, writeable: true, isPrimaryWriter: true)
  63. .Build();
  64. // 创建 INI 配置文件
  65. var iniPath = Path.Combine(_testDir, "config.ini");
  66. File.WriteAllText(iniPath, """
  67. [Database]
  68. Host=localhost
  69. Port=5432
  70. Name=testdb
  71. [App]
  72. Name=BenchmarkApp
  73. Version=1.0.0
  74. MaxRetries=3
  75. Enabled=true
  76. """);
  77. _iniCfg = new CfgBuilder()
  78. .AddIni(iniPath, level: 0, writeable: true, isPrimaryWriter: true)
  79. .Build();
  80. // 创建 XML 配置文件
  81. var xmlPath = Path.Combine(_testDir, "config.xml");
  82. File.WriteAllText(xmlPath, """
  83. <?xml version="1.0" encoding="utf-8"?>
  84. <configuration>
  85. <Database>
  86. <Host>localhost</Host>
  87. <Port>5432</Port>
  88. <Name>testdb</Name>
  89. </Database>
  90. <App>
  91. <Name>BenchmarkApp</Name>
  92. <Version>1.0.0</Version>
  93. <MaxRetries>3</MaxRetries>
  94. <Enabled>true</Enabled>
  95. </App>
  96. </configuration>
  97. """);
  98. _xmlCfg = new CfgBuilder()
  99. .AddXml(xmlPath, level: 0, writeable: true, isPrimaryWriter: true)
  100. .Build();
  101. // 创建 YAML 配置文件
  102. var yamlPath = Path.Combine(_testDir, "config.yaml");
  103. File.WriteAllText(yamlPath, """
  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. _yamlCfg = new CfgBuilder()
  115. .AddYaml(yamlPath, level: 0, writeable: true, isPrimaryWriter: true)
  116. .Build();
  117. // 创建 TOML 配置文件
  118. var tomlPath = Path.Combine(_testDir, "config.toml");
  119. File.WriteAllText(tomlPath, """
  120. [Database]
  121. Host = "localhost"
  122. Port = 5432
  123. Name = "testdb"
  124. [App]
  125. Name = "BenchmarkApp"
  126. Version = "1.0.0"
  127. MaxRetries = 3
  128. Enabled = true
  129. """);
  130. _tomlCfg = new CfgBuilder()
  131. .AddToml(tomlPath, level: 0, writeable: true, isPrimaryWriter: true)
  132. .Build();
  133. }
  134. [GlobalCleanup]
  135. public void Cleanup()
  136. {
  137. Dispose();
  138. }
  139. public void Dispose()
  140. {
  141. _jsonCfg?.Dispose();
  142. _envCfg?.Dispose();
  143. _iniCfg?.Dispose();
  144. _xmlCfg?.Dispose();
  145. _yamlCfg?.Dispose();
  146. _tomlCfg?.Dispose();
  147. if (Directory.Exists(_testDir))
  148. {
  149. Directory.Delete(_testDir, true);
  150. }
  151. }
  152. #region Get 性能测试
  153. [Benchmark(Baseline = true)]
  154. [BenchmarkCategory("Get")]
  155. public string? Json_Get() => _jsonCfg.Get("Database:Host");
  156. [Benchmark]
  157. [BenchmarkCategory("Get")]
  158. public string? Env_Get() => _envCfg.Get("DATABASE_HOST");
  159. [Benchmark]
  160. [BenchmarkCategory("Get")]
  161. public string? Ini_Get() => _iniCfg.Get("Database:Host");
  162. [Benchmark]
  163. [BenchmarkCategory("Get")]
  164. public string? Xml_Get() => _xmlCfg.Get("Database:Host");
  165. [Benchmark]
  166. [BenchmarkCategory("Get")]
  167. public string? Yaml_Get() => _yamlCfg.Get("Database:Host");
  168. [Benchmark]
  169. [BenchmarkCategory("Get")]
  170. public string? Toml_Get() => _tomlCfg.Get("Database:Host");
  171. #endregion
  172. #region Get<T> 类型转换性能测试
  173. [Benchmark]
  174. [BenchmarkCategory("GetTyped")]
  175. public int Json_GetInt() => _jsonCfg.Get<int>("Database:Port");
  176. [Benchmark]
  177. [BenchmarkCategory("GetTyped")]
  178. public int Env_GetInt() => _envCfg.Get<int>("DATABASE_PORT");
  179. [Benchmark]
  180. [BenchmarkCategory("GetTyped")]
  181. public int Ini_GetInt() => _iniCfg.Get<int>("Database:Port");
  182. [Benchmark]
  183. [BenchmarkCategory("GetTyped")]
  184. public int Xml_GetInt() => _xmlCfg.Get<int>("Database:Port");
  185. [Benchmark]
  186. [BenchmarkCategory("GetTyped")]
  187. public int Yaml_GetInt() => _yamlCfg.Get<int>("Database:Port");
  188. [Benchmark]
  189. [BenchmarkCategory("GetTyped")]
  190. public int Toml_GetInt() => _tomlCfg.Get<int>("Database:Port");
  191. #endregion
  192. #region Exists 性能测试
  193. [Benchmark]
  194. [BenchmarkCategory("Exists")]
  195. public bool Json_Exists() => _jsonCfg.Exists("Database:Host");
  196. [Benchmark]
  197. [BenchmarkCategory("Exists")]
  198. public bool Env_Exists() => _envCfg.Exists("DATABASE_HOST");
  199. [Benchmark]
  200. [BenchmarkCategory("Exists")]
  201. public bool Ini_Exists() => _iniCfg.Exists("Database:Host");
  202. [Benchmark]
  203. [BenchmarkCategory("Exists")]
  204. public bool Xml_Exists() => _xmlCfg.Exists("Database:Host");
  205. [Benchmark]
  206. [BenchmarkCategory("Exists")]
  207. public bool Yaml_Exists() => _yamlCfg.Exists("Database:Host");
  208. [Benchmark]
  209. [BenchmarkCategory("Exists")]
  210. public bool Toml_Exists() => _tomlCfg.Exists("Database:Host");
  211. #endregion
  212. #region Set 性能测试
  213. [Benchmark]
  214. [BenchmarkCategory("Set")]
  215. public void Json_Set() => _jsonCfg.Set("App:TempKey", "TempValue");
  216. [Benchmark]
  217. [BenchmarkCategory("Set")]
  218. public void Env_Set() => _envCfg.Set("APP_TEMPKEY", "TempValue");
  219. [Benchmark]
  220. [BenchmarkCategory("Set")]
  221. public void Ini_Set() => _iniCfg.Set("App:TempKey", "TempValue");
  222. [Benchmark]
  223. [BenchmarkCategory("Set")]
  224. public void Xml_Set() => _xmlCfg.Set("App:TempKey", "TempValue");
  225. [Benchmark]
  226. [BenchmarkCategory("Set")]
  227. public void Yaml_Set() => _yamlCfg.Set("App:TempKey", "TempValue");
  228. [Benchmark]
  229. [BenchmarkCategory("Set")]
  230. public void Toml_Set() => _tomlCfg.Set("App:TempKey", "TempValue");
  231. #endregion
  232. }