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 {
{"%08q", "abc", `000"abc"`},
{"%5s", "abcdefghijklmnopqrstuvwxyz", "abcdefghijklmnopqrstuvwxyz"},
{"%.5s", "abcdefghijklmnopqrstuvwxyz", "abcde"},
{"%.0s", "日本語日本語", ""},
{"%.5s", "日本語日本語", "日本語日本"},
{"%.10s", "日本語日本語", "日本語日本語"},
{"%.5s", []byte("日本語日本語"), "日本語日本"},
{"%.5q", "abcdefghijklmnopqrstuvwxyz", `"abcde"`},
{"%.5x", "abcdefghijklmnopqrstuvwxyz", `6162636465`},
......@@ -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) {
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
......
......@@ -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.
func (f *fmt) truncate(s string) string {
if f.precPresent && f.prec < utf8.RuneCountInString(s) {
if f.precPresent {
n := f.prec
for i := range s {
if n == 0 {
s = s[:i]
break
}
n--
if n < 0 {
return s[:i]
}
}
}
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