dateparse/bench_test.go
Klondike Dragon 23f8fa1af0 Further optimize ambiguous parsing
Optimize the common and special case where mm and dd are the same length, just swap in place. Avoids having to reparse the entire string.

For this case, it's about 30% faster and reduces allocations by about 15%.

This format is especially common, hence the reason to optimize for this case.

Also fix the case for ambiguous date/time in the mm:dd:yyyy format.
2023-12-16 13:52:00 -07:00

174 lines
3.9 KiB
Go

package dateparse
import (
"fmt"
"testing"
"time"
)
/*
go test -bench Parse
BenchmarkShotgunParse 50000 37588 ns/op 13258 B/op 167 allocs/op
BenchmarkDateparseParseAny 500000 5752 ns/op 0 B/op 0 allocs/op
// Aarons Laptop Lenovo 900 Feb 2018
BenchmarkShotgunParse-4 50000 30045 ns/op 13136 B/op 169 allocs/op
BenchmarkParseAny-4 200000 8627 ns/op 144 B/op 3 allocs/op
// ifreddyrondon Laptop MacBook Pro (Retina, Mid 2012) March 2018
BenchmarkShotgunParse-8 50000 33940 ns/op 13136 B/op 169 allocs/op
BenchmarkParseAny-8 200000 10146 ns/op 912 B/op 29 allocs/op
BenchmarkParseDateString-8 10000 123077 ns/op 208 B/op 13 allocs/op
*/
func BenchmarkShotgunParse(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
for _, dateStr := range testDates {
// This is the non dateparse traditional approach
_, _ = parseShotgunStyle(dateStr)
}
}
}
func BenchmarkParseAny(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
for _, dateStr := range testDates {
_, _ = ParseAny(dateStr)
}
}
}
func BenchmarkBigShotgunParse(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
for _, t := range testInputs {
// This is the non dateparse traditional approach
_, _ = parseShotgunStyle(t.in)
}
}
}
func BenchmarkBigParseAny(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
for _, t := range testInputs {
_, _ = ParseAny(t.in)
}
}
}
func BenchmarkBigParseIn(b *testing.B) {
b.ReportAllocs()
loc, _ := time.LoadLocation("America/New_York")
for i := 0; i < b.N; i++ {
for _, t := range testInputs {
_, _ = ParseIn(t.in, loc)
}
}
}
func BenchmarkBigParseRetryAmbiguous(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
for _, t := range testInputs {
_, _ = ParseAny(t.in, RetryAmbiguousDateWithSwap(true))
}
}
}
func BenchmarkShotgunParseErrors(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
for _, t := range testParseErrors {
// This is the non dateparse traditional approach
_, _ = parseShotgunStyle(t.in)
}
}
}
func BenchmarkParseAnyErrors(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
for _, t := range testParseErrors {
_, _ = ParseAny(t.in)
}
}
}
func BenchmarkParseAmbiguous(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
MustParse("13/02/2014 04:08:09 +0000 UTC", RetryAmbiguousDateWithSwap(true))
}
}
/*
func BenchmarkParseDateString(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
for _, dateStr := range testDates {
timeutils.ParseDateString(dateStr)
}
}
}
*/
var (
testDates = []string{
"2012/03/19 10:11:59",
"2012/03/19 10:11:59.3186369",
"2009-08-12T22:15:09-07:00",
"2014-04-26 17:24:37.3186369",
"2012-08-03 18:31:59.257000000",
"2013-04-01 22:43:22",
"2014-04-26 17:24:37.123",
"2014-12-16 06:20:00 UTC",
"1384216367189",
"1332151919",
"2014-05-11 08:20:13,787",
"2014-04-26 05:24:37 PM",
"2014-04-26",
}
ErrDateFormat = fmt.Errorf("invalid date format")
timeFormats = []string{
// ISO 8601ish formats
time.RFC3339Nano,
time.RFC3339,
// Unusual formats, prefer formats with timezones
time.RFC1123Z,
time.RFC1123,
time.RFC822Z,
time.RFC822,
time.UnixDate,
time.RubyDate,
time.ANSIC,
// Hilariously, Go doesn't have a const for it's own time layout.
// See: https://code.google.com/p/go/issues/detail?id=6587
"2006-01-02 15:04:05.999999999 -0700 MST",
// No timezone information
"2006-01-02T15:04:05.999999999",
"2006-01-02T15:04:05",
"2006-01-02 15:04:05.999999999",
"2006-01-02 15:04:05",
}
)
func parseShotgunStyle(raw string) (time.Time, error) {
for _, format := range timeFormats {
t, err := time.Parse(format, raw)
if err == nil {
// Parsed successfully
return t, nil
}
}
return time.Time{}, ErrDateFormat
}