Slow Runt 3

Posted by jcnnghm Tue, 03 Jun 2008 12:52:00 GMT

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 daysinmonth method. That method appears to be the cause of the issue.

Trackbacks

Use the following link to trackback from your own site:
http://littlebitofcode.com/trackbacks?article_id=12

  1. http://h2lo.com/dental_health Mon, 11 Aug 2008 20:29:26 GMT

    Does anyone know if the newest version of Runt fixes this? I would like to use it on my dental hygiene site for scheduling visits for teeth cleaning.

    Thanks for any information!

  2. Lance Mon, 11 Aug 2008 20:30:16 GMT

    Sorry, the above is from me.

  3. Justin Tue, 13 Jan 2009 00:09:38 GMT

    I contributed this as a patch to Runt, as well as a few other things. The library works very well.