Optimize memory for error case

New option SimpleErrorMessages that avoids allocation in the error path. It's off by default to preserve backwards compatibility.

Added benchmark BenchmarkBigParseAnyErrors that takes the big set of test cases, and injects errors to make them fail at pseudo-random places.

This optimization speeds up the error path runtime by 4x and reduces error path allocation bytes by 13x!
This commit is contained in:
Klondike Dragon
2023-12-16 23:28:15 -07:00
parent d2e1443c4d
commit fbf07cc274
4 changed files with 330 additions and 215 deletions

View File

@@ -71,9 +71,11 @@ func BenchmarkBigParseIn(b *testing.B) {
func BenchmarkBigParseRetryAmbiguous(b *testing.B) {
b.ReportAllocs()
opts := []ParserOption{RetryAmbiguousDateWithSwap(true)}
b.ResetTimer()
for i := 0; i < b.N; i++ {
for _, t := range testInputs {
_, _ = ParseAny(t.in, RetryAmbiguousDateWithSwap(true))
_, _ = ParseAny(t.in, opts...)
}
}
}
@@ -90,17 +92,48 @@ func BenchmarkShotgunParseErrors(b *testing.B) {
func BenchmarkParseAnyErrors(b *testing.B) {
b.ReportAllocs()
opts := []ParserOption{SimpleErrorMessages(true)}
b.ResetTimer()
for i := 0; i < b.N; i++ {
for _, t := range testParseErrors {
_, _ = ParseAny(t.in)
_, _ = ParseAny(t.in, opts...)
}
}
}
func BenchmarkBigParseAnyErrors(b *testing.B) {
b.ReportAllocs()
opts := []ParserOption{SimpleErrorMessages(true)}
// manufacture a bunch of different tests with random errors put in them
var testBigErrorInputs []string
for index, t := range testInputs {
b := []byte(t.in)
spread := 4 + (index % 4)
startingIndex := spread % len(b)
for i := startingIndex; i < len(b); i += spread {
b[i] = '?'
}
testBigErrorInputs = append(testBigErrorInputs, string(b))
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
for _, in := range testBigErrorInputs {
_, err := ParseAny(in, opts...)
if err == nil {
panic(fmt.Sprintf("expected parsing to fail: %s", in))
}
}
}
}
func BenchmarkParseAmbiguous(b *testing.B) {
b.ReportAllocs()
opts := []ParserOption{RetryAmbiguousDateWithSwap(true)}
b.ResetTimer()
for i := 0; i < b.N; i++ {
MustParse("13/02/2014 04:08:09 +0000 UTC", RetryAmbiguousDateWithSwap(true))
MustParse("13/02/2014 04:08:09 +0000 UTC", opts...)
}
}