-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Alter logic in Time.leap_year? for performance #5575
Conversation
spec/std/time/time_spec.cr
Outdated
@@ -745,6 +745,29 @@ describe Time do | |||
Time.days_in_year(1990).should eq(365) | |||
end | |||
|
|||
it "knows which years are leap_year?" do | |||
{ 1900 => false, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great to include a spec for this!
Though I'd suggest to write it like this:
{1900, 1965, 1999, 2001, 2018, 2019, 2021, 2099, 2100, 2101, 2200}.each do |year|
Time.leap_year?(year).should be_false
end
{1968, 1972, 2000, 2004, 2020, 2400}.each do |year|
Time.leap_year?(year).should be_true
end
I'd prefer this but it's just a nitpicking suggestion...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Assuming that you also meant to change those to be valid syntax for Array(Int32)
with […]
rather than {…}
, I'd be OK with that. Let me know if you intended that to be an action item, too, or just a nitpick.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it would be better that way, but I don't know what others think...
{ ... }
was intended, that's a tuple literal.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, very new to crystal so that's my first encounter with a tuple literal!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It might also be quite reasonable to split this into 4 separate test cases:
- 400-year leap years:
{1600, 2000, 2400}
- 100-year normal years:
{1700, 1800, 1900, 2100, 2200, 2300}
- typical non-century leap years:
{1968, 1972, 2004, 2020}
- a smattering of non-century normal years:
{1965, 1999, 2001, 2018, 2019, 2021, 2099, 2101}
Benchmark: require "benchmark"
def leap_year_old?(year)
unless 1 <= year <= 9999
raise ArgumentError.new "Invalid year"
end
(year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)
end
def leap_year_new?(year)
unless 1 <= year <= 9999
raise ArgumentError.new "Invalid year"
end
year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)
end
numbers = Array.new(100_000) { rand(1..9999) }
a = 0
b = 0
Benchmark.ips do |x|
x.report("old") do
a = numbers.count { |i| leap_year_old?(i) }
end
x.report("new") do
b = numbers.count { |i| leap_year_new?(i) }
end
end
puts a, b Output:
It seems slower. So 👎 for me. |
Actually... when I try with all numbers from 1 to 9999 without randomness:
I get:
Then when I try it with more numbers (uniformly distributed):
I get:
So it seems to be faster if the numbers are uniformly distributed. But if they are random (I would suppose that's uniform too?) it's slower. I don't know what's going on. |
Well, If you "randomly" got a bunch of multiples of 4, then it would tend to even out. Here's a take:
|
Just to beat this dead 🐴 a bit more. (Noting that the best, bad, and worst case numbers are based on the order of operations in
Gives: (after reordering from "best" to "worst")
|
Let the && short-circuit the evaluation for all years that are *not* divisible by 4 (i.e., 75% of them!).
31e97d1
to
ff7a62b
Compare
Didn't realize that the CI would be so picky about formatting. |
Merge 🕦? |
Let the && short-circuit the evaluation for all years that are not
divisible by 4 (i.e., 75% of them!).
Can close #5572