aboutsummaryrefslogtreecommitdiff
path: root/src/runtime/string_test.go
diff options
context:
space:
mode:
authorMartin Möhrmann <moehrmann@google.com>2018-04-24 15:13:08 +0200
committerMartin Möhrmann <moehrmann@google.com>2018-05-06 05:31:01 +0000
commitb9a59d9f2e78ce497b38a984f62094a53e7dfce7 (patch)
treec595460f4950f5f76d59cec82c651993ea449196 /src/runtime/string_test.go
parenta8a60ac2a7bec701de6b502889e1dc740761e183 (diff)
downloadgo-b9a59d9f2e78ce497b38a984f62094a53e7dfce7.tar.xz
cmd/compile: optimize len([]rune(string))
Adds a new runtime function to count runes in a string. Modifies the compiler to detect the pattern len([]rune(string)) and replaces it with the new rune counting runtime function. RuneCount/lenruneslice/ASCII 27.8ns ± 2% 14.5ns ± 3% -47.70% (p=0.000 n=10+10) RuneCount/lenruneslice/Japanese 126ns ± 2% 60ns ± 2% -52.03% (p=0.000 n=10+10) RuneCount/lenruneslice/MixedLength 104ns ± 2% 50ns ± 1% -51.71% (p=0.000 n=10+9) Fixes #24923 Change-Id: Ie9c7e7391a4e2cca675c5cdcc1e5ce7d523948b9 Reviewed-on: https://go-review.googlesource.com/108985 Run-TryBot: Martin Möhrmann <moehrmann@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Josh Bleecher Snyder <josharian@gmail.com>
Diffstat (limited to 'src/runtime/string_test.go')
-rw-r--r--src/runtime/string_test.go38
1 files changed, 38 insertions, 0 deletions
diff --git a/src/runtime/string_test.go b/src/runtime/string_test.go
index c6e925d2e0..678ff00363 100644
--- a/src/runtime/string_test.go
+++ b/src/runtime/string_test.go
@@ -9,6 +9,7 @@ import (
"strconv"
"strings"
"testing"
+ "unicode/utf8"
)
// Strings and slices that don't escape and fit into tmpBuf are stack allocated,
@@ -110,6 +111,43 @@ var stringdata = []struct{ name, data string }{
{"MixedLength", "$Ѐࠀက퀀𐀀\U00040000\U0010FFFF"},
}
+var sinkInt int
+
+func BenchmarkRuneCount(b *testing.B) {
+ // Each sub-benchmark counts the runes in a string in a different way.
+ b.Run("lenruneslice", func(b *testing.B) {
+ for _, sd := range stringdata {
+ b.Run(sd.name, func(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ sinkInt += len([]rune(sd.data))
+ }
+ })
+ }
+ })
+ b.Run("rangeloop", func(b *testing.B) {
+ for _, sd := range stringdata {
+ b.Run(sd.name, func(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ n := 0
+ for range sd.data {
+ n++
+ }
+ sinkInt += n
+ }
+ })
+ }
+ })
+ b.Run("utf8.RuneCountInString", func(b *testing.B) {
+ for _, sd := range stringdata {
+ b.Run(sd.name, func(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ sinkInt += utf8.RuneCountInString(sd.data)
+ }
+ })
+ }
+ })
+}
+
func BenchmarkRuneIterate(b *testing.B) {
b.Run("range", func(b *testing.B) {
for _, sd := range stringdata {