Skip to content

Commit

Permalink
Pool the Runes buffer for SplitFunc; perf is better
Browse files Browse the repository at this point in the history
The allocation penalty of SplitFunc over 'native' scanner is down to around 10%, instead of 200%.

Perf penalty is now ~8% instead of more than 20% without the pool.
  • Loading branch information
clipperhouse committed Apr 28, 2020
1 parent a4ae9ac commit e02aebd
Showing 1 changed file with 12 additions and 1 deletion.
13 changes: 12 additions & 1 deletion scanner.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"bytes"
"fmt"
"io"
"sync"
"unicode/utf8"
)

Expand Down Expand Up @@ -127,14 +128,21 @@ func (sc *Scanner) readRune() (r rune, eof bool, err error) {
return r, false, nil
}

var runesPool = sync.Pool{
New: func() interface{} {
var runes Runes
return runes
},
}

// NewSplitFunc creates a new bufio.SplitFunc, based on a uax29.BreakFunc
func NewSplitFunc(breakFunc BreakFunc) bufio.SplitFunc {
return func(data []byte, atEOF bool) (advance int, token []byte, err error) {
if atEOF && len(data) == 0 {
return 0, nil, nil
}

var buffer Runes
buffer := runesPool.Get().(Runes)[:0]
var pos Pos

i := 0
Expand Down Expand Up @@ -171,6 +179,9 @@ func NewSplitFunc(breakFunc BreakFunc) bufio.SplitFunc {
for _, r := range buffer[:pos] {
n += utf8.RuneLen(r)
}

runesPool.Put(buffer)

return n, data[:n], nil
}
}

0 comments on commit e02aebd

Please sign in to comment.