From e5fa9fe9def11cdf010176f5871efdda2a6d99de Mon Sep 17 00:00:00 2001 From: xfy Date: Thu, 4 Jun 2026 11:09:08 +0800 Subject: [PATCH] perf(compression): pre-compute MIME type byte slices for isCompressible Add typesBytes and typesWildcardPrefix fields to Middleware, built once at construction. isCompressible now uses pre-converted byte slices instead of allocating []byte(t) per comparison per request. --- .../middleware/compression/compression.go | 27 +++++++++++++------ 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/internal/middleware/compression/compression.go b/internal/middleware/compression/compression.go index c56955e..4d88127 100644 --- a/internal/middleware/compression/compression.go +++ b/internal/middleware/compression/compression.go @@ -112,6 +112,10 @@ type Middleware struct { brotliPool *compressorPool // types 可压缩的 MIME 类型列表 types []string + // typesBytes 预计算的小写 MIME 类型字节切片 + typesBytes [][]byte + // typesWildcardPrefix 预计算的通配符前缀字节切片 + typesWildcardPrefix [][]byte // level 压缩级别(1-9) level int @@ -171,6 +175,15 @@ func New(cfg *config.CompressionConfig) (*Middleware, error) { algorithm: algo, } + for _, t := range m.types { + lower := strings.ToLower(t) + if base, found := strings.CutSuffix(lower, "/*"); found { + m.typesWildcardPrefix = append(m.typesWildcardPrefix, []byte(base)) + } else { + m.typesBytes = append(m.typesBytes, []byte(lower)) + } + } + // 初始化缓冲池 m.gzipPool = newGzipPool(cfg.Level) m.brotliPool = newBrotliPool(cfg.Level) @@ -296,22 +309,20 @@ func (m *Middleware) Process(next fasthttp.RequestHandler) fasthttp.RequestHandl // 返回值: // - bool: 是否可压缩 func (m *Middleware) isCompressible(contentType []byte) bool { - // 移除 charset 等参数 ct := contentType if idx := bytes.IndexByte(ct, ';'); idx >= 0 { ct = ct[:idx] } ct = bytes.TrimSpace(ct) - for _, t := range m.types { - if bytes.Equal(bytes.ToLower([]byte(t)), ct) { + for _, t := range m.typesBytes { + if bytes.Equal(t, ct) { return true } - // 支持通配符匹配 - if base, found := strings.CutSuffix(t, "/*"); found { - if bytes.HasPrefix(ct, []byte(base)) { - return true - } + } + for _, prefix := range m.typesWildcardPrefix { + if bytes.HasPrefix(ct, prefix) { + return true } } return false