Commit 83765d13 authored by Martin Möhrmann's avatar Martin Möhrmann Committed by Rob Pike

fmt: optimize string truncation

Count only the runes up to the requested precision
to decide where to truncate a string.

Change the loop within truncate to need fewer jumps.

name                     old time/op  new time/op  delta
SprintfTruncateString-2   188ns ± 3%   155ns ± 3%  -17.43%  (p=0.000 n=20+20)

Change-Id: I17ca9fc0bb8bf7648599df48e4785251bbc31e99
Reviewed-on: https://go-review.googlesource.com/20098Reviewed-by: default avatarRob Pike <r@golang.org>
parent 2faf5bca
...@@ -199,7 +199,9 @@ var fmtTests = []struct { ...@@ -199,7 +199,9 @@ var fmtTests = []struct {
{"%08q", "abc", `000"abc"`}, {"%08q", "abc", `000"abc"`},
{"%5s", "abcdefghijklmnopqrstuvwxyz", "abcdefghijklmnopqrstuvwxyz"}, {"%5s", "abcdefghijklmnopqrstuvwxyz", "abcdefghijklmnopqrstuvwxyz"},
{"%.5s", "abcdefghijklmnopqrstuvwxyz", "abcde"}, {"%.5s", "abcdefghijklmnopqrstuvwxyz", "abcde"},
{"%.0s", "日本語日本語", ""},
{"%.5s", "日本語日本語", "日本語日本"}, {"%.5s", "日本語日本語", "日本語日本"},
{"%.10s", "日本語日本語", "日本語日本語"},
{"%.5s", []byte("日本語日本語"), "日本語日本"}, {"%.5s", []byte("日本語日本語"), "日本語日本"},
{"%.5q", "abcdefghijklmnopqrstuvwxyz", `"abcde"`}, {"%.5q", "abcdefghijklmnopqrstuvwxyz", `"abcde"`},
{"%.5x", "abcdefghijklmnopqrstuvwxyz", `6162636465`}, {"%.5x", "abcdefghijklmnopqrstuvwxyz", `6162636465`},
...@@ -928,6 +930,14 @@ func BenchmarkSprintfString(b *testing.B) { ...@@ -928,6 +930,14 @@ func BenchmarkSprintfString(b *testing.B) {
}) })
} }
func BenchmarkSprintfTruncateString(b *testing.B) {
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
Sprintf("%.3s", "日本語日本語日本語")
}
})
}
func BenchmarkSprintfInt(b *testing.B) { func BenchmarkSprintfInt(b *testing.B) {
b.RunParallel(func(pb *testing.PB) { b.RunParallel(func(pb *testing.PB) {
for pb.Next() { for pb.Next() {
......
...@@ -282,14 +282,13 @@ func (f *fmt) integer(a int64, base uint64, signedness bool, digits string) { ...@@ -282,14 +282,13 @@ func (f *fmt) integer(a int64, base uint64, signedness bool, digits string) {
// truncate truncates the string to the specified precision, if present. // truncate truncates the string to the specified precision, if present.
func (f *fmt) truncate(s string) string { func (f *fmt) truncate(s string) string {
if f.precPresent && f.prec < utf8.RuneCountInString(s) { if f.precPresent {
n := f.prec n := f.prec
for i := range s { for i := range s {
if n == 0 {
s = s[:i]
break
}
n-- n--
if n < 0 {
return s[:i]
}
} }
} }
return s return s
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment