time: Timer -> StopWatch; time.Duration
parent
f3e3d7e0c5
commit
25f2b171fc
|
@ -54,8 +54,8 @@ const (
|
||||||
|
|
||||||
pub struct Benchmark {
|
pub struct Benchmark {
|
||||||
pub mut:
|
pub mut:
|
||||||
bench_timer time.Timer
|
bench_timer time.StopWatch
|
||||||
step_timer time.Timer
|
step_timer time.StopWatch
|
||||||
ntotal int
|
ntotal int
|
||||||
nok int
|
nok int
|
||||||
nfail int
|
nfail int
|
||||||
|
@ -70,14 +70,14 @@ pub mut:
|
||||||
|
|
||||||
pub fn new_benchmark() Benchmark {
|
pub fn new_benchmark() Benchmark {
|
||||||
return Benchmark{
|
return Benchmark{
|
||||||
bench_timer: time.new_timer()
|
bench_timer: time.new_stopwatch()
|
||||||
verbose: true
|
verbose: true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_benchmark_no_cstep() Benchmark {
|
pub fn new_benchmark_no_cstep() Benchmark {
|
||||||
return Benchmark{
|
return Benchmark{
|
||||||
bench_timer: time.new_timer()
|
bench_timer: time.new_stopwatch()
|
||||||
verbose: true
|
verbose: true
|
||||||
no_cstep: true
|
no_cstep: true
|
||||||
}
|
}
|
||||||
|
@ -85,7 +85,7 @@ pub fn new_benchmark_no_cstep() Benchmark {
|
||||||
|
|
||||||
pub fn new_benchmark_pointer() &Benchmark {
|
pub fn new_benchmark_pointer() &Benchmark {
|
||||||
return &Benchmark{
|
return &Benchmark{
|
||||||
bench_timer: time.new_timer()
|
bench_timer: time.new_stopwatch()
|
||||||
verbose: true
|
verbose: true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -147,7 +147,7 @@ pub fn start() Benchmark {
|
||||||
|
|
||||||
pub fn (b mut Benchmark) measure(label string) i64 {
|
pub fn (b mut Benchmark) measure(label string) i64 {
|
||||||
b.ok()
|
b.ok()
|
||||||
res := b.step_timer.elapsed()
|
res := b.step_timer.elapsed().milliseconds()
|
||||||
println(b.step_message_with_label(BSPENT, 'in $label'))
|
println(b.step_message_with_label(BSPENT, 'in $label'))
|
||||||
b.step()
|
b.step()
|
||||||
return res
|
return res
|
||||||
|
@ -172,10 +172,10 @@ pub fn (b &Benchmark) step_message_with_label(label string, msg string) string {
|
||||||
'${b.cstep:3d}/${b.nexpected_steps:3d}'
|
'${b.cstep:3d}/${b.nexpected_steps:3d}'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
timed_line = b.tdiff_in_ms('[${sprogress}] $msg', b.step_timer.elapsed())
|
timed_line = b.tdiff_in_ms('[${sprogress}] $msg', b.step_timer.elapsed().milliseconds())
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
timed_line = b.tdiff_in_ms(msg, b.step_timer.elapsed())
|
timed_line = b.tdiff_in_ms(msg, b.step_timer.elapsed().milliseconds())
|
||||||
}
|
}
|
||||||
return '${label:-5s}${timed_line}'
|
return '${label:-5s}${timed_line}'
|
||||||
}
|
}
|
||||||
|
@ -201,11 +201,11 @@ pub fn (b &Benchmark) total_message(msg string) string {
|
||||||
if b.verbose {
|
if b.verbose {
|
||||||
tmsg = '<=== total time spent $tmsg'
|
tmsg = '<=== total time spent $tmsg'
|
||||||
}
|
}
|
||||||
return ' ' + b.tdiff_in_ms(tmsg, b.bench_timer.elapsed())
|
return ' ' + b.tdiff_in_ms(tmsg, b.bench_timer.elapsed().milliseconds())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (b &Benchmark) total_duration() i64 {
|
pub fn (b &Benchmark) total_duration() i64 {
|
||||||
return b.bench_timer.elapsed()
|
return b.bench_timer.elapsed().milliseconds()
|
||||||
}
|
}
|
||||||
|
|
||||||
// //////////////////////////////////////////////////////////////////
|
// //////////////////////////////////////////////////////////////////
|
||||||
|
|
|
@ -0,0 +1,52 @@
|
||||||
|
// Copyright (c) 2019-2020 Alexander Medvednikov. All rights reserved.
|
||||||
|
// Use of this source code is governed by an MIT license
|
||||||
|
// that can be found in the LICENSE file.
|
||||||
|
module time
|
||||||
|
|
||||||
|
pub struct StopWatch {
|
||||||
|
pause_time u64
|
||||||
|
pub:
|
||||||
|
start u64
|
||||||
|
end u64
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new_stopwatch() StopWatch {
|
||||||
|
return StopWatch{start: time.sys_mono_now()}
|
||||||
|
}
|
||||||
|
|
||||||
|
// start Starts the timer. If the timer was paused, restarts counting.
|
||||||
|
pub fn (t mut StopWatch) start() {
|
||||||
|
if t.pause_time == 0 {
|
||||||
|
t.start = time.sys_mono_now()
|
||||||
|
} else {
|
||||||
|
t.start += time.sys_mono_now() - t.pause_time
|
||||||
|
}
|
||||||
|
t.end = 0
|
||||||
|
t.pause_time = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn (t mut StopWatch) restart() {
|
||||||
|
t.end = 0
|
||||||
|
t.pause_time = 0
|
||||||
|
t.start = time.sys_mono_now()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn (t mut StopWatch) stop() {
|
||||||
|
t.end = time.sys_mono_now()
|
||||||
|
t.pause_time = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn (t mut StopWatch) pause() {
|
||||||
|
t.pause_time = time.sys_mono_now()
|
||||||
|
t.end = t.pause_time // so elapsed keeps track of actual running time
|
||||||
|
}
|
||||||
|
|
||||||
|
// elapsed returns the Duration since the last start call
|
||||||
|
pub fn (t StopWatch) elapsed() Duration {
|
||||||
|
if t.end == 0 {
|
||||||
|
return Duration(time.sys_mono_now() - t.start)
|
||||||
|
} else {
|
||||||
|
return Duration(t.end - t.start)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -20,7 +20,21 @@ const (
|
||||||
days_per_400_years = 365 * 400 + 97
|
days_per_400_years = 365 * 400 + 97
|
||||||
days_per_100_years = 365 * 100 + 24
|
days_per_100_years = 365 * 100 + 24
|
||||||
days_per_4_years = 365 * 4 + 1
|
days_per_4_years = 365 * 4 + 1
|
||||||
days_before = [0, 31, 31 + 28, 31 + 28 + 31, 31 + 28 + 31 + 30, 31 + 28 + 31 + 30 + 31, 31 + 28 + 31 + 30 + 31 + 30, 31 + 28 + 31 + 30 + 31 + 30 + 31, 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31, 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30, 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31, 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30, 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30 + 31, ]
|
days_before = [
|
||||||
|
0,
|
||||||
|
31,
|
||||||
|
31 + 28,
|
||||||
|
31 + 28 + 31,
|
||||||
|
31 + 28 + 31 + 30,
|
||||||
|
31 + 28 + 31 + 30 + 31,
|
||||||
|
31 + 28 + 31 + 30 + 31 + 30,
|
||||||
|
31 + 28 + 31 + 30 + 31 + 30 + 31,
|
||||||
|
31 + 28 + 31 + 30 + 31 + 30 + 31 + 31,
|
||||||
|
31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30,
|
||||||
|
31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31,
|
||||||
|
31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30,
|
||||||
|
31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30 + 31,
|
||||||
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
pub struct Time {
|
pub struct Time {
|
||||||
|
@ -121,7 +135,7 @@ pub fn (t Time) unix_time() int {
|
||||||
return make_unix_time(tt)
|
return make_unix_time(tt)
|
||||||
}
|
}
|
||||||
|
|
||||||
// add_days returns a new time struct with an added number of seconds.
|
// add_seconds returns a new time struct with an added number of seconds.
|
||||||
pub fn (t Time) add_seconds(seconds int) Time {
|
pub fn (t Time) add_seconds(seconds int) Time {
|
||||||
// TODO Add(d time.Duration)
|
// TODO Add(d time.Duration)
|
||||||
return unix(t.unix + seconds)
|
return unix(t.unix + seconds)
|
||||||
|
@ -265,3 +279,48 @@ fn convert_ctime(t C.tm) Time {
|
||||||
unix: make_unix_time(t)
|
unix: make_unix_time(t)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// A lot of these are taken from the Go library
|
||||||
|
pub type Duration i64
|
||||||
|
|
||||||
|
pub const(
|
||||||
|
nanosecond = Duration(1)
|
||||||
|
microsecond = Duration(1000) * nanosecond
|
||||||
|
millisecond = Duration(1000) * microsecond
|
||||||
|
second = Duration(1000) * millisecond
|
||||||
|
minute = Duration(60) * second
|
||||||
|
hour = Duration(60) * minute
|
||||||
|
)
|
||||||
|
|
||||||
|
// nanoseconds returns the duration as an integer number of nanoseconds.
|
||||||
|
pub fn (d Duration) nanoseconds() i64 { return i64(d) }
|
||||||
|
|
||||||
|
// microseconds returns the duration as an integer number of microseconds.
|
||||||
|
pub fn (d Duration) microseconds() i64 { return i64(d) / 1000 }
|
||||||
|
|
||||||
|
// milliseconds returns the duration as an integer number of milliseconds.
|
||||||
|
pub fn (d Duration) milliseconds() i64 { return i64(d) / 1_000_000 }
|
||||||
|
|
||||||
|
// The following functions return floating point numbers because it's common to
|
||||||
|
// consider all of them in sub-one intervals
|
||||||
|
|
||||||
|
// seconds returns the duration as a floating point number of seconds.
|
||||||
|
pub fn (d Duration) seconds() f64 {
|
||||||
|
sec := d / second
|
||||||
|
nsec := d % second
|
||||||
|
return f64(sec) + f64(nsec)/1e9
|
||||||
|
}
|
||||||
|
|
||||||
|
// minutes returns the duration as a floating point number of minutes.
|
||||||
|
pub fn (d Duration) minutes() f64 {
|
||||||
|
min := d / minute
|
||||||
|
nsec := d % minute
|
||||||
|
return f64(min) + f64(nsec)/(60*1e9)
|
||||||
|
}
|
||||||
|
|
||||||
|
// hours returns the duration as a floating point number of hours.
|
||||||
|
pub fn (d Duration) hours() f64 {
|
||||||
|
hr := d / hour
|
||||||
|
nsec := d % hour
|
||||||
|
return f64(hr) + f64(nsec)/(60*60*1e9)
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,40 @@
|
||||||
|
module time
|
||||||
|
|
||||||
|
#include <mach/mach_time.h>
|
||||||
|
|
||||||
|
const (
|
||||||
|
// start_time is needed on Darwin and Windows because of potential overflows
|
||||||
|
start_time = C.mach_absolute_time()
|
||||||
|
time_base = init_time_base()
|
||||||
|
)
|
||||||
|
|
||||||
|
[typedef]
|
||||||
|
struct C.mach_timebase_info_data_t {
|
||||||
|
numer u64
|
||||||
|
denom u64
|
||||||
|
}
|
||||||
|
|
||||||
|
fn C.mach_absolute_time() u64
|
||||||
|
fn C.mach_timebase_info(&C.mach_timebase_info_data_t)
|
||||||
|
|
||||||
|
struct InternalTimeBase {
|
||||||
|
numer u64
|
||||||
|
denom u64
|
||||||
|
}
|
||||||
|
|
||||||
|
fn init_time_base() InternalTimeBase {
|
||||||
|
mut tb := C.mach_timebase_info_data_t{}
|
||||||
|
C.mach_timebase_info(&tb)
|
||||||
|
return InternalTimeBase{numer:tb.numer, denom:tb.denom}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn sys_mono_now_darwin() u64 {
|
||||||
|
tm := C.mach_absolute_time()
|
||||||
|
return mul_div(tm - start_time, time_base.numer, time_base.denom)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn mul_div(val, numer, denom u64) u64 {
|
||||||
|
q := val / denom
|
||||||
|
r := val % denom
|
||||||
|
return q * numer + r * numer / denom
|
||||||
|
}
|
|
@ -17,3 +17,25 @@ fn C.timegm(&tm) time_t
|
||||||
fn make_unix_time(t C.tm) int {
|
fn make_unix_time(t C.tm) int {
|
||||||
return int(C.timegm(&t))
|
return int(C.timegm(&t))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type time_t voidptr
|
||||||
|
|
||||||
|
// in most systems, these are __quad_t, which is an i64
|
||||||
|
struct C.timespec {
|
||||||
|
tv_sec i64
|
||||||
|
tv_nsec i64
|
||||||
|
}
|
||||||
|
|
||||||
|
// the first arg is defined in include/bits/types.h as `__S32_TYPE`, which is `int`
|
||||||
|
fn C.clock_gettime(int, &C.timespec)
|
||||||
|
|
||||||
|
fn sys_mono_now() u64 {
|
||||||
|
$if macos {
|
||||||
|
return sys_mono_now_darwin()
|
||||||
|
} $else {
|
||||||
|
ts := C.timespec{}
|
||||||
|
C.clock_gettime(C.CLOCK_MONOTONIC, &ts)
|
||||||
|
return u64(ts.tv_sec) * 1_000_000_000 + u64(ts.tv_nsec)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,8 +12,48 @@ struct C.tm {
|
||||||
tm_sec int
|
tm_sec int
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[typedef]
|
||||||
|
struct C.LARGE_INTEGER {
|
||||||
|
QuadPart i64
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
// start_time is needed on Darwin and Windows because of potential overflows
|
||||||
|
// Windows: don't store the LARGE_INTEGER, just the QuadPart
|
||||||
|
start_time = init_win_time_start()
|
||||||
|
freq_time = init_win_time_freq()
|
||||||
|
)
|
||||||
|
|
||||||
fn C._mkgmtime(&C.tm) time_t
|
fn C._mkgmtime(&C.tm) time_t
|
||||||
|
|
||||||
|
fn C.QueryPerformanceCounter(&C.LARGE_INTEGER) C.BOOL
|
||||||
|
|
||||||
|
fn C.QueryPerformanceFrequency(&C.LARGE_INTEGER) C.BOOL
|
||||||
|
|
||||||
fn make_unix_time(t C.tm) int {
|
fn make_unix_time(t C.tm) int {
|
||||||
return int(C._mkgmtime(&t))
|
return int(C._mkgmtime(&t))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn init_win_time_freq() u64 {
|
||||||
|
mut f := C.LARGE_INTEGER{}
|
||||||
|
_ := C.QueryPerformanceFrequency(&f)
|
||||||
|
return u64(f.QuadPart)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn init_win_time_start() u64 {
|
||||||
|
mut s := C.LARGE_INTEGER{}
|
||||||
|
_ := C.QueryPerformanceCounter(&s)
|
||||||
|
return u64(s.QuadPart)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn sys_mono_now() u64 {
|
||||||
|
mut tm := C.LARGE_INTEGER{}
|
||||||
|
_ := C.QueryPerformanceCounter(&tm) // XP or later never fail
|
||||||
|
return mul_div(u64(tm.QuadPart) - start_time, 1_000_000_000, freq_time)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn mul_div(val, numer, denom u64) u64 {
|
||||||
|
q := val / denom
|
||||||
|
r := val % denom
|
||||||
|
return q * numer + r * numer / denom
|
||||||
|
}
|
||||||
|
|
|
@ -1,60 +0,0 @@
|
||||||
// Copyright (c) 2019-2020 Alexander Medvednikov. All rights reserved.
|
|
||||||
// Use of this source code is governed by an MIT license
|
|
||||||
// that can be found in the LICENSE file.
|
|
||||||
module time
|
|
||||||
|
|
||||||
// Timer struct and functions
|
|
||||||
// start and end are # of ms since start of system.
|
|
||||||
// When end_ticks == 0, this means the timer is actively "running"
|
|
||||||
pub struct Timer {
|
|
||||||
pause_start i64
|
|
||||||
pub:
|
|
||||||
start_ticks i64
|
|
||||||
end_ticks i64
|
|
||||||
}
|
|
||||||
|
|
||||||
// start Starts the timer. If the timer was paused, restarts counting.
|
|
||||||
pub fn (t mut Timer) start() {
|
|
||||||
if t.pause_start == 0 {
|
|
||||||
t.start_ticks = ticks()
|
|
||||||
} else {
|
|
||||||
// We were paused, so pretend like the time we were paused didn't
|
|
||||||
// happen
|
|
||||||
t.start_ticks += ticks() - t.pause_start
|
|
||||||
}
|
|
||||||
t.end_ticks = 0
|
|
||||||
t.pause_start = 0
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn (t mut Timer) restart() {
|
|
||||||
t.end_ticks = 0
|
|
||||||
t.pause_start = 0
|
|
||||||
t.start_ticks = ticks()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn (t mut Timer) pause() {
|
|
||||||
t.pause_start = ticks()
|
|
||||||
t.end_ticks = t.pause_start // so elapsed() still keeps track of the cared-amount of time
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn (t mut Timer) stop() {
|
|
||||||
t.end_ticks = ticks()
|
|
||||||
t.pause_start = 0
|
|
||||||
}
|
|
||||||
|
|
||||||
// elapsed If the Timer is stopped, returns the number of milliseconds between
|
|
||||||
// the last start and stop.
|
|
||||||
// If the Timer is still running, returns the number of milliseconds from the
|
|
||||||
// last start to now.
|
|
||||||
pub fn (t Timer) elapsed() i64 {
|
|
||||||
if t.end_ticks == 0 {
|
|
||||||
return ticks() - t.start_ticks
|
|
||||||
} else {
|
|
||||||
return t.end_ticks - t.start_ticks
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn new_timer() Timer {
|
|
||||||
return Timer{start_ticks: ticks()}
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in New Issue