-
Notifications
You must be signed in to change notification settings - Fork 17.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
bytes: WriteString, WriteByte and Write vary in performance #26264
Comments
One thing I've noticed is that sometimes inlining a variable manually makes a difference.
is faster than doing:
not by a lot but it's still consistently faster by about 3 to 5% however, and of course if you do multiple writes it adds up. |
The Benchmark here may be flawed because
It also doesn't look like
|
Generally speaking:
func BenchmarkBytes3(b *testing.B) {
var buf bytes.Buffer
for i := 0; i < b.N; i++ {
if i%1024 == 0 {
buf.Reset()
}
buf.Write([]byte{'a','b','c','d','e','f'})
}
}
func BenchmarkBytes4(b *testing.B) {
var buf bytes.Buffer
s := []byte{'a','b','c','d','e','f'}
for i := 0; i < b.N; i++ {
if i%1024 == 0 {
buf.Reset()
}
buf.Write(s)
}
} On my machine Edit: If you average across a lot of runs using different string/slice sizes the difference is practically "not there" (at least on my machine). As far as to why two BTW: For some reason benchmem always returns 0B and 0 allocs even if I explicitly use make() because I'd expected there to be some allocations because for strings larger than 32 in size stringtoslicebyte imo can't use a tmpBuf and must does allocate one in the call to rawbyteslice which invokes mallocgc so I should see at least something |
See #26264 for a case where using |
@mvdan you've linked to this issue? But my observation is still that there are differences between these functions in specific circumstances and it even makes a difference whether you inline it or not but the difference is tiny and the benchmarks are so flaky that sometimes inlining it is better and sometimes not inlining it is better. Might have something to do with the size of the function that uses write or whatever. I haven't yet been able to pinpoint anything conclusive except what I've already mentioned above. |
Flaky because look for example at:
I can run this a dozen times on my machine and BenchmarkBar is consistently slower by 2-4% but both the tests and the functions are completely identical but there's nothing inherently slower about Foo/Bar and these Benchmarks. This might be simply some microarchitectural/layout/cache thing. However, this also depends on if there are other benchmarks or other code in the |
CL125796 does change the situation a little bit:
That CL makes Not sure why |
Change https://golang.org/cl/125796 mentions this issue: |
@FMNSSun apologies that I haven't replied to your comments directly so far. I had read them, I just hadn't sat down to write proper replies. You're right that my thinking about Two So all in all, happy to close the issue once the CL has been merged. |
@mvdan Seems like the CL is merged; should this issue be closed? Thanks. |
@ianlancetaylor thanks for the ping; I indeed think this can be closed. It doesn't look like there's much else to do for now. |
This is probably a compiler enhancement issue, but since I haven't done much digging, I'm conservatively filing it against the bytes package.
The first surprise here is that
WriteByte('a'); WriteByte('b')
is slightly faster thanWriteString("ab")
. The latter is much nicer to read and write, so it would be nice if it was at least as fast. This was encountered while optimizing theencoding.json
encoder: https://go-review.googlesource.com/c/go/+/122460/1/src/encoding/json/encode.go#650The difference is just a few nanoseconds or ~20%, but in a hot loop like when JSON is encoding struct fields, this can be noticeable.
The second surprise is how
WriteString
is much faster thanWrite
. I haven't come across this directly, but I'd also assume that both would be comparable in performance.If I replace
bytes.Buffer
withstrings.Builder
the numbers are somewhat similar, butString
is faster thanByteByte
./cc @randall77 @josharian @kevinburke
The text was updated successfully, but these errors were encountered: