From b9a59d9f2e78ce497b38a984f62094a53e7dfce7 Mon Sep 17 00:00:00 2001 From: Martin Möhrmann Date: Tue, 24 Apr 2018 15:13:08 +0200 Subject: cmd/compile: optimize len([]rune(string)) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 TryBot-Result: Gobot Gobot Reviewed-by: Josh Bleecher Snyder --- src/unicode/utf8/utf8_test.go | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) (limited to 'src/unicode') diff --git a/src/unicode/utf8/utf8_test.go b/src/unicode/utf8/utf8_test.go index dc9c4251bd..359461bd05 100644 --- a/src/unicode/utf8/utf8_test.go +++ b/src/unicode/utf8/utf8_test.go @@ -212,14 +212,25 @@ func TestSequencing(t *testing.T) { } } -// Check that a range loop and a []int conversion visit the same runes. +func runtimeRuneCount(s string) int { + return len([]rune(s)) // Replaced by gc with call to runtime.countrunes(s). +} + +// Check that a range loop, len([]rune(string)) optimization and +// []rune conversions visit the same runes. // Not really a test of this package, but the assumption is used here and -// it's good to verify -func TestIntConversion(t *testing.T) { +// it's good to verify. +func TestRuntimeConversion(t *testing.T) { for _, ts := range testStrings { + count := RuneCountInString(ts) + if n := runtimeRuneCount(ts); n != count { + t.Errorf("%q: len([]rune()) counted %d runes; got %d from RuneCountInString", ts, n, count) + break + } + runes := []rune(ts) - if RuneCountInString(ts) != len(runes) { - t.Errorf("%q: expected %d runes; got %d", ts, len(runes), RuneCountInString(ts)) + if n := len(runes); n != count { + t.Errorf("%q: []rune() has length %d; got %d from RuneCountInString", ts, n, count) break } i := 0 -- cgit v1.3