From ac400acfd0ed25169a0a9c80cbc611a73dffdad2 Mon Sep 17 00:00:00 2001 From: sinkingpoint Date: Thu, 11 Jul 2024 11:20:06 +1200 Subject: [PATCH] Re-use Syslog Readers Signed-off-by: sinkingpoint --- octetcounting/parser.go | 4 ++-- octetcounting/scanner.go | 36 +++++++++++++++++++++++++++++++++++- 2 files changed, 37 insertions(+), 3 deletions(-) diff --git a/octetcounting/parser.go b/octetcounting/parser.go index 5a5d4f8..a8d63cc 100644 --- a/octetcounting/parser.go +++ b/octetcounting/parser.go @@ -5,15 +5,14 @@ import ( "io" syslog "github.com/leodido/go-syslog/v4" - "github.com/leodido/go-syslog/v4/rfc5424" "github.com/leodido/go-syslog/v4/rfc3164" + "github.com/leodido/go-syslog/v4/rfc5424" ) // parser is capable to parse the input stream containing syslog messages with octetcounting framing. // // Use NewParser function to instantiate one. type parser struct { - msglen int64 maxMessageLength int s Scanner internal syslog.Machine @@ -96,6 +95,7 @@ func (p *parser) Parse(r io.Reader) { } func (p *parser) run() { + defer p.s.Release() for { var tok Token diff --git a/octetcounting/scanner.go b/octetcounting/scanner.go index 7926515..6317db0 100644 --- a/octetcounting/scanner.go +++ b/octetcounting/scanner.go @@ -5,8 +5,38 @@ import ( "bytes" "io" "strconv" + "sync" ) +var readerPool sync.Pool + +// getReader returns a *bufio.Reader that is guaranteed +// to have a buffer of at least `size`. +func getReader(r io.Reader, size int) *bufio.Reader { + if buf := readerPool.Get(); buf != nil { + buf := buf.(*bufio.Reader) + + // If the buffer we get is smaller than the requested buffer, put it back + // and create a new one. stdlib has multiple buckets for various sizes to + // make this more efficient, but that's overkill here. + if buf.Size() < size { + readerPool.Put(buf) + buf = bufio.NewReaderSize(r, size) + } else { + buf.Reset(r) + } + + return buf + } + + return bufio.NewReaderSize(r, size) +} + +// putReader returns the given bufio.Reader to the pool to be used again. +func putReader(r *bufio.Reader) { + readerPool.Put(r) +} + // eof represents a marker byte for the end of the reader var eof = byte(0) @@ -39,7 +69,7 @@ type Scanner struct { // NewScanner returns a pointer to a new instance of Scanner. func NewScanner(r io.Reader, maxLength int) *Scanner { return &Scanner{ - r: bufio.NewReaderSize(r, maxLength+20), // max uint64 is 19 characters + a space + r: getReader(r, maxLength+20), // max uint64 is 19 characters + a space } } @@ -151,3 +181,7 @@ func (s *Scanner) scanSyslogMsg() Token { lit: b, } } + +func (s *Scanner) Release() { + putReader(s.r) +}