rickar/cal

Performance degradation in IsHoliday

Closed this issue · 2 comments

func Benchmark2017IsHoliday(b *testing.B) {
	for i := 0; i < b.N; i++ {
		MonThruSatCal.IsHoliday(time.Date(2017, time.January, 3, 0, 0, 0, 0, time.Local))
	}
}

// v1.0.5
goos: darwin
goarch: amd64
cpu: Intel(R) Core(TM) i7-9750H CPU @ 2.60GHz
Benchmark2017IsHoliday-12    	 6088034	       209.7 ns/op	       0 B/op	       0 allocs/op
PASS

// v2.0.2
goos: darwin
goarch: amd64
cpu: Intel(R) Core(TM) i7-9750H CPU @ 2.60GHz
Benchmark2017IsHoliday-12    	  402406	      2824 ns/op	       0 B/op	       0 allocs/op
PASS

After updating to v2.0.2 we noticed a performance degradation in our application and tracked it down to this library. after digging into the methods we were running it looks like it's coming from IsHoliday(). We create a calendar that includes Saturday as a workday with most US holidays. It looks like this function is over 10x slower than the v1 equivalent.

Most of the slowdown seems to be from supporting alternate timezones. time.Date() internally looks up timezones constantly. A big improvement comes from setting cal.DefaultLoc to time.UTC.

In any case, I was able to make some improvements and get it down to roughly ~2x slower instead of ~10x.

The fix for this ended up causing issues with custom calcs, so I changed to allow an optional internal cache. With the Cacheable flag enabled on the Calendar, it runs ~50x faster than the original v2 code and about ~3x faster than the v1 code.