-
Notifications
You must be signed in to change notification settings - Fork 18k
cmd/compile,unicode/utf8: utf8.EncodeRune has different performance from the equivalent string conversion #48684
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
Comments
At the very least, this may be a useful data point for #27400. |
Yep, this is in part #27400. When I sprinkle the benchmarks with package main
import (
"bytes"
"runtime"
"testing"
"unicode/utf8"
)
//go:noinline
func utf8EncodeRune(b []byte, r rune) int {
return utf8.EncodeRune(b[:], r)
}
//go:noinline
func stringEncodeRune(b []byte, r rune) int {
return copy(b[:], string(r))
}
func BenchmarkEncodeRune(b *testing.B) {
b.ReportAllocs()
const r = '💩'
for n := b.N; n > 0; n-- {
b := [utf8.UTFMax]byte{}
n := utf8EncodeRune(b[:], r)
runtime.KeepAlive(b)
runtime.KeepAlive(n)
}
}
func BenchmarkCopyConvertedRune(b *testing.B) {
b.ReportAllocs()
const r = '💩'
for n := b.N; n > 0; n-- {
b := [utf8.UTFMax]byte{}
n := stringEncodeRune(b[:], r)
runtime.KeepAlive(b)
runtime.KeepAlive(n)
}
}
|
I don't think this is a fair benchmark. Most of
|
That's fair — but is also a pretty strong argument that |
I'm sympathetic, but not sure what the fix might be. Sometimes you want to benchmark the fully-optimized code, including any dead code elimination. Generally any benchmark with "_ = " in it is ripe for dead code elimination that maybe wasn't intended. Certainly fixing #27400 would help. |
@randall77 For a few years I have been under the impression that I think we need a |
@cespare So I think I misspoke a bit here:
It does force its argument to be generated, in the sense that the value must be available at the |
In this case I suspect that the problem may be on the input side rather than the output side. The input |
What version of Go are you using (
go version
)?Does this issue reproduce with the latest release?
Yes.
What operating system and processor architecture are you using (
go env
)?go env
OutputWhat did you do?
What did you expect to see?
utf8.EncodeRune
performance exactly equal to the code usingcopy
and astring
conversion, since they are (as far as I can tell) semantically equivalent (compare #3939).I wrote a fuzz test to demonstrate equivalence, and found no counterexamples after 5 minutes of fuzzing:
What did you see instead?
utf8.EncodeRune
takes something like 9x longer than thestring
-and-copy
equivalent:The text was updated successfully, but these errors were encountered: