lolly/internal/middleware/compression/compression_bench_test.go

279 lines
6.4 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Package compression 提供压缩中间件的基准测试。
//
// 该文件测试 gzip/brotli 压缩性能、Pool 复用效率和组件级性能。
//
// 作者xfy
package compression
import (
"testing"
"github.com/valyala/fasthttp"
"rua.plus/lolly/internal/config"
"rua.plus/lolly/internal/testutil"
)
// BenchmarkGzipCompress_1KB 测试 gzip 压缩 1KB 数据的性能。
func BenchmarkGzipCompress_1KB(b *testing.B) {
cfg := &config.CompressionConfig{
Type: "gzip",
Level: 6,
MinSize: 100,
Types: []string{"text/html", "application/json"},
}
mw, _ := New(cfg)
data := testutil.GenerateTestData(testutil.Size1KB)
b.ResetTimer()
for b.Loop() {
mw.compressWithPool(data, mw.gzipPool)
}
}
// BenchmarkGzipCompress_10KB 测试 gzip 压缩 10KB 数据的性能。
func BenchmarkGzipCompress_10KB(b *testing.B) {
cfg := &config.CompressionConfig{
Type: "gzip",
Level: 6,
MinSize: 100,
}
mw, _ := New(cfg)
data := testutil.GenerateTestData(testutil.Size10KB)
b.ResetTimer()
for b.Loop() {
mw.compressWithPool(data, mw.gzipPool)
}
}
// BenchmarkGzipCompress_100KB 测试 gzip 压缩 100KB 数据的性能。
func BenchmarkGzipCompress_100KB(b *testing.B) {
cfg := &config.CompressionConfig{
Type: "gzip",
Level: 6,
MinSize: 100,
}
mw, _ := New(cfg)
data := testutil.GenerateTestData(testutil.Size100KB)
b.ResetTimer()
for b.Loop() {
mw.compressWithPool(data, mw.gzipPool)
}
}
// BenchmarkBrotliCompress_1KB 测试 brotli 压缩 1KB 数据的性能。
func BenchmarkBrotliCompress_1KB(b *testing.B) {
cfg := &config.CompressionConfig{
Type: "brotli",
Level: 6,
MinSize: 100,
}
mw, _ := New(cfg)
data := testutil.GenerateTestData(testutil.Size1KB)
b.ResetTimer()
for b.Loop() {
mw.compressWithPool(data, mw.brotliPool)
}
}
// BenchmarkBrotliCompress_10KB 测试 brotli 压缩 10KB 数据的性能。
func BenchmarkBrotliCompress_10KB(b *testing.B) {
cfg := &config.CompressionConfig{
Type: "brotli",
Level: 6,
MinSize: 100,
}
mw, _ := New(cfg)
data := testutil.GenerateTestData(testutil.Size10KB)
b.ResetTimer()
for b.Loop() {
mw.compressWithPool(data, mw.brotliPool)
}
}
// BenchmarkCompressionPool 测试压缩 Pool 复用效率。
//
// 模拟实际使用场景,反复从 Pool 获取和归还压缩器。
func BenchmarkCompressionPool(b *testing.B) {
cfg := &config.CompressionConfig{
Type: "gzip",
Level: 6,
MinSize: 100,
}
mw, _ := New(cfg)
data := testutil.GenerateTestData(testutil.Size1KB)
b.ResetTimer()
for b.Loop() {
mw.compressWithPool(data, mw.gzipPool)
}
}
// BenchmarkCompressionMiddleware 组件级测试:测量压缩中间件本身的开销。
//
// 使用 mockHandler 排除下游处理的影响。
func BenchmarkCompressionMiddleware(b *testing.B) {
cfg := &config.CompressionConfig{
Type: "gzip",
Level: 6,
MinSize: 100,
Types: []string{
"text/html", "text/css", "application/json",
},
}
mw, _ := New(cfg)
// 创建 10KB 响应数据
responseBody := testutil.GenerateTestData(testutil.Size10KB)
// Mock handler 返回固定响应
mockHandler := func(ctx *fasthttp.RequestCtx) {
ctx.SetStatusCode(fasthttp.StatusOK)
ctx.SetContentType("application/json")
ctx.SetBody(responseBody)
}
handler := mw.Process(mockHandler)
b.ResetTimer()
for b.Loop() {
ctx := &fasthttp.RequestCtx{}
ctx.Request.Header.SetMethod(fasthttp.MethodGet)
ctx.Request.SetRequestURI("/api/test")
ctx.Request.Header.Set("Accept-Encoding", "gzip")
handler(ctx)
}
}
// BenchmarkCompressionMiddlewareNoCompress 测试无需压缩场景的性能开销。
//
// 当客户端不支持压缩时,中间件应几乎无额外开销。
func BenchmarkCompressionMiddlewareNoCompress(b *testing.B) {
cfg := &config.CompressionConfig{
Type: "gzip",
Level: 6,
MinSize: 100,
}
mw, _ := New(cfg)
responseBody := testutil.GenerateTestData(testutil.Size10KB)
mockHandler := func(ctx *fasthttp.RequestCtx) {
ctx.SetStatusCode(fasthttp.StatusOK)
ctx.SetContentType("application/json")
ctx.SetBody(responseBody)
}
handler := mw.Process(mockHandler)
b.ResetTimer()
for b.Loop() {
ctx := &fasthttp.RequestCtx{}
ctx.Request.Header.SetMethod(fasthttp.MethodGet)
ctx.Request.SetRequestURI("/api/test")
// 不设置 Accept-Encoding 头
handler(ctx)
}
}
// BenchmarkIsCompressible 测试 MIME 类型检查性能。
func BenchmarkIsCompressible(b *testing.B) {
cfg := &config.CompressionConfig{
Type: "gzip",
Level: 6,
Types: []string{
"text/html", "text/css", "text/javascript",
"application/json", "application/javascript",
},
}
mw, _ := New(cfg)
contentTypes := [][]byte{
[]byte("application/json"),
[]byte("text/html; charset=utf-8"),
[]byte("image/png"),
[]byte("application/octet-stream"),
[]byte("text/css"),
}
b.ResetTimer()
for b.Loop() {
for _, ct := range contentTypes {
mw.isCompressible(ct)
}
}
}
// BenchmarkCompressionLevelComparison 比较不同压缩级别的性能。
func BenchmarkCompressionLevelComparison(b *testing.B) {
data := testutil.GenerateTestData(testutil.Size10KB)
b.Run("Level1", func(b *testing.B) {
cfg := &config.CompressionConfig{Type: "gzip", Level: 1}
mw, _ := New(cfg)
b.ResetTimer()
for b.Loop() {
mw.compressWithPool(data, mw.gzipPool)
}
})
b.Run("Level6", func(b *testing.B) {
cfg := &config.CompressionConfig{Type: "gzip", Level: 6}
mw, _ := New(cfg)
b.ResetTimer()
for b.Loop() {
mw.compressWithPool(data, mw.gzipPool)
}
})
b.Run("Level9", func(b *testing.B) {
cfg := &config.CompressionConfig{Type: "gzip", Level: 9}
mw, _ := New(cfg)
b.ResetTimer()
for b.Loop() {
mw.compressWithPool(data, mw.gzipPool)
}
})
}
// BenchmarkCompressionMiddlewareParallel 测试并发场景下的中间件性能。
func BenchmarkCompressionMiddlewareParallel(b *testing.B) {
cfg := &config.CompressionConfig{
Type: "gzip",
Level: 6,
MinSize: 100,
Types: []string{"application/json"},
}
mw, _ := New(cfg)
responseBody := testutil.GenerateTestData(testutil.Size10KB)
mockHandler := func(ctx *fasthttp.RequestCtx) {
ctx.SetStatusCode(fasthttp.StatusOK)
ctx.SetContentType("application/json")
ctx.SetBody(responseBody)
}
handler := mw.Process(mockHandler)
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
ctx := &fasthttp.RequestCtx{}
ctx.Request.Header.SetMethod(fasthttp.MethodGet)
ctx.Request.SetRequestURI("/api/test")
ctx.Request.Header.Set("Accept-Encoding", "gzip")
handler(ctx)
}
})
}