-
-
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
Cleaner (and more performant!) implementation of Time.leap_year? #5572
Comments
Please can you make a PR, would be cool to benchmark |
Yes, I'm planning on it, but it's taking a while to get all the |
@rab what exactly are you finding difficult or time-consuming, just for reference. |
Also, trying to concurrently run
in another window. (on a Mac) |
Fair enough. |
For reference, here is the theoretical performance gain:
Average 4.02 calculations per call Proposed implementation:
Average 2.52 calculations per call These calculations assume even distribution of years as input. Any suggestions on a different distribution for benchmarking? A normal distribution centered around 2018? A random distribution from 1800 - 2100? |
If a normal distribution is used, this might be a good tool: |
It's rather pedantic, but there far too much detail at the Wikipedia entry for Proleptic Gregorian calendar. The current crystal implementation already declares years outside of 1–9999 as invalid so there are additional comparisons on the As for a distribution, it would be more realistic (in my opinion) so consider that the most likely year is the current one with near future years and perhaps the past 100 years occupying most of the long-tail. Most programs rarely have to deal with years outside of a 2-lifetime-span around the current date. Given that is roughly 1918–2118, you could get by with simply
|
It's a performance improvement in theory and maybe chops off half a nanosecond here and there. So it's a valuable contribution. I don't see a point in overcomplicating this. |
OK, here's a benchmark:
First with the original code:
And again with the new code:
So @straight-shoota is definitely in the ballpark in that 0.54s faster over 10_000_000_000 runs is saving 0.054 ns per call on average. |
Yeah, seems that any change in the distribution isn't worth the effort. |
Instead of running benchmarks after benchmark, what about looking at the generated LLVM IR and compiled ASM, to check for LLVM optimizations? |
In Mark Siemers (@marksiemers) post Top 5 Reasons for Ruby-ists to Use Crystal, he used an example of a leap year predicate early in the article to demonstrate the similarity of Ruby and Crystal code. In one of the comments, an alternate implementation of a
leap_year?
predicate was offered and Mark said it looked better:Since I've written this same predicate in multiple languages and system across 30 years or more, I chimed in with a brief analysis confirming that it was better, but didn't go far enough if minimizing operations was a goal. Mark suggested that I offer my implementation as a PR.
$ git --no-pager diff --unified=5
Briefly, since 75% of all years will fail the
year % 4 == 0
test, letting the&&
short-circuit before checking for century years is a big win.The text was updated successfully, but these errors were encountered: