12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697(******************************************************************************)(* *)(* Monolith *)(* *)(* François Pottier *)(* *)(* Copyright Inria. All rights reserved. This file is distributed under the *)(* terms of the GNU Lesser General Public License as published by the Free *)(* Software Foundation, either version 3 of the License, or (at your *)(* option) any later version, as described in the file LICENSE. *)(* *)(******************************************************************************)typeclock={(* Our granularity. This is the number of ticks that we let go until we
check what we have to do. A tick that is a multiple of [granularity] is
said to be round. *)granularity:int;(* Our start time. *)start:float;(* An optional timeout. *)timeout:floatoption;(* The current time. *)mutablenow:float;(* The number of ticks that have taken place. *)mutableticks:int;(* The last time a user function [f] was called via [tick clock f]. *)mutablelast:float;(* A circular array of the times at which the most recent round ticks
took place. *)window:floatarray;(* An index into the circular window. *)mutablenext:int;}letmake?timeoutgranularity=letstart=Unix.gettimeofday()inletn=10(* window size *)inletclock={granularity;start;now=start;ticks=0;last=0.;timeout;window=Array.makenstart;next=0;}inclockexceptionTimeoutletcheck_timeoutclock=matchclock.timeoutwith|None->()|Sometimeout->ifclock.now-.clock.start>timeoutthenraiseTimeoutlettick_bodyclockf=(* A round tick. Record the current time. *)clock.now<-Unix.gettimeofday();(* Update the window. *)clock.window.(clock.next)<-clock.now;letn=Array.lengthclock.windowinclock.next<-(clock.next+1)modn;(* Check if roughly one new second has elapsed. If so, call the user
function [f]. *)ifclock.now>clock.last+.1.0thenbeginclock.last<-clock.now;f()end;(* Check whether the clock's time limit has been reached. *)check_timeoutclocklet[@inline]tickclockf=(* Count one tick. *)clock.ticks<-clock.ticks+1;(* If [granularity] ticks have been counted, perform more expensive work. *)ifclock.ticksmodclock.granularity=0thentick_bodyclockfletticksclock=clock.ticksletelapsed_timeclock=truncate(clock.now-.clock.start)letoverall_ticks_per_secondclock=truncate(float_of_intclock.ticks/.(clock.now-.clock.start))letcurrent_ticks_per_secondclock=letn=Array.lengthclock.windowinletoldest=clock.window.(clock.next)andnewest=clock.nowintruncate(float_of_int(clock.granularity*n)/.(newest-.oldest))