5 ms·
Even if upgraded, its is so flawed that it is practically universally replaced anyways. There are two severe issues which must be addressed for it to be saved.
by midjji 5y ago
Even if upgraded, its is so flawed that it is practically universally replaced anyways.
There are two severe issues which must be addressed for it to be saved. First, the type should be float, not int. The former has an intuitive precision, while the latter does not. Not to mention the sign issues. It is very rare to see a timestamp int which is not used as a kind of fixed point float somewhere in practice, but doing so manually gives rise to endless bugs. float on the other hand, can always be in second, which is much more intuitive, and means the downstream apps fix if precision changes is much easier to get right. For these reasons, upgrading to float64 would be substantially better than upgrading to int64, while being better for most use cases, almost always as fast, and require less thought in downstream.
However, I think we can do even better. Int64 is also too small, as the common nanosecond clocks would only give a century of range, which requires adjusting pretty much every algorithm, even if it only ever deals with a few times. And of course, if I dont care about precession, I want the floating point to deal with it for me.
It almost always makes sense to use a time precision exceeding the most common clock with which it will be used, and with a range covering the most common use cases. Most regular cpus give nanosecond precision, but then float64 would only give a few years of range exactly, which is a bit too short for many applications which want exact precision, and use the standard 1973 start. The long awaited float128 however, would be sufficient for billions of years at pico precision, while maintaining low memory and compute costs. Notably cheaper than int32 was originally. float128 simply makes for a fantastic timestamp format for almost every application. Its extremely convenient compared to the clunky std::chrono, works in C and interop, and is very simple to use.
The only downside is that compiler support, while getting better, remains bad.
- oshiar53-0 5y agoIs there something wrong in particular for using built-in fixed-point types for timestamps? Yes, overflow/underflow issues and yada yada, but virtually every type can be mised in its own way.
- foxfluff 5y agoNothing wrong with fixed point. It's only a problem because people end up hand-rolling their arithmetic (and botching it) instead of using library functions that do it right.
- midjji 5y agoFixedpoint is great, but floating point behave more like how people appear to expect timestamps to work. That said, I like so many others have written my own damned fixed point function for various reasons, and like everyone else I got it wrong several times on the way. If only there was a simple template class that could take care of it for you, but well, such a simple template class would really just be a basic numeric type anyways, so why not include it in the specification, ensuring that a high performance, extremely well tested variant was available everywhere form the start. Imagine how many millions of hours of coder time could have been saved if the C specification included fixedpoint<20,12> (or however you wanna write it), and thus would have created a single standard implementation for all of them. Having not just basic arithmetics, but decent sin, cos, sqrt, atan2 etc, all parth of cmath. The difference now would be minor with soft float beeing ubiquitous, but back when it was faster... Damn.
- eru 5y agoYou could use arbitrary precision rational numbers. Many languages support these in their standard libraries. (Eg Python does.) They are a bit slow compared to ints or floats, but good for precision.
- midjji 5y agoFixed point could work, and they are certainly better than ints, but floating point behaves more like people expect timestamps to work, and the specific fixed-point I need never seems to be available.
- brazzy 5y ago> It is very rare to see a timestamp int which is not used as a kind of fixed point float somewhere in practice Uh... what? I have in fact never seen a timestamp being used that way. What kind of use cases are we talking about? > Int64 is also too small, as the common nanosecond clocks would only give a century of range An unsigned Int64 worth of nanoseconds has a range of over 584 years.
- midjji 5y agoTimestamp ints get constantly casted back and forth between seconds, microseconds, and nano seconds. its an absolute mess everywhere. This are fixed point floats. Everything sensor related, and countless logging, file or anywhere wait_for or timeouts are used are typical usecases, and indirectly whenever people need to do simple things like basic arithmetics on timestamps. The code will either contain some precision change or a unfixed bug related to overflow of one or more kinds. So int64 is half, and I was off by a factor of three doing it in my head... I was wrong no doubt about that. But the order of magnitude is the problem, it should be millenia, or millions of years, not a few centuries.
- yyyk 5y agoWonderful, now we'll have NaN issues, and precision issues where 0.3 can't be truly represented. Did I mention floating point trap, and hard/soft float ABI compatibility? Linux apps like calling gettimeofday() frequently, and now it will be slower, esp. when the processor doesn't do floating point natively. float128 is even worse - it doesn't exist on some ABIs or exist in some other ways, e.g. old Power/PowerPCs used an IBM format. Do we limit them to their own ABI (extra burden on distros), or use double in which case apps expecting 128bits will have quite a surprise.
- midjji 5y agoHow are you going to represent 0.3 using a non fixed point integer? And if you do, use fixed point, you suddenly have other just as common numbers you cant represent. You really think NaN is a better is a less intuitive result than what whatint64(1)/int64(0) gives? You really think the latter wont result in a bug as well? gettimeofday is deprecated as of 2008. So even using it is a bug. Using it more than a few times per seconds is almost certainly a bug. The function also uses an ambiguous representation, but and as the docs dont specify, I would have to check the code to se if it relies on microseconds being less than 10^6, and even if I check this for standard glibc, I would not trust other implementations to do the same. However, as we can assume that the pseudo integer type used does not need to use have multiple codes for basic numbers, its easy to se that the range is just under 52 bits. gettimeofday is so old that they didn't even expect that emulated int64 was available. That is, if they used a double instead, it would perfectly cover the same range, require much less code, while simultaneously been easier to get right, support all standard operations you would expect, behave more intuitively in many cases, and be faster on most platforms, though as you say, perhaps slightly slower on soft float platforms. Though I woudnt be so sure, almost every project notices float performance, almost no project notices gettimeofday performance. The ABI would break by changing the type regardless, numeric types should never be used without explicitly specifying precision, and no, the burden is primarily on compilers. With float128 as a core language feature as it should be, noting that while it should be IEEE... compliant, it may be emulated, the burden on the distros would be small, and likely net beneficial as timestamps is one of those things that cause very rare and hard to replicate bugs absolutely everywhere.
- mlyle 5y agoWhy use floating point for timestamps? In practice, floating point timestamps have a constant precision throughout their life. That is, the exponent has the same value for a really long time, and you don't get any benefit from the "floating" aspect. As another poster points out, overflow/NaN/infinity is the one nice thing you get. But you pick up all the idiosyncrasies of floats, too. As you point out, float64 is worse than int64_t at attaining a given level of precision for a reasonable amount of time. You do point out that floats "seamlessly upgrade" to increased precision, and this is kind of nice. But if we're picking a 128 bit type, there should be no upgrading needed ever. It just doesn't make sense.
- midjji 5y agoBecause in every situation I have ever run into a floating point timestamp behaves more intuitively, and when I started converting my programs to use floating point timestamps almost every function that used timestamps lost dozens of hard to understand special cases that accounted for int overflow, unsignedness, etc problems. Problems which every single one had bit me in the ass at least once before I wrote the code managing the special case, and of which nearly every single one had at least one bug in it. See the revisions to std::midpoint for great examples of how hard this is to do right. However, because float128 overrepresents all the older basic type variants, it becomes trivial. If the code could possibly have been made to work for any of them, it will automatically always work for float128. Its got more to do with how intuitively the timestamp behaves, and that you can use seconds as the unit everywhere and no longer need to keep track of if this wait function took seconds or milliseconds. Using infty to indicate a timeout function should block indefinetly is also much more intuitive than using 0.