1
0
mirror of https://github.com/golang/go synced 2024-11-24 14:20:13 -07:00

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/20098
Reviewed-by: Rob Pike <r@golang.org>
This commit is contained in:
Martin Möhrmann 2016-03-02 20:31:20 +01:00 committed by Rob Pike
parent 2faf5bca2e
commit 83765d135f
2 changed files with 14 additions and 5 deletions

View File

@ -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() {

View File

@ -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