From: Kyle Consalus Date: Wed, 5 Jan 2011 19:42:35 +0000 (-0800) Subject: Made format string handling more efficient. X-Git-Tag: weekly.2011-01-06~8 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=754f0402c3d570e9d956b491f0434e1fccff6e6f;p=gostls13.git Made format string handling more efficient. R=rsc, r, r2 CC=golang-dev https://golang.org/cl/3421042 --- diff --git a/src/pkg/fmt/fmt_test.go b/src/pkg/fmt/fmt_test.go index 0234ad41d3..0aafe6d994 100644 --- a/src/pkg/fmt/fmt_test.go +++ b/src/pkg/fmt/fmt_test.go @@ -45,11 +45,6 @@ func TestFmtInterface(t *testing.T) { } } -type fmtTest struct { - fmt string - val interface{} - out string -} const b32 uint32 = 1<<32 - 1 const b64 uint64 = 1<<64 - 1 @@ -106,7 +101,11 @@ func (p *P) String() string { var b byte -var fmttests = []fmtTest{ +var fmttests = []struct { + fmt string + val interface{} + out string +}{ {"%d", 12345, "12345"}, {"%v", 12345, "12345"}, {"%t", true, "true"}, @@ -439,6 +438,12 @@ func BenchmarkSprintfIntInt(b *testing.B) { } } +func BenchmarkSprintfPrefixedInt(b *testing.B) { + for i := 0; i < b.N; i++ { + Sprintf("This is some meaningless prefix text that needs to be scanned %d", 6) + } +} + func TestCountMallocs(t *testing.T) { mallocs := 0 - runtime.MemStats.Mallocs for i := 0; i < 100; i++ { @@ -485,12 +490,10 @@ func (*flagPrinter) Format(f State, c int) { io.WriteString(f, "["+s+"]") } -type flagTest struct { +var flagtests = []struct { in string out string -} - -var flagtests = []flagTest{ +}{ {"%a", "[%a]"}, {"%-a", "[%-a]"}, {"%+a", "[%+a]"}, @@ -524,11 +527,10 @@ func TestStructPrinter(t *testing.T) { s.a = "abc" s.b = "def" s.c = 123 - type Test struct { + var tests = []struct { fmt string out string - } - var tests = []Test{ + }{ {"%v", "{abc def 123}"}, {"%+v", "{a:abc b:def c:123}"}, } @@ -622,13 +624,11 @@ func TestFormatterPrintln(t *testing.T) { func args(a ...interface{}) []interface{} { return a } -type starTest struct { +var startests = []struct { fmt string in []interface{} out string -} - -var startests = []starTest{ +}{ {"%*d", args(4, 42), " 42"}, {"%.*d", args(4, 42), "0042"}, {"%*.*d", args(8, 4, 42), " 0042"}, @@ -644,18 +644,9 @@ var startests = []starTest{ {"%*d", args(int32(4), 42), "%!(BADWIDTH)42"}, } -// TODO: there's no conversion from []T to ...T, but we can fake it. These -// functions do the faking. We index the table by the length of the param list. -var sprintf = []func(string, []interface{}) string{ - 0: func(f string, i []interface{}) string { return Sprintf(f) }, - 1: func(f string, i []interface{}) string { return Sprintf(f, i[0]) }, - 2: func(f string, i []interface{}) string { return Sprintf(f, i[0], i[1]) }, - 3: func(f string, i []interface{}) string { return Sprintf(f, i[0], i[1], i[2]) }, -} - func TestWidthAndPrecision(t *testing.T) { for _, tt := range startests { - s := sprintf[len(tt.in)](tt.fmt, tt.in) + s := Sprintf(tt.fmt, tt.in...) if s != tt.out { t.Errorf("%q: got %q expected %q", tt.fmt, s, tt.out) } diff --git a/src/pkg/fmt/print.go b/src/pkg/fmt/print.go index 8cc54ed8c6..412260441f 100644 --- a/src/pkg/fmt/print.go +++ b/src/pkg/fmt/print.go @@ -118,12 +118,7 @@ func (p *pp) Flag(b int) bool { } func (p *pp) add(c int) { - if c < utf8.RuneSelf { - p.buf.WriteByte(byte(c)) - } else { - w := utf8.EncodeRune(p.runeBuf[0:], c) - p.buf.Write(p.runeBuf[0:w]) - } + p.buf.WriteRune(c) } // Implement Write so we can call Fprintf on a pp (through State), for @@ -825,12 +820,18 @@ func (p *pp) doPrintf(format string, a []interface{}) { end := len(format) fieldnum := 0 // we process one field per non-trivial format for i := 0; i < end; { - c, w := utf8.DecodeRuneInString(format[i:]) - if c != '%' { - p.buf.WriteRune(c) - i += w - continue + lasti := i + for i < end && format[i] != '%' { + i++ + } + if i > lasti { + p.buf.WriteString(format[lasti:i]) } + if i >= end { + // done processing format string + break + } + // Process one verb i++ // flags and widths @@ -876,7 +877,7 @@ func (p *pp) doPrintf(format string, a []interface{}) { p.buf.Write(noVerbBytes) continue } - c, w = utf8.DecodeRuneInString(format[i:]) + c, w := utf8.DecodeRuneInString(format[i:]) i += w // percent is special - absorbs no operand if c == '%' {