http_upstream_benchmark_test.go 2.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  1. package repository
  2. import (
  3. "net/http"
  4. "net/url"
  5. "testing"
  6. "github.com/Wei-Shaw/sub2api/internal/config"
  7. )
  8. // httpClientSink 用于防止编译器优化掉基准测试中的赋值操作
  9. // 这是 Go 基准测试的常见模式,确保测试结果准确
  10. var httpClientSink *http.Client
  11. // BenchmarkHTTPUpstreamProxyClient 对比重复创建与复用代理客户端的开销
  12. //
  13. // 测试目的:
  14. // - 验证连接池复用相比每次新建的性能提升
  15. // - 量化内存分配差异
  16. //
  17. // 预期结果:
  18. // - "复用" 子测试应显著快于 "新建"
  19. // - "复用" 子测试应零内存分配
  20. func BenchmarkHTTPUpstreamProxyClient(b *testing.B) {
  21. // 创建测试配置
  22. cfg := &config.Config{
  23. Gateway: config.GatewayConfig{ResponseHeaderTimeout: 300},
  24. }
  25. upstream := NewHTTPUpstream(cfg)
  26. svc, ok := upstream.(*httpUpstreamService)
  27. if !ok {
  28. b.Fatalf("类型断言失败,无法获取 httpUpstreamService")
  29. }
  30. proxyURL := "http://127.0.0.1:8080"
  31. b.ReportAllocs() // 报告内存分配统计
  32. // 子测试:每次新建客户端
  33. // 模拟未优化前的行为,每次请求都创建新的 http.Client
  34. b.Run("新建", func(b *testing.B) {
  35. parsedProxy, err := url.Parse(proxyURL)
  36. if err != nil {
  37. b.Fatalf("解析代理地址失败: %v", err)
  38. }
  39. settings := defaultPoolSettings(cfg)
  40. for i := 0; i < b.N; i++ {
  41. // 每次迭代都创建新客户端,包含 Transport 分配
  42. transport, err := buildUpstreamTransport(settings, parsedProxy, upstreamProtocolModeDefault)
  43. if err != nil {
  44. b.Fatalf("创建 Transport 失败: %v", err)
  45. }
  46. httpClientSink = &http.Client{
  47. Transport: transport,
  48. }
  49. }
  50. })
  51. // 子测试:复用已缓存的客户端
  52. // 模拟优化后的行为,从缓存获取客户端
  53. b.Run("复用", func(b *testing.B) {
  54. // 预热:确保客户端已缓存
  55. entry, err := svc.getOrCreateClient(proxyURL, 1, 1)
  56. if err != nil {
  57. b.Fatalf("getOrCreateClient: %v", err)
  58. }
  59. client := entry.client
  60. b.ResetTimer() // 重置计时器,排除预热时间
  61. for i := 0; i < b.N; i++ {
  62. // 直接使用缓存的客户端,无内存分配
  63. httpClientSink = client
  64. }
  65. })
  66. }