In our project we need to parse proc maps pretty frequently and we've noticed that there are lots of small allocations coming from parsing the device and addresses from procfs' maps file.
The rough split of memory allocated is:
bufio.(*Scanner).Text: 25%
strings.Split: 50%
string.Fields: 25%
The two callers of strings.Split are the two parsing functions that we are optimising here. I've added some benchmarks to show the improvements.
Before
$ go test -benchmem -run=^$ -bench ^BenchmarkParse.*$ github.com/prometheus/procfs
goos: linux
goarch: amd64
pkg: github.com/prometheus/procfs
cpu: Intel(R) Core(TM) i7-8700K CPU @ 3.70GHz
BenchmarkParseAddress-12 12218004 123.0 ns/op 32 B/op 1 allocs/op
BenchmarkParseDevice-12 15074881 85.11 ns/op 32 B/op 1 allocs/op
PASS
ok github.com/prometheus/procfs 2.978s
After
$ go test -benchmem -run=^$ -bench ^BenchmarkParse.*$ github.com/prometheus/procfs
goos: linux
goarch: amd64
pkg: github.com/prometheus/procfs
cpu: Intel(R) Core(TM) i7-8700K CPU @ 3.70GHz
BenchmarkParseAddress-12 28619314 50.45 ns/op 0 B/op 0 allocs/op
BenchmarkParseDevice-12 49721935 29.66 ns/op 0 B/op 0 allocs/op
PASS
ok github.com/prometheus/procfs 2.991s
In our project we need to parse proc maps pretty frequently and we've noticed that there are lots of small allocations coming from parsing the device and addresses from procfs' maps file.
The rough split of memory allocated is:
The two callers of strings.Split are the two parsing functions that we are optimising here. I've added some benchmarks to show the improvements.
Before
After