diff --git a/internal/corazawaf/transaction.go b/internal/corazawaf/transaction.go index 7fce408f3..1a4785b90 100644 --- a/internal/corazawaf/transaction.go +++ b/internal/corazawaf/transaction.go @@ -587,9 +587,9 @@ func (tx *Transaction) GetField(rv ruleVariableParams) []types.MatchData { } // in the most common scenario filteredMatches length will be - // the same as matches length, so we avoid allocating per result - filteredMatches := make([]types.MatchData, 0, len(matches)) - + // the same as matches length, so we avoid allocating per result. + // We reuse the matches slice to store filtered results avoiding extra allocation. + filteredCount := 0 for _, c := range matches { isException := false lkey := strings.ToLower(c.Key()) @@ -600,10 +600,11 @@ func (tx *Transaction) GetField(rv ruleVariableParams) []types.MatchData { } } if !isException { - filteredMatches = append(filteredMatches, c) + matches[filteredCount] = c + filteredCount++ } } - matches = filteredMatches + matches = matches[:filteredCount] if rv.Count { count := len(matches) diff --git a/internal/corazawaf/transaction_test.go b/internal/corazawaf/transaction_test.go index 0bb0c4c65..64d548546 100644 --- a/internal/corazawaf/transaction_test.go +++ b/internal/corazawaf/transaction_test.go @@ -1291,6 +1291,20 @@ func TestTxGetField(t *testing.T) { } } +func BenchmarkTxGetField(b *testing.B) { + tx := makeTransaction(b) + rvp := ruleVariableParams{ + Variable: variables.Args, + } + for i := 0; i < b.N; i++ { + tx.GetField(rvp) + } + if err := tx.Close(); err != nil { + b.Fatalf("Failed to close transaction: %s", err.Error()) + } + b.ReportAllocs() +} + func TestTxProcessURI(t *testing.T) { waf := NewWAF() tx := waf.NewTransaction()