Proposal for new approach with nanoseconds integers#107
Proposal for new approach with nanoseconds integers#107ChristopherRabotin merged 18 commits intonyx-space:masterfrom
Conversation
|
Thanks for the pr! If I read the benchmarks correctly, using nanos and centuries is about 3 times faster than two floats for the Also, for the record, the conversion was about whether an FPU was available on embedded platforms, right? And that, typically, an FPU is slower than a APU. Was there another reason? |
|
Just updated the PR. Indeed, going to f64 is slower but all other operations in the end should be faster. For now, I use a 128-bit type as intermediary for the addition operation, which should not be needed when optimizing further as we could switch to a Apart for performance, advantages are compatibility with platforms without FPU and guaranteed nanosecond-precision anywhere in the possible Duration range (implementations using floating-points have variable time precision across the range, with very low precision at the extremes). |
f3b75bc to
bb28a35
Compare
|
Cleaned-up the branch a bit, almost all tests are passing now. Still need some work on the printing side, and it looks like there might be some nasty rounding errors I need to track down, but I'm positive this gets finalized soon™ |
7604317 to
1529409
Compare
ChristopherRabotin
left a comment
There was a problem hiding this comment.
Very good job! I think we (you) should change centuries to a smaller representation because we don't need lots of bits there. Also, avoid the overflows with the ::from() call instead of coercing the conversion where possible.
src/duration.rs
Outdated
There was a problem hiding this comment.
Yes, I think that an i16 would be sufficient: that's still 256 centuries before J1900 and after J1900, so about 38% to the oldest cave paintings in the world (-660 centuries ago).
Also, in doing so, we're moving from 2x64 bits to 64+16=80 bits, thereby saving 48 bits.
src/duration.rs
Outdated
There was a problem hiding this comment.
| pub fn new(ns : u64, centuries : i64) -> Self { | |
| pub fn new(centuries : i64, ns : u64) -> Self { |
It makes more sense to me to have the larger representation first.
src/duration.rs
Outdated
There was a problem hiding this comment.
From my rough math, it seems like an i128 can represent +/- 5.8 centuries. So I think there should be several functions instead of just total_ns, and I think that total_ns should have a warning: "Will panic if more than 5.8 centuries away from J1900". Then, add a try_total_ns that can't panic (returns a Result<i128, Error> of enum Overflow or something like that). And a third function called try_ns_from(baseline_century: i16) that shifts the reference century.
Question: should the base century be J2000? All astro stuff uses J2000, only Network Time Protocol uses J1900, but all of our applications so far are for astro...
>>> (2**64 / (1e9)) / (86400.*365.25*100)
5.845420460906264
There was a problem hiding this comment.
Maybe the switch to J2000 should be done in another PR to merge this one in faster.
src/duration.rs
Outdated
There was a problem hiding this comment.
I think that where possible, the code should be u64::from(...) because that forces the compiler to check that the operation is lossless and can't panic. This would give me some reassurance in the conversions.
src/duration.rs
Outdated
There was a problem hiding this comment.
Yeah, that's fair. We should add tests for that and try to de-risk it, maybe by doing lots of conversions manually or the u64::from method.
src/duration.rs
Outdated
There was a problem hiding this comment.
Because my Display implementation adds a space at the end of the string and I thought I'd rather trim() the tests than add complexity to the impl just for a single space
src/duration.rs
Outdated
There was a problem hiding this comment.
Nice! This is better I think
src/duration.rs
Outdated
There was a problem hiding this comment.
Hmm, why is this test different? Actually, shouldn't the original test ending with 123ns actually display 203 nanoseconds as you do? Seems like a bug in the previous version
src/duration.rs
Outdated
There was a problem hiding this comment.
Are you sure this test is correct? Can we add more years tests because I'm just worried we'll get the conversion wrong.
There was a problem hiding this comment.
I assumed 1 year = 365 days, as this is only used for Display. It's easy to rollback the years part of the decomposition if you're not comfortable with it, I just thought I'd roll with it as it was basically free in the new Display impl. We could indeed add more years tests though
There was a problem hiding this comment.
I think that the IETF or someone defines a year as 365.25 days (since one century is 36525 days). But the problem is that it's an approximate definition, and that's why lots of implementations don't allow for year based computations: it's confusing.
There was a problem hiding this comment.
Understood, it makes sense, I will remove this part of the decomposition then
|
Okay, I did a few changes to this branch. It doesn't work yet, but there's progress: I unified the |
|
Just posting some temporary benchmarks from this PR after I started working on it last week. Summary:
With nanosecond precisionWith TwoFloatNote: this was executed after the nanosecond precision so the "performance" increase/decrease metrics are compared to the nanosecond branch |
Signed-off-by: Christopher Rabotin <christopher.rabotin@gmail.com>
Remove lots of impl_ops for Duration because rustc isn't happy Signed-off-by: Christopher Rabotin <christopher.rabotin@gmail.com>
|
Crap... just implement a bunch of code fixes and now the performance is quite bad. Edit: I think the issue is the creation of a |
Signed-off-by: Christopher Rabotin <christopher.rabotin@gmail.com>
Signed-off-by: Christopher Rabotin <christopher.rabotin@gmail.com>
|
Ha! Switching the creation of a |
Signed-off-by: Christopher Rabotin <christopher.rabotin@gmail.com>
Signed-off-by: Christopher Rabotin <christopher.rabotin@gmail.com>
Signed-off-by: Christopher Rabotin <christopher.rabotin@gmail.com>
Signed-off-by: Christopher Rabotin <christopher.rabotin@gmail.com>
|
Final benchmarks
|
Signed-off-by: Christopher Rabotin <christopher.rabotin@gmail.com>
Signed-off-by: Christopher Rabotin <christopher.rabotin@gmail.com>
Did some light refactoring and benchmarked (will be deleted before merging). What are your thoughts about this approach ?
Note : this currently relies on bigint_helper_methods (rust-lang/rust#85532) so compiles on Nightly only