]> Cypherpunks repositories - gostls13.git/commitdiff
fmt: optimize string truncation
authorMartin Möhrmann <martisch@uos.de>
Wed, 2 Mar 2016 19:31:20 +0000 (20:31 +0100)
committerRob Pike <r@golang.org>
Wed, 2 Mar 2016 20:51:38 +0000 (20:51 +0000)
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>
src/fmt/fmt_test.go
src/fmt/format.go

index 0d0e3138070be9dd45a3b12a2784933e298af59c..69141a156dd3ae93d14c248e6335a27a22fc0865 100644 (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() {
index e49b8af967a431d4457202f9832ff8cd91d14a16..302f82441d9c472fd44aa2b6b9d35bbeed27859b 100644 (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