From 676f9dfa067ec4990b45c7f91364c680d04beb99 Mon Sep 17 00:00:00 2001 From: Rob Pike Date: Thu, 7 Jan 2010 14:36:54 +1100 Subject: [PATCH] make Format about twice as fast by removing allocations, using a bytes.Buffer add a benchmark R=rsc CC=golang-dev https://golang.org/cl/181164 --- src/pkg/time/format.go | 52 ++++++++++++++++----------------------- src/pkg/time/time_test.go | 7 ++++++ 2 files changed, 28 insertions(+), 31 deletions(-) diff --git a/src/pkg/time/format.go b/src/pkg/time/format.go index 52d62a9086..28550aa364 100644 --- a/src/pkg/time/format.go +++ b/src/pkg/time/format.go @@ -1,6 +1,7 @@ package time import ( + "bytes" "strconv" ) @@ -12,16 +13,17 @@ const ( // These are predefined layouts for use in Time.Format. // The standard time used in the layouts is: -// Mon Jan 2 15:04:05 PST 2006 (PST is GMT-0800) +// Mon Jan 2 15:04:05 MST 2006 (MST is GMT-0700) // which is Unix time 1136243045. +// (Think of it as 01/02 03:04:05PM '06 -0700.) const ( ANSIC = "Mon Jan 2 15:04:05 2006" - UnixDate = "Mon Jan 2 15:04:05 PST 2006" - RFC850 = "Monday, 02-Jan-06 15:04:05 PST" - RFC1123 = "Mon, 02 Jan 2006 15:04:05 PST" + UnixDate = "Mon Jan 2 15:04:05 MST 2006" + RFC850 = "Monday, 02-Jan-06 15:04:05 MST" + RFC1123 = "Mon, 02 Jan 2006 15:04:05 MST" Kitchen = "3:04PM" // Special case: use Z to get the time zone formatted according to ISO 8601, - // which is -0800 or Z for UTC + // which is -0700 or Z for UTC ISO8601 = "2006-01-02T15:04:05Z" ) @@ -46,7 +48,7 @@ const ( stdZulu = "1504" stdPM = "PM" stdpm = "pm" - stdTZ = "PST" + stdTZ = "MST" stdISO8601TZ = "Z" ) @@ -112,26 +114,6 @@ func charType(c uint8) int { return separator } -func pieces(s string) []string { - p := make([]string, 20) - i := 0 - // Each iteration generates one piece - for n := range p { - if i >= len(s) { - p = p[0:n] - break - } - start := i - c := s[i] - pieceType := charType(c) - for i < len(s) && charType(s[i]) == pieceType { - i++ - } - p[n] = s[start:i] - } - return p -} - func zeroPad(i int) string { s := strconv.Itoa(i) if i < 10 { @@ -146,9 +128,17 @@ func zeroPad(i int) string { // the time to be formatted. Predefined layouts ANSIC, UnixDate, // ISO8601 and others describe standard representations. func (t *Time) Format(layout string) string { - pc := pieces(layout) - s := "" - for _, p := range pc { + b := new(bytes.Buffer) + // Each iteration generates one piece + for len(layout) > 0 { + c := layout[0] + pieceType := charType(c) + i := 0 + for i < len(layout) && charType(layout[i]) == pieceType { + i++ + } + p := layout[0:i] + layout = layout[i:] switch p { case stdYear: p = strconv.Itoa64(t.Year % 100) @@ -218,9 +208,9 @@ func (t *Time) Format(layout string) string { case stdTZ: p = t.Zone } - s += p + b.WriteString(p) } - return s + return b.String() } // String returns a Unix-style representation of the time value. diff --git a/src/pkg/time/time_test.go b/src/pkg/time/time_test.go index 4dfdea4456..8f7c267cb6 100644 --- a/src/pkg/time/time_test.go +++ b/src/pkg/time/time_test.go @@ -161,3 +161,10 @@ func BenchmarkNanoseconds(b *testing.B) { Nanoseconds() } } + +func BenchmarkFormat(b *testing.B) { + time := SecondsToLocalTime(1265346057) + for i := 0; i < b.N; i++ { + time.Format("Mon Jan 2 15:04:05 2006") + } +} -- 2.48.1