#!/bin/bash
# core/timer - Duration Measuring Support
set -e
lib_load 'sys/tool/bc'
######
# Timer Value
# timer_now() - Prints the current time with nanoseconds.
timer_now() { date '+%s.%N'; }
######
# Timer Variables
# timer_var_running() - Prints name of variable that stores a boolean
# value indicating the running state of the given timer ($1).
timer_var_running() { echo "$1"; }
# timer_var_start() - Prints name of variable that stores the starting
# time of the given timer ($1).
timer_var_start() { echo "${1}_start"; }
# timer_var_final() - Prints name of variable that stores the final
# time of the given timer ($1).
timer_var_final() { echo "${1}_final"; }
# timer_var_marks() - Prints name of an array variable that stores
# marks for the given timer ($1).
timer_var_marks() { echo "${1}_marks"; }
######
# Timer Mark Interface
#
# A `timer mark` is defined as the time an event occurred while the
# timer is running. This interface does not enforce any policy
# regarding the frequency, number, values, or ordering of marks.
# They simply must be valid time values formatted in the same manner as
# output by ``timer_now()``. Their meaning is left to the user.
# timer_mark() - Saves a new mark ($2) for the given timer ($1).
# $1 - Name of timer.
# $2 - Mark time. If `null`, obtains the current `Timer Value`_.
timer_mark() {
min_max_args 1 2 "$@"
local var when
var=$(timer_var_marks "$1")
when=${2:-$(timer_now)}
[ "$when" ] || error "timer $1: unable to set mark"
eval "$var+=( $when )"
}
# timer_mark_all() - Prints the list of marks for the given timer ($1).
# $1 - Name of timer.
timer_mark_all() {
has_args 1 "$@"
local marksvar=$(timer_var_marks "$1")
eval "echo \"\${${marksvar}[*]}\""
}
# timer_mark_count() - Prints the number of marks for the given timer ($1).
# $1 - Name of timer.
timer_mark_count() {
has_args 1 "$@"
local marksvar
marksvar=$(timer_var_marks "$1")
eval "echo \$((\${#$marksvar[*]}))"
}
# timer_mark_first() - Prints the first mark for the given timer ($1).
# $1 - Name of timer.
timer_mark_first() {
has_args 1 "$@"
local marksvar
marksvar=$(timer_var_marks "$1")
eval "echo \"\$$marksvar\""
}
# timer_mark_get() - Prints the mark at the given index ($2) for the
# given timer ($1).
# $1 - Name of timer.
# $2 - Index into mark array.
timer_mark_get() {
has_args 2 "$@"
local marksvar
marksvar=$(timer_var_marks "$1")
eval "echo \"\${${marksvar}[$2]}\""
}
# timer_mark_measure() - Computes and prints the difference between
# two marks ($2 and $3) for the given timer ($1).
# $1 - Name of timer.
# $2 - First index into timer mark array.
# $3 - Second index into timer mark array.
timer_mark_measure() {
has_args 3 "$@"
local name=$1
local idxstart=$2
local idxfinal=$3
local count
count=$(timer_mark_count "$name")
if ! [ $idxstart -lt $count -a $idxfinal -lt $count ]; then
local msg="cannot measure from $idxstart to $idxfinal"
error "timer $name: $msg with $count marks"
fi
local start final elapsed
start=$(timer_mark_get $name $idxstart)
final=$(timer_mark_get $name $idxfinal)
bc_gen_sub $final $start | bc_run
}
######
# Timer Lap Interface
#
# A `timer lap` is defined as the elapsed interval between two succesive
# timer marks. Thus, `n` saved marks will calculate `n - 1` lap intervals.
# timer_laps() - Prints the number of extant laps for the given timer ($1).
# $1 - Name of timer.
timer_laps() {
has_args 1 "$@"
local count
count=$(timer_mark_count "$1")
if [ $count -gt 1 ]; then
echo $((count - 1))
else
echo 0
fi
}
# timer_has_laps() - Checks the number of extant laps for the given timer ($1).
# $1 - Name of timer.
# Returns: Succcess if the timer has recorded at least one lap.
timer_has_laps() {
has_args 1 "$@"
local laps=$(timer_laps "$1")
[ $laps -gt 0 ]
}
# timer_lap_measure() - Prints the elapsed time between two marks ($2
# and $3) for the given timer ($1).
# $1 - Name of timer.
# $2 - First index into timer mark array.
# $3 - Second index into timer mark array.
timer_lap_measure() {
has_args 3 "$@"
local name=$1
if ! timer_has_laps "$name"; then
warn "timer: $name: no laps recorded"
return
fi
timer_mark_measure "$2" "$3"
}
# timer_lap_measure() - Prints the last lap interval for the given timer ($1).
# $1 - Name of timer
timer_lap_last() {
has_args 1 "$@"
timer_lap_measure "$1" -2 -1
}
######
# Timer Query
# timer_is_exists() - Checks to see if the given timer ($1) exists.
# $1 - Name of timer
# Returns: Success if the timer exists.
timer_exists() {
local -n running=$(timer_var_running "$1")
[ "$running" ]
}
# timer_is_running() - Checks to see if the given timer ($1) is running.
# $1 - Name of timer
# Returns: Success if the timer is running.
timer_is_running() {
has_args 1 "$@"
local -n running=$(timer_var_running "$1")
[ "$running" ] && $running
}
# timer_running() - Sets the running state ($2) for the given timer ($1).
# $1 - Name of timer
# $2 - New running state (``true`` or ``false``)
timer_running() {
local -n running=$(timer_var_running "$1")
running=$2
}
######
# Timer Control
# timer_start() - Stops the given timer ($1)
# $1 - Name of timer
timer_start() {
has_args 1 "$@"
local name=$1
if timer_is_running "$name"; then
warn "$name: timer already running"
return
fi
timer_running true
local -n start=$(timer_var_start "$name")
start=$(timer_now)
timer_mark $name $start
}
# timer_stop() - Stops the given timer ($1)
# $1 - Name of timer
timer_stop() {
has_args 1 "$@"
local name=$1
local -n final=$(timer_var_final "$name")
final=$(timer_now)
timer_mark $name $final
timer_running false
}
######
# Timer Reporting
# timer_elapsed() - Prints a human readable version of the elapsed time
# for the given timer ($1).
# $1 - Name of timer
timer_elapsed() {
local elapsed
elapsed=$(timer_elapsed_seconds "$@")
local sec=${elapsed%.*}
local nsec=${elapsed#*.}
local hrs=$((sec / 3600))
[ $hrs -gt 0 ] && echo "$hrs hours" || hrs=''
secs=$((secs % 3600))
local min=$((sec / 60))
[ "$hrs" -o $min -gt 0 ] && echo "${hrs:+, }$min minutes" || min=''
sec=$((sec % 60))
echo "${min:+, }$sec.$nsec seconds"
}
# timer_elapsed_seconds() - Prints the total number of elapsed seconds
# with nanosecond resolution.
# $1 - Name of timer
timer_elapsed_seconds() {
has_args 1 "$@"
echo "$(timer_mark_measure "$1" 0 -1)"
}
Generated on Fri Jul 28 14:35:06 PDT 2017 by mcsh d14 v0.23.0.