From 5f859ba83d4c47b6a6a75559041207387acab7ba Mon Sep 17 00:00:00 2001 From: =?utf8?q?Justin=20Nu=C3=9F?= Date: Sun, 31 May 2015 13:17:59 +0200 Subject: [PATCH] time: Use AppendFormat in Marshal[Text|JSON] The current implementations of MarshalJSON and MarshalText use time.Format which returns a string (converted from a byte slice), only to convert it back to a byte slice. Avoid the conversion (and thus an allocation) by directly appending the formatted time to a preallocated byte slice, using the new AppendFormat function, introduced in golang.org/cl/1760. This reduces the allocations done in Marshal[Text|JSON] by 50%. benchmark old ns/op new ns/op delta BenchmarkMarshalJSON 626 507 -19.01% BenchmarkMarshalText 598 511 -14.55% benchmark old allocs new allocs delta BenchmarkMarshalJSON 2 1 -50.00% BenchmarkMarshalText 2 1 -50.00% benchmark old bytes new bytes delta BenchmarkMarshalJSON 96 48 -50.00% BenchmarkMarshalText 96 48 -50.00% Fixes #11025 Change-Id: I468f78d075a6ecc1cdc839df7fb407fbc6ff2e70 Reviewed-on: https://go-review.googlesource.com/10555 Reviewed-by: Brad Fitzpatrick Run-TryBot: Brad Fitzpatrick TryBot-Result: Gobot Gobot --- src/time/time.go | 11 +++++++++-- src/time/time_test.go | 14 ++++++++++++++ 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/src/time/time.go b/src/time/time.go index 294cc77f41..c78c80c43b 100644 --- a/src/time/time.go +++ b/src/time/time.go @@ -935,7 +935,12 @@ func (t Time) MarshalJSON() ([]byte, error) { // See golang.org/issue/4556#c15 for more discussion. return nil, errors.New("Time.MarshalJSON: year outside of range [0,9999]") } - return []byte(t.Format(`"` + RFC3339Nano + `"`)), nil + + b := make([]byte, 0, len(RFC3339Nano)+2) + b = append(b, '"') + b = t.AppendFormat(b, RFC3339Nano) + b = append(b, '"') + return b, nil } // UnmarshalJSON implements the json.Unmarshaler interface. @@ -952,7 +957,9 @@ func (t Time) MarshalText() ([]byte, error) { if y := t.Year(); y < 0 || y >= 10000 { return nil, errors.New("Time.MarshalText: year outside of range [0,9999]") } - return []byte(t.Format(RFC3339Nano)), nil + + b := make([]byte, 0, len(RFC3339Nano)) + return t.AppendFormat(b, RFC3339Nano), nil } // UnmarshalText implements the encoding.TextUnmarshaler interface. diff --git a/src/time/time_test.go b/src/time/time_test.go index 2d16ea59ae..a925e98a83 100644 --- a/src/time/time_test.go +++ b/src/time/time_test.go @@ -1060,6 +1060,20 @@ func BenchmarkFormatNow(b *testing.B) { } } +func BenchmarkMarshalJSON(b *testing.B) { + t := Now() + for i := 0; i < b.N; i++ { + t.MarshalJSON() + } +} + +func BenchmarkMarshalText(b *testing.B) { + t := Now() + for i := 0; i < b.N; i++ { + t.MarshalText() + } +} + func BenchmarkParse(b *testing.B) { for i := 0; i < b.N; i++ { Parse(ANSIC, "Mon Jan 2 15:04:05 2006") -- 2.48.1