mirror of
https://github.com/golang/go
synced 2024-11-22 20:14:40 -07:00
time: optimize Format for RFC3339 and RFC3339Nano
Optimise Format for the most frequently used RFC3339 and RFC3339Nano layouts by avoiding parsing of layout. > benchstat oldBench.txt newBench.txt name old time/op new time/op delta FormatRFC3339-8 302ns ± 1% 203ns ± 0% -32.89% (p=0.016 n=5+4) FormatRFC3339Nano-8 337ns ± 1% 219ns ± 1% -34.91% (p=0.008 n=5+5) name old alloc/op new alloc/op delta FormatRFC3339-8 32.0B ± 0% 32.0B ± 0% ~ (all equal) FormatRFC3339Nano-8 32.0B ± 0% 32.0B ± 0% ~ (all equal) name old allocs/op new allocs/op delta FormatRFC3339-8 1.00 ± 0% 1.00 ± 0% ~ (all equal) FormatRFC3339Nano-8 1.00 ± 0% 1.00 ± 0% ~ (all equal) Fixes #54093 Change-Id: Ifc84fce6078e24514ecbcd234875bca4aaab5e0e Reviewed-on: https://go-review.googlesource.com/c/go/+/421877 Run-TryBot: Ian Lance Taylor <iant@google.com> Auto-Submit: Joseph Tsai <joetsai@digital-static.net> TryBot-Result: Gopher Robot <gobot@golang.org> Auto-Submit: Ian Lance Taylor <iant@google.com> Reviewed-by: Than McIntosh <thanm@google.com> Reviewed-by: Ian Lance Taylor <iant@google.com> Reviewed-by: Joseph Tsai <joetsai@digital-static.net> Run-TryBot: Joseph Tsai <joetsai@digital-static.net>
This commit is contained in:
parent
8298c545f3
commit
133c0e9011
@ -626,6 +626,15 @@ func (t Time) AppendFormat(b []byte, layout string) []byte {
|
||||
min int
|
||||
sec int
|
||||
)
|
||||
|
||||
// Handle most frequent layouts separately.
|
||||
switch layout {
|
||||
case RFC3339:
|
||||
return t.appendFormatRFC3339(b, abs, offset, false)
|
||||
case RFC3339Nano:
|
||||
return t.appendFormatRFC3339(b, abs, offset, true)
|
||||
}
|
||||
|
||||
// Each iteration generates one std value.
|
||||
for layout != "" {
|
||||
prefix, std, suffix := nextStdChunk(layout)
|
||||
@ -781,6 +790,48 @@ func (t Time) AppendFormat(b []byte, layout string) []byte {
|
||||
return b
|
||||
}
|
||||
|
||||
func (t Time) appendFormatRFC3339(b []byte, abs uint64, offset int, nanos bool) []byte {
|
||||
// Format date.
|
||||
year, month, day, _ := absDate(abs, true)
|
||||
b = appendInt(b, year, 4)
|
||||
b = append(b, '-')
|
||||
b = appendInt(b, int(month), 2)
|
||||
b = append(b, '-')
|
||||
b = appendInt(b, day, 2)
|
||||
|
||||
b = append(b, 'T')
|
||||
|
||||
// Format time.
|
||||
hour, min, sec := absClock(abs)
|
||||
b = appendInt(b, hour, 2)
|
||||
b = append(b, ':')
|
||||
b = appendInt(b, min, 2)
|
||||
b = append(b, ':')
|
||||
b = appendInt(b, sec, 2)
|
||||
|
||||
if nanos {
|
||||
std := stdFracSecond(stdFracSecond9, 9, '.')
|
||||
b = formatNano(b, uint(t.Nanosecond()), std)
|
||||
}
|
||||
|
||||
if offset == 0 {
|
||||
return append(b, 'Z')
|
||||
}
|
||||
|
||||
// Format zone.
|
||||
zone := offset / 60 // convert to minutes
|
||||
if zone < 0 {
|
||||
b = append(b, '-')
|
||||
zone = -zone
|
||||
} else {
|
||||
b = append(b, '+')
|
||||
}
|
||||
b = appendInt(b, zone/60, 2)
|
||||
b = append(b, ':')
|
||||
b = appendInt(b, zone%60, 2)
|
||||
return b
|
||||
}
|
||||
|
||||
var errBad = errors.New("bad value for field") // placeholder not passed to user
|
||||
|
||||
// ParseError describes a problem parsing a time string.
|
||||
|
@ -1402,6 +1402,20 @@ func BenchmarkFormat(b *testing.B) {
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkFormatRFC3339(b *testing.B) {
|
||||
t := Unix(1265346057, 0)
|
||||
for i := 0; i < b.N; i++ {
|
||||
t.Format("2006-01-02T15:04:05Z07:00")
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkFormatRFC3339Nano(b *testing.B) {
|
||||
t := Unix(1265346057, 0)
|
||||
for i := 0; i < b.N; i++ {
|
||||
t.Format("2006-01-02T15:04:05.999999999Z07:00")
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkFormatNow(b *testing.B) {
|
||||
// Like BenchmarkFormat, but easier, because the time zone
|
||||
// lookup cache is optimized for the present.
|
||||
|
Loading…
Reference in New Issue
Block a user