|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [MirageOS-devel] Timestamp representation and CLOCK
Justin's point that would you store a large number of timestamps you'd anyway
devise your own representation achieved to convince me that using int64 * int
as initially proposed seemed to be the right representation to me: it has ample
range, nanosecond precision and we would not invent anything new.
However while trying to implement this representation in ptime I realized that
addition is more tricky that needed because the nanosecond count can overflow
on 32-bit platforms. While it does overflow in a magnitude that makes it still
usable to perform the carry on addition â e.g. trying to add two [ns0] and
[ns1] ranging from 0 to 999_999_999 in 32-bit yields the following on overflow:
1e9 max_int][min_int (ns0+ns1) 0
... ----+---------------++--------------+------------+-- ...
[-------------------------------]
(ns0+ns1) mod 1e9
I still find the resulting representation to be too tricky for OCaml
programming. Here is how addition needs to be implemented:
let add (s0, ns0) (s1, ns1) =
let s = Int64.add s0 s1 in
let ns = ns0 + ns1 in
if ns < 0 then (* 32-bit overflow *)
Int64.(add s 1L), max_int - 1_000_000_000 + 1 + (ns - min_int)
else if ns < 1_000_000_000 then
s, ns
else (* ns > 1_000_000_000 *)
Int64.(add s 1L), ns mod 1_000_000_000
So I propose to use the following representation. Namely a signed count of days
from the epoch and a pico precision timestamp in that day (another form of
date-time value in some sense). So this is:
type posix_t = int * int64
with (d, ps) representing the point in time [d] * 86'400e12 + [ps] picoseconds
from the epoch. [ps] in the range [0;86_399_999_999_999_999]. Incidentally this
is the representation I would use internally for a calendar library as it
conceptually similar the handy Julian Date "calendar" [1] in which a lot of
calendar calculations become easier to perform.
This has the same properties as my previous proposal except that we are
inventing something (mildly) new, make better precision trade-off (the size of
the range of days representable around the epoch is entirely sufficient,
5'883'516 years on 32-bit platforms) and the representation is easier to use on
both 32-bit and 64-bit platforms. Here's how 32-bit clean addition gets
implemented:
let add (d0, ns0) (d1, ns1) =
let d = d0 + d1 in
let ns = Int64.add ns0 ns1 in
let ns_clamp = Int64.rem ns 86_400_000_000_000_000L in
let d = d + Int64.compare ns ns_clamp in
d, ns_clamp
Having this and adding a function for accessing the clock period which was
suggested by DavidS and Justin, this would bring us to the following CLOCK:
module type CLOCK = sig
val now_d_ps : unit -> int * int64
(** [now_d_ps ()] is [(d, ps)] representing the time occuring at
[d] * 86'400e12 + [ps] picoseconds from the epoch 1970-01-01
00:00:00 UTC. [ps] is in the range \[[0];[86_399_999_999_999_999L]\]. *)
val period_d_ps : unit -> (int * int64) option
(** [period_d_ps ()] is if available [Some (d, ps)] representing the
clock's picosecond period [d] * 86'400e12 + [ps]. [ps] is in the
range \[[0];[86_399_999_999_999_999L]\]. *)
val current_tz_offset_s : unit -> int
(** [current_tz_offset_s ()] is the clock's current local time zone
offset to UTC in seconds. *)
end
So what do people think of this ?
Daniel
P.S. Also note that on 64-bit platforms this could actually be represented by
an int pair, as the calculations for pico seconds would fit in the 2^62-1 bits.
[1] http://scienceworld.wolfram.com/astronomy/JulianDate.html
_______________________________________________
MirageOS-devel mailing list
MirageOS-devel@xxxxxxxxxxxxxxxxxxxx
http://lists.xenproject.org/cgi-bin/mailman/listinfo/mirageos-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |