Merge pull request #1322 from DigitalVeer/logbuffer-regexp-cache

Cache compiled regular expressions in the log buffer
This commit is contained in:
kubernetes-prow[bot]
2026-07-22 06:05:44 +00:00
committed by GitHub
2 changed files with 25 additions and 5 deletions
+11 -5
View File
@@ -39,6 +39,8 @@ type logBuffer struct {
msg []string
max int
current int
// regexps caches compiled regular expressions.
regexps map[string]*regexp.Regexp
}
// NewLogBuffer creates log buffer with max line number limit. Because we only match logs
@@ -47,9 +49,10 @@ type logBuffer struct {
// lines of patterns we support.
func NewLogBuffer(maxLines int) *logBuffer {
return &logBuffer{
buffer: make([]*types.Log, maxLines),
msg: make([]string, maxLines),
max: maxLines,
buffer: make([]*types.Log, maxLines),
msg: make([]string, maxLines),
max: maxLines,
regexps: make(map[string]*regexp.Regexp),
}
}
@@ -59,10 +62,13 @@ func (b *logBuffer) Push(log *types.Log) {
b.current++
}
// TODO(random-liu): Cache regexp if garbage collection becomes a problem someday.
func (b *logBuffer) Match(expr string) []*types.Log {
// The expression should be checked outside, and it must match to the end.
reg := regexp.MustCompile(expr + `\z`)
reg, ok := b.regexps[expr]
if !ok {
reg = regexp.MustCompile(expr + `\z`)
b.regexps[expr] = reg
}
log := b.String()
loc := reg.FindStringIndex(log)
if loc == nil {
+14
View File
@@ -108,3 +108,17 @@ func TestMatch(t *testing.T) {
}
}
}
func BenchmarkMatch(b *testing.B) {
buf := NewLogBuffer(10)
for i := 0; i < 10; i++ {
buf.Push(&types.Log{Message: "Out of memory: Kill process 20744 (mysqld) score 318 or sacrifice child"})
}
// A pattern from the default kernel monitor configuration which does not
// match the buffered logs.
expr := `task [\S ]+:\w+ blocked for more than \w+ seconds\.`
b.ResetTimer()
for i := 0; i < b.N; i++ {
buf.Match(expr)
}
}