Slow Runt 3
While unit testing some code that I’ve been working on that uses the excellent runt library, I ran into a bit of code that was quite slow. When calling the include? method of the Runt::DIMonth class with a negative value for the week of the month argument (i.e. DIMonth.new(-1,6).include?(date)) it took over 120 seconds to execute my unit tests.
I replaced the method max_day_of_month (Runt::TExprUtils), as listed below:
def max_day_of_month(date)
result = 1
next_month = nil
if(date.mon==12)
next_month = Date.new(date.year+1,1,1)
else
next_month = Date.new(date.year,date.mon+1,1)
end
date.step(next_month,1){ |d| result=d.day unless d.day < result }
result
end
with the following code:
def max_day_of_month(date)
month = date.month
year = date.year
if month == 2
!year.nil? && (year % 4 == 0) && ((year % 100 != 0) || (year % 400 == 0)) ? 29 : 28
elsif month <= 7
month % 2 == 0 ? 30 : 31
else
month % 2 == 0 ? 31 : 30
end
end
The same unit tests can now be performed in under two seconds. I didn’t write the algorithm, it’s taken verbatim from the Rails ActiveSupport::CoreExtensions::Time::Calculations::ClassMethods module days_in_month method. That method appears to be the cause of the issue.