nyx-space / hifitime

A high fidelity time management library in Rust

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Increase precision of Duration to cover 10^-29 seconds to 10^28 seconds

ChristopherRabotin opened this issue · comments

commented

This is really just for fun and I don't imagine anyone ever needing this, but behind an ultra feature crate, the Duration struct could change the centuries from i16 to i64 and add a subnanos field of type u64. This would make the structure relatively big (192 bits / 24 octets) but it would allow representations of duration from 5.4e-29 seconds (or 54 quectoseconds) to 2.9e+28 seconds (2.9e+4 yottaseconds or 29 qettaseconds).

According to https://en.wikipedia.org/wiki/Orders_of_magnitude_(time), this means that the smallest duration would be 162 thousand times longer than the mean lifetime of W and Z bosons and the largest time would be just short of the radioactive half-life of tellurium-128, the longest known half-life of any elemental isotope.

All in one library! \o/

Note: Currently, the maximum duration is 1.03e+14 seconds, or just short of the typical lifetime of a biological species on Earth (130 teraseconds -- Duration::MAX is 103 teraseconds).

Math:

In [7]: f"{Duration.init_from_max().to_seconds():e}"
Out[7]: '1.034079e+14'
In [8]: 1.0/2**64 * 1e-9 # they are sub-nanoseconds hence the 1e-9
Out[8]: 5.421010862427523e-29
(...)
In [14]: (Unit.Century * 1).to_seconds()
Out[14]: 3155760000.0

In [15]: 2**(64-1) * 3155760000.0 # we can't do the math with Durations since they max out
Out[15]: 2.9106748539024827e+28
commented

More seriously, it might make sense to have a crate feature called attosecond where simply a u32 would be added as subnanos.

Adding a u32 as subnanos would support 0.2328... attoseconds. Note that to support all of the specs of the Precise Time Protocol, femtoseconds may be needed since the maximum allowable Jitter is 250 fm: https://github.com/opencomputeproject/Time-Appliance-Project/tree/master/Open-Time-Server/#pps-out .

In [3]: 1.0/2**32 * 1e-9
Out[3]: 2.3283064365386964e-19
commented

I should run some benchmarks to see if there is any impact in changing the centuries to a 32 bit integer and adding that subnanos field. The fields of Duration are not exposed publicly, so changing those won't be a breaking change.

Hello,

I'm curious as to where this topic lies on your roadmap ?

You have stated in several places that the current accuracy is 1E-9s.
My current application is RADAR positioning, which is then theoretically limited to 30cm accuracy.
When you say 1E-9, I presume it is not the actual accuracy but more like the smallest error the testbench tolerates, therefore the "garanteed" value, is that correct ? Don't get me wrong, it's great to have one, very few people go this far because it's usually the most complex thing to express, correctly define and target. And I say this because I work in the industry, use and make instruments 🤣

So far my experience is that hifitime has never been the limiting factor, but I'm also thinking about the future and what we could do better and hope for. IMO it would be the minimum to support what PTP requires. I'm pretty sure PTP will once again evolve very soon, most likely when PTP3/White rabbit becomes the standard, which already achieves 1E-11 accuracy (somewhere around that). Lab clocks from the 90s have an accuracy of 1E-15 at 1second. The best clock these days are located around 1E-18/1E-19 (optical clocks). Anyways, I would argue that it is not something you want to change regularly and should be well thought ahead and scaled properly (and indeed, should remain focused on physics). And also, a 10x magnitude margin is always minimum :)

Side note (a)

I have been trying to keep track of this project for a while, but just like you I am far too involved in my own stuff, it is hard to take part in anything else. I'm curious as to how they express time. If they did not choose hifitime, it might be a good idea to discuss and see if they could join the adventure

Side note (b)

Me laughing at this proposal, is not me laughing at the actual proposal but more at the idea of making this toolkit better, while it is already outstanding. And yes, emojis are not and will never be proper means of communications 😆

So I've yet to start any work on this, but if needed, I don't think it'll be a huge amount of work (especially once #296 is implemented since lots of the testing can be formally verified). As long as there is no backward incompatibility, we could also plan this for version 4.1.

Concerning stattime, I reached out to them a while ago and never heard back: pendulum-project/statime#333 . They only closed the issue without comment. So I assume that they are more interested in rewriting the code and opening the door for mistakes that have been solved with hifitime -- but it isn't my problem ;-) I know of at least one other project that didn't want to use hifitime although they have exactly the same use case I had originally, and specifically because they said that they want to try to make something similar.

So I've yet to start any work on this, but if needed, I don't think it'll be a huge amount of work (especially once #296 is implemented since lots of the testing can be formally verified). As long as there is no backward incompatibility, we could also plan this for version 4.1.

Sounds great

Concerning stattime, I reached out to them a while ago and never heard back: pendulum-project/statime#333 . They only closed the issue without comment. So I assume that they are more interested in rewriting the code and opening the door for mistakes that have been solved with hifitime -- but it isn't my problem ;-) I know of at least one other project that didn't want to use hifitime although they have exactly the same use case I had originally, and specifically because they said that they want to try to make something similar.

it looks like a private company (although I don't really quite grasp these private companies working on github). That's their decision, we'll see what they achieve. I see that they use std::time shipped by tokio. As a side note, all my GNSS related libraries (which I consider my "main" libraries these days) use hifitime and not std anymore

Should Duration be a single i128?

Currently Unit supports multiplications with one float type (f64) and one signed integer type (i64). The advantage of supporting only one type for each is that when the user requests something like 0.159 * Unit::Second, the compiler knows to convert that 0.159 to a f64. Similarly, when the user specifies -159 * Unit::Centuries, the compiler knows to convert that to a i64.

Using a single i128 integer would allow the Duration to cover 5e19 centuries if that was an integer counter on the nanoseconds. More usefully though, we could change this integer to count the number of attoseconds (1e-18 seconds) (or smaller!) and that would still cover 53,914,487,622 centuries.

I'd probably just recommend that the Duration be a counter of zepto seconds (1e-21 seconds) which would still allow the representation of dates for up to 53,914,487 centuries, or roughly 1.7e17 seconds, or a bit more than the age of the Earth (and about 25% of the age of the universe).

This kind of seems like a massive overkill, but it would also greatly simplify the code for Duration, getting rid of the normalize() function all together, and enabling lots of const fn functions. It would extend the list of possible units and frequencies (a functionality I actually never use). I also expect that it would massively speed up the computations of durations because we wouldn't need to normalize any of the durations.

@gwbres , what do you think?

@pwnorbitals, you have a lot of experience in embedded systems: would using a signed 128-bit integer be an issue for supporting some of the platforms you've demonstrated hifitime on? As of March 2024, the Rust compiler has fixed the alignment difference for i128/u128 between Rust and C, if I understand correctly.

The i128 is part of core rust. Soon, I'll try to implement this change and see how it affects performance. Switching to a supported type would simplify a lot of the testing and complexity of the Duration type.

The i128 is part of core rust. Soon, I'll try to implement this change and see how it affects performance. Switching to a supported type would simplify a lot of the testing and complexity of the Duration type.

looking forward to it, keep us updated