package core_unix

  1. Overview
  2. Docs
Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source

Module Time_stamp_counterSource

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                      27.99ns     2.00w
  Time_ns.now                   25.21ns
  TSC.Calibrator.calibrate      68.61ns
  TSC.now                        6.87ns
  TSC.to_time                    4.30ns     2.00w
  TSC.to_time (TSC.now ())       8.75ns     2.00w
  TSC.to_time_ns                 4.70ns
  TSC.to_time_ns(TSC.now ())     9.56ns
  id                             2.86ns
  TSC.Span.of_ns                11.66ns
  TSC.Span.to_ns                 3.84ns

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.
  • Put another way, it would not make sense to send a sexp of t from one box to another and then convert it to a Time.t, because t counts the number of cycles since reset. So the measure only makes sense in the context of a single machine.
  • Note that a cursory search for information about time stamp counter usage may give a false impression of its unreliability. Early processor implementations of TSC could be skewed by clock frequency changes (C-states) and by small differences between the startup time of each processor on a multi-processor machine. Modern hardware can usually be assumed to have an "invariant" tsc, and Linux has support to synchronize the initial counters at boot time when multiple processors are present.

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

Sourcetype t = private Core.Int63.t
include Core.Bin_prot.Binable.S with type t := t
include Bin_prot.Binable.S_only_functions with type t := t
Sourceval bin_size_t : t Bin_prot.Size.sizer
Sourceval bin_write_t : t Bin_prot.Write.writer
Sourceval bin_read_t : t Bin_prot.Read.reader
Sourceval __bin_read_t__ : (int -> t) Bin_prot.Read.reader

This function only needs implementation if t exposed to be a polymorphic variant. Despite what the type reads, this does *not* produce a function after reading; instead it takes the constructor tag (int) before reading and reads the rest of the variant t afterwards.

Sourceval bin_shape_t : Bin_prot.Shape.t
include Ppx_compare_lib.Comparable.S with type t := t
include Sexplib0.Sexpable.S with type t := t
Sourceval t_of_sexp : Sexplib0.Sexp.t -> t
Sourceval sexp_of_t : t -> Sexplib0.Sexp.t
include Core.Comparisons.S with type t := t
include Base.Comparisons.Infix with type t := t
val (>=) : t -> t -> bool
val (<=) : t -> t -> bool
val (=) : t -> t -> bool
val (>) : t -> t -> bool
val (<) : t -> t -> bool
val (<>) : t -> t -> bool
val equal : t -> t -> bool
val compare : t -> t -> int

compare t1 t2 returns 0 if t1 is equal to t2, a negative integer if t1 is less than t2, and a positive integer if t1 is greater than t2.

val min : t -> t -> t
val max : t -> t -> t
Sourcemodule Calibrator : sig ... end

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.)

Sourcemodule Span : sig ... end

Span indicates some integer number of cycles.

Sourceval now : unit -> t
Sourceval diff : t -> t -> Span.t
Sourceval add : t -> Span.t -> t
Sourceval to_int63 : t -> Core.Int63.t
Sourceval zero : t

A default calibrator for the current process. Most programs can just use this calibrator; use others if collecting data from other processes / machines.

The first time this lazy value is forced, it spends approximately 3ms calibrating.

While the Async scheduler is running, this value is recalibrated regularly. IF NOT USING THE ASYNC SCHEDULER, you must have some other means of making sure recalibration occurs.

Sourceval to_time : t -> calibrator:Calibrator.t -> Core.Time_float.t

It is guaranteed that repeated calls will return nondecreasing Time.t values.

Sourceval to_time_ns : t -> calibrator:Calibrator.t -> Core.Time_ns.t