Skip to content

Commit

Permalink
Reduce the size of the buffered reader to improve CPU performance
Browse files Browse the repository at this point in the history
  • Loading branch information
DaneEveritt committed Jan 23, 2022
1 parent d701b35 commit de04e73
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 2 deletions.
9 changes: 8 additions & 1 deletion system/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,14 @@ func MustInt(v string) int {
// over the websocket. If a line exceeds that size, it is truncated and only that
// amount is sent over.
func ScanReader(r io.Reader, callback func(line []byte)) error {
br := bufio.NewReader(r)
// Based on benchmarking this seems to be the best size for the reader buffer
// to maintain fast enough workflows without hammering the CPU for allocations.
//
// Additionally, most games are outputting a high-frequency of smaller lines,
// rather than a bunch of massive lines. This allocation amount is the total
// number of bytes being output for each call to ReadLine() before it moves on
// to the next data pull.
br := bufio.NewReaderSize(r, 256)
// Avoid constantly re-allocating memory when we're flooding lines through this
// function by using the same buffer for the duration of the call and just truncating
// the value back to 0 every loop.
Expand Down
20 changes: 19 additions & 1 deletion system/utils_test.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
package system

import (
"math/rand"
"strings"
"testing"
"time"

. "github.com/franela/goblin"
)

func TestScanReader(t *testing.T) {
func Test_Utils(t *testing.T) {
g := Goblin(t)

g.Describe("ScanReader", func() {
Expand Down Expand Up @@ -39,3 +41,19 @@ func TestScanReader(t *testing.T) {
})
})
}

func Benchmark_ScanReader(b *testing.B) {
r := rand.New(rand.NewSource(time.Now().UnixNano()))
var str string
for i := 0; i < 10; i++ {
str += strings.Repeat("hello \rworld", r.Intn(2000)) + "\n"
}
reader := strings.NewReader(str)

b.ResetTimer()
for i := 0; i < b.N; i++ {
_ = ScanReader(reader, func(line []byte) {
// no op
})
}
}

0 comments on commit de04e73

Please sign in to comment.