|
|
Am 11.08.2021 um 14:57 schrieb William F Pokorny:
> In your preamble, you didn't mention 'now' being used as an SDL timing
> mechanism. It's something people do today and it carries risk with
> respect to any particular timing result. The reasons is we are using the
> system_clock for 'now' which can be updated at any time moving forward
> or backward - synchronization with time servers, etc.
>
> We don't warn against timing use of 'now' in the documentation as far as
> I know. Perhaps we should?
I don't think there's much sense to warn of using `now` in this capacity
in particular.
If people want a rough idea of how long the individual pieces of their
scene take to parse, for example to decide what portions of their scene
to try and optimize, `now` is probably good enough. It's not like system
clocks are typically corrected umpteen times a day, or changed by huge
values.
Also, given that `now` has days as its unit of measure, and the docs
make no promises about its precision other than that it is "seconds or
better", I think that's enough of a warning to not use it for
microseconds precision measurements if anything serious depends on it.
If people want precise performance metrics, anything based on a real
time clock - even `std::chrono::steady_clock` - is a poor choice of tool
anyway. In general, I would guess that the task/thread scheduling jitter
introduces far more noise into the measurements than the occasional
system clock adjustment. CPU time would be a far better candidate for
such things.
Also note that for the purpose of performance metrics, we already
provide measurements of the total parsing time, both real time and CPU time.
If you think we should provide more tools for performance measurements,
I would argue that some `#split_time` directive to print out the current
parser stats would make more sense than some basic building block that
users would have to build additional SDL code around, that in turn would
potentially skew the results, to actually put to use.
But I don't see any dire need for such a feature.
> In povr's f_clock() the up front returned time comes from steady_clock
> instead - which on my Ubuntu 20.04 machine appears to be a monotonic
> clock since the last reboot/boot.
That's what `steady_clock` is for. If it wasn't monotonic, it would
violate the C++ specs.
But being monotonic and steady, it is obviously no good as a building
block for getting the time of day as a string (and conversion to an
absolute date may also be a pain).
> Of note for POV-Ray v3.8 and onward is that the Fn_TimePt00, Fn_TimePt00
> method for capturing time points should work in v3.8 beta 1, but it
> doesn't because when 'now' was added, the support for it was not added
> to parser_strings.cpp alongside pi, tau, etc. This a stand alone 'now'
> issue.
Then that sounds like a bug to me, or at least an issue.
> Putting more of the whole plan/implementation on the table because I see
> secondary 'concerns' such as POV-Ray's Y2K epoch not lining up with any
> unix like system I've ever used - all have been at Jan 1, 1970. This
> makes understanding the values POV-Ray is generating and using harder to
> work with.
This was a deliberate choice, based on various considerations:
* The value was to be exposed to the user, allowing them to assign it to
other variables, as well as perform arithmetics on it (such as adding a
day or an hour before converting to a date/time string, or computing the
number of minutes the parsing took and inserting that value as text in
the image; or computing a value from scratch to be later represented as
a date/time string).
This inevitably meant that the format would have to be based on a
floating-point representation.
This in turn meant that the maximum possible absolute precision would
not be constant, but vary depending on the distance from whatever "zero
point" we would choose. So it would be advantageous to choose a "zero
point" close to the time we live in.
* The value should have a precision of seconds in the worst case, but
higher precision if possible.
* With POV-Ray being a platform-agnostic project at heart, I did not
want to give preference for any existing platform-specific time
representation format - neither POSIX' native seconds-since-1970
timestamp format, nor Windows' native 100ns-intervals-since-1601 format.
The only format I would have considered would have been a format defined
as part of the C/C++ standard. Had I followed that route, I would have
ended up using 1900 as the basis, as that's the only epoch year that had
been explicitly specified by the official C/C++ standard at the time
(see the `std::tm` structure). The POSIX epoch hasn't made it into the
official C/C++ standard until C++20, and even then only for non-C
features for now.
Also remember that back then (2013 or earlier), POSIX time wasn't nearly
as ubiquitous as it is today.
* I did want a format that would be easy for users to understand, and
* I specificially did want a format that would be easily convertible to
POSIX time.
While the latter would seem to clearly speak in favor of POSIX time
itself, in conjunction with the previous point it actually speaks
AGAINST it; here's why:
POSIX time is often cited as being the number of seconds that have
elapsed since 1970-01-01 00:00 UTC.
That is NOT the case.
As a matter of fact, POSIX time is currently about 30 seconds short of
that value.
Instead, POSIX time is the number of _days_ that have elapsed since that
point in time, plus the number of seconds that have elapsed since 00:00
UTC of the current (UTC) day.
(Modulo one or two other minor quirks.)
The difference being that this method does not include leap seconds.
By specifying the format of `now` to give a number of days, rather than
seconds, we're avoiding this subtle difference between what peopole
_think_ POSIX time is, and what it _actually_ is.
(As a minor snag, on days with leap seconds we're actually off by up to
1 second in the value reported, but those days are rare.)
Now with using days instead of seconds for the `now` format, some math
would be required to convert to or from POSIX time anyway; so
introducing a constant offset in addition to the seconds-per-day factor
was anything but a big deal.
Year 2000 made for a far nicer epoch than 1970, or 1961, or even 1900.
And it was closer to "home", meaning we'd have more headroom in terms of
precision for longer time in the future.
(Year 2000 also had the benefit that UTC was already defined in its
current form then. In 1970 it wasn't, so the POSIX time value 0 is
somewhat ambiguous. Not that it matters, as current dates are still
well-defined.)
* Speaking of conversion, If it would turn out that users wanted to
convert to or from POSIX time frequently, enough so that it would
warrant support from our side, the format choisen would have made it
trivial to provide an official include file to define a function or
macro to convert between the two formats. And other then-competing
formats besides.
> Unix commands like date have some nice options:
>
> date --date='TZ="America/Los_Angeles" 09:00 next Mon' +"%s"
>
> but we cannot use the results directly in POV-Ray. Hmm, maybe an
> explicit unix time to y2k seconds type for f_clock...
What's wrong with a simple conversion function?
Why put all the burden on the building block that has the primary job of
getting the current date and time in _some_ format?
That's a difficult enough job as it is. Leave conversion stuff to
separate dedicated functions. It's also a difficult enough job.
There is _no_ reason whatsoever to mix them. Just as there is _no_
reason whatsoever to cram `now` and `datetime` in a single monolithic
function, as the original design would have had it.
> Aside:
> Supposing datetime fixed to support %z %Z, and 'now' returning always a
> no dst utc or local time you can fairly easily adjust the fractional day
> value to account for dst of say an hour with:
>
> #declare DSToffset = (1/24);
Yeah, no.
I'm already working on a solution that is far simpler for the user.
> (1) - The C++/Boost (plus time.h etc) date/time options go on forever. I
> don't begin to understand them all and it looks like c++20 is aiming to
> revamp/extend a lot of it. Coding wise. I tried to stick mostly with c.
Yeah, it makes for fun reading. Especially the parts where you go,
"yeah, you got THIS functionality here, and THAT functionality there,
but all of this doesn't give me THAT THING I REALLY WANT, which should
be far more trivial to implement than THIS and THAT?! And probably just
as common a use case."
Case in point:
There are two functions to convert `std::time_t` to a `std::tm`
structure: One giving you the UTC representation, the other giving you
the local time representation.
There is also a function to convert a `std::tm` in local time
representation to `time_t`.
But where is the **** function that will allow me to populate a
`std::tm` with a UTC representation and convert *THAT* to `time_t`? That
would have to be even easier to implement!
So how else do I get a `time_t` representation of 2000-01-01 00:00 UTC?!
And no, just casting 30 years' worth of seconds to `time_t` is NOT the
proper way to do it folks, because `time_t` is NOT guaranteed to use
POSIX representation. Not even in C++20.
I've now decided that the cleanest way of doing it (in pure C++11
without boost anyway) may be to convert 2000-01-01 00:00 local time to
`time_t`, convert that into UTC, convert that back again to `time_t`
pretending it to be local time, compute the difference to the first
`time_t` obtained, and subtract the result from that first `time_t`.
Behold - 2000-01-01 00:00 UTC as `time_t`. Easy as pi. Or half a tau.
Anyway, irrational. Transcendental even.
Post a reply to this message
|
|