# Module Time_stamp_counter

    module Time_stamp_counter: sig .. end

High-performance timing.

This module provides the fast function `now ()` which is our best effort high-performance cycle counter for a given platform. For x86 systems this retrieves the CPU's internal time stamp counter using the RDTSC instruction. For systems that do not have a RDTSC instruction, we fallback to using `clock_gettime(CLOCK_MONOTONIC)`.

Here is a benchmark of execution time in nanos and allocations in words:

          Name                         Time/Run   mWd/Run
         ---------------------------- ---------- ---------
          Time.now                      37.93ns     2.00w
          Time_ns.now                   28.18ns
          TSC.Calibrator.calibrate     115.43ns    28.00w
          TSC.now                        7.14ns
          TSC.to_time                    3.44ns     2.00w
          TSC.to_time (TSC.now ())       8.24ns     2.00w
          TSC.to_time_ns                14.20ns
          TSC.to_time_ns(TSC.now ())     9.80ns
          id                             2.91ns
          TSC.Span.of_ns                 5.81ns
          TSC.Span.to_ns                 3.70ns

Type `t` is an `Int63.t` and consequently has no allocation overhead (on 64-bit machines), unlike `Time.now ()` which returns a boxed float.

Functions are also provided to estimate the relationship of CPU time-stamp-counter frequency to real time, thereby allowing one to convert from `t` to `Time.t`. There are some caveats to this that are worth noting:

- The conversion to `Time.t` depends on an estimate of the time-stamp-counter frequency. This frequency may be volatile on some systems, thereby reducing the utility of this conversion. See the `Calibrator` module below for details.

- The captured `t` can only be converted to a `Time.t` if one also has a recently calibrated `Calibrator.t` from the same machine.

See also: http://en.wikipedia.org/wiki/Time_Stamp_Counter

    type t = private Core_kernel.Std.Int63.t

    module Calibrator: sig .. end

A calibrator contains a snapshot of machine-specific information that is used to convert between TSC values and clock time.

    module Span: sig .. end

`Span` indicates some integer number of cycles.

    val now : unit -> t

    val diff : t -> t -> Span.t

    val add : t -> Span.t -> t

    val to_int63 : t -> Core_kernel.Std.Int63.t

`to_int63 t` returns the TSC value represented by `t` as an `Int63.t`.

    val to_time : ?calibrator:Calibrator.t -> t -> Time.t

`to_time t` converts a `t` to a `Time.t`. It is guaranteed that repeated calls of `to_time ()` will return nondecreasing `Time.t` values.

    val to_time_ns : ?calibrator:Calibrator.t ->
           t -> Core_kernel.Std.Time_ns.t

`to_time_ns t` converts a `t` to an integer number of nanos since the epoch.

    val t_of_sexp : Sexplib.Sexp.t -> t

    val sexp_of_t : t -> Sexplib.Sexp.t

    val compare : t -> t -> int

    val bin_t : t Core_kernel.Std.Bin_prot.Type_class.t

    val bin_read_t : t Core_kernel.Std.Bin_prot.Read.reader

    val __bin_read_t__ : (int -> t) Core_kernel.Std.Bin_prot.Read.reader

    val bin_reader_t : t Core_kernel.Std.Bin_prot.Type_class.reader

    val bin_size_t : t Core_kernel.Std.Bin_prot.Size.sizer

    val bin_write_t : t Core_kernel.Std.Bin_prot.Write.writer

    val bin_writer_t : t Core_kernel.Std.Bin_prot.Type_class.writer

A calibrator contains a snapshot of machine-specific information that is used to convert between TSC values and clock time. This information needs to be calibrated periodically such that it stays updated w.r.t. changes in the CPU's time-stamp-counter frequency, which can vary depending on load, heat etc. (Also see the comment in the `.ml` file)

Calibration at the rate of 0.1, 1 or 2 secs produces errors (measured as the difference between `Time.now` and the reported time here) on the order of 1-2us. Given the precision of 52bit float mantissa values, this is very close to least error one can have on these values. Calibration once per 10sec produces errors that are +/-4us. Calibration once per minute produces errors that are +/-15us and calibration once in 3mins produces errors +/-30us. (It is worth remarking that the error has a positive bias of 1us -- i.e. the error dances around the 1us mark, rather than around 0. It is unclear where this bias is introduced, though it probably does not matter for most applications.)

This module maintains an instance of `t` internal to the module. The internal instance of `t` can be updated via calls to `calibrate ()`, i.e. without specifying the `t` parameter. In all the functions below that take an optional `Calibrator.t` argument, the internal instance is used when no calibrator is explicitly specified.
`create ()` creates an uninitialized calibrator instance. Creating a calibrator takes about 3ms. One needs a recently calibrated `Calibrator.t` and the TSC value from the same machine to meaningfully convert the TSC value to a `Time.t`.
`calibrate ~t` updates `t` by measuring the current value of the TSC and `Time.now`.
Returns the estimated MHz of the CPU's time-stamp-counter based on the TSC and `Time.now ()`. This function is undefined on 32bit machines.
`Span` indicates some integer number of cycles.
`to_int63 t` returns the TSC value represented by `t` as an `Int63.t`.
`to_time t` converts a `t` to a `Time.t`. It is guaranteed that repeated calls of `to_time ()` will return nondecreasing `Time.t` values.
`to_time_ns t` converts a `t` to an integer number of nanos since the epoch.