From 2d13f51244927cd629f374f0497cc854fd565f31 Mon Sep 17 00:00:00 2001 From: rabbitstack Date: Mon, 23 Dec 2024 10:10:34 +0100 Subject: [PATCH] perf(filter): Speed up expression String methods Use the StringBuilder for a more efficient string concatenation. --- pkg/filter/ql/expr.go | 38 +++++++++++++++++++++++++++++++++---- pkg/filter/ql/literal.go | 41 +++++++++++++++++++++++++--------------- 2 files changed, 60 insertions(+), 19 deletions(-) diff --git a/pkg/filter/ql/expr.go b/pkg/filter/ql/expr.go index fbb8997b8..54714ec04 100644 --- a/pkg/filter/ql/expr.go +++ b/pkg/filter/ql/expr.go @@ -18,7 +18,9 @@ package ql -import "fmt" +import ( + "strings" +) // Node represents a node in the abstract syntax tree. type Node interface { @@ -36,7 +38,14 @@ type ParenExpr struct { } // String returns a string representation of the parenthesized expression. -func (e *ParenExpr) String() string { return fmt.Sprintf("(%s)", e.Expr.String()) } +func (e *ParenExpr) String() string { + var b strings.Builder + b.Grow(len(e.Expr.String()) + 2) + b.WriteRune('(') + b.WriteString(e.Expr.String()) + b.WriteRune(')') + return b.String() +} // BinaryExpr represents an operation between two expressions. type BinaryExpr struct { @@ -47,7 +56,21 @@ type BinaryExpr struct { // String returns a string representation of the binary expression. func (e *BinaryExpr) String() string { - return fmt.Sprintf("%s %s %s", e.LHS.String(), e.Op.String(), e.RHS.String()) + var b strings.Builder + + lhs := e.LHS.String() + op := e.Op.String() + rhs := e.RHS.String() + + b.Grow(len(lhs) + len(op) + len(rhs) + 2) + + b.WriteString(lhs) + b.WriteString(" ") + b.WriteString(op) + b.WriteString(" ") + b.WriteString(rhs) + + return b.String() } // NotExpr represents an unary not expression. @@ -56,4 +79,11 @@ type NotExpr struct { } // String returns a string representation of the not expression. -func (e *NotExpr) String() string { return fmt.Sprintf("(%s)", e.Expr.String()) } +func (e *NotExpr) String() string { + var b strings.Builder + b.Grow(len(e.Expr.String()) + 2) + b.WriteRune('(') + b.WriteString(e.Expr.String()) + b.WriteRune(')') + return b.String() +} diff --git a/pkg/filter/ql/literal.go b/pkg/filter/ql/literal.go index c42076f89..3f6bf8bcf 100644 --- a/pkg/filter/ql/literal.go +++ b/pkg/filter/ql/literal.go @@ -19,8 +19,6 @@ package ql import ( - "bytes" - "fmt" "github.com/rabbitstack/fibratus/pkg/filter/fields" "github.com/rabbitstack/fibratus/pkg/kevent" "github.com/rabbitstack/fibratus/pkg/kevent/ktypes" @@ -129,16 +127,25 @@ type ListLiteral struct { // String returns a string representation of the literal. func (s *ListLiteral) String() string { - var buf bytes.Buffer - _, _ = buf.WriteString("(") - for idx, tagKey := range s.Values { + var n int + for _, elem := range s.Values { + n += len(elem) + 2 + } + + var b strings.Builder + b.Grow(n + 2) + b.WriteRune('(') + + for idx, elem := range s.Values { if idx != 0 { - _, _ = buf.WriteString(", ") + b.WriteString(", ") } - _, _ = buf.WriteString(tagKey) + b.WriteString(elem) } - _, _ = buf.WriteString(")") - return buf.String() + + b.WriteRune(')') + + return b.String() } // Function represents a function call. @@ -158,14 +165,18 @@ func (f *Function) ArgsSlice() []string { // String returns a string representation of the call. func (f *Function) String() string { - // join arguments. - var str []string - for _, arg := range f.Args { - str = append(str, arg.String()) - } + args := strings.Join(f.ArgsSlice(), ", ") + + var b strings.Builder + b.Grow(len(args) + len(f.Name) + 2) + + b.WriteString(f.Name) + b.WriteRune('(') + b.WriteString(args) + b.WriteRune(')') // Write function name and args. - return fmt.Sprintf("%s(%s)", f.Name, strings.Join(str, ", ")) + return b.String() } // validate ensures that the function name obtained