diff --git a/cmd/tools/fast/fast.v b/cmd/tools/fast/fast.v index 078546835b..35ca11ea27 100644 --- a/cmd/tools/fast/fast.v +++ b/cmd/tools/fast/fast.v @@ -80,7 +80,7 @@ fn measure(cmd string) int { exec(cmd) } println('Building...') - sw := time.new_stopwatch() + sw := time.new_stopwatch({}) exec(cmd) return int(sw.elapsed().milliseconds()) } diff --git a/doc/docs.md b/doc/docs.md index 6e03f1fdc5..36ea81c9e6 100644 --- a/doc/docs.md +++ b/doc/docs.md @@ -1494,7 +1494,7 @@ You can also use stopwatches to measure just portions of your code explicitly: ```v import time fn main(){ - sw := time.new_stopwatch() + sw := time.new_stopwatch({}) println('Hello world') println('Greeting the world took: ${sw.elapsed().nanoseconds()}ns') } diff --git a/vlib/benchmark/benchmark.v b/vlib/benchmark/benchmark.v index 7db28172a4..7dd60abbac 100644 --- a/vlib/benchmark/benchmark.v +++ b/vlib/benchmark/benchmark.v @@ -70,14 +70,14 @@ pub mut: pub fn new_benchmark() Benchmark { return Benchmark{ - bench_timer: time.new_stopwatch() + bench_timer: time.new_stopwatch({}) verbose: true } } pub fn new_benchmark_no_cstep() Benchmark { return Benchmark{ - bench_timer: time.new_stopwatch() + bench_timer: time.new_stopwatch({}) verbose: true no_cstep: true } @@ -85,7 +85,7 @@ pub fn new_benchmark_no_cstep() Benchmark { pub fn new_benchmark_pointer() &Benchmark { return &Benchmark{ - bench_timer: time.new_stopwatch() + bench_timer: time.new_stopwatch({}) verbose: true } } diff --git a/vlib/live/executable/reloader.v b/vlib/live/executable/reloader.v index 05645fd5ea..1f0677ab68 100644 --- a/vlib/live/executable/reloader.v +++ b/vlib/live/executable/reloader.v @@ -49,7 +49,7 @@ fn elog(r &live.LiveReloadInfo, s string){ } fn compile_and_reload_shared_lib(r mut live.LiveReloadInfo) ?bool { - sw := time.new_stopwatch() + sw := time.new_stopwatch({}) new_lib_path := compile_lib(mut r) or { return error('errors while compiling $r.original') } @@ -63,7 +63,7 @@ fn compile_lib(r mut live.LiveReloadInfo) ?string { new_lib_path, new_lib_path_with_extension := current_shared_library_path(mut r) cmd := '$r.vexe $r.vopts -o $new_lib_path $r.original' elog(r,'> compilation cmd: $cmd') - cwatch := time.new_stopwatch() + cwatch := time.new_stopwatch({}) recompilation_result := os.exec( cmd ) or { eprintln('recompilation failed') return none diff --git a/vlib/time/stopwatch.v b/vlib/time/stopwatch.v index 52890f6dbb..fcd7299d59 100644 --- a/vlib/time/stopwatch.v +++ b/vlib/time/stopwatch.v @@ -3,50 +3,65 @@ // that can be found in the LICENSE file. module time -pub struct StopWatch { -mut: - pause_time u64 -pub mut: - start u64 - end u64 +pub struct StopWatchOptions { + auto_start bool = true } -pub fn new_stopwatch() StopWatch { - return StopWatch{pause_time: 0, start: time.sys_mono_now(), end: 0} +pub struct StopWatch { +mut: + elapsed u64 +pub mut: + start u64 + end u64 +} + +pub fn new_stopwatch(opts StopWatchOptions) StopWatch { + mut initial := u64(0) + + if opts.auto_start { + initial = time.sys_mono_now() + } + + return StopWatch{elapsed: 0, start: initial, end: 0} } // start Starts the timer. If the timer was paused, restarts counting. pub fn (mut t StopWatch) start() { - if t.pause_time == 0 { - t.start = time.sys_mono_now() - } else { - t.start += time.sys_mono_now() - t.pause_time - } + t.start = time.sys_mono_now() t.end = 0 - t.pause_time = 0 } pub fn (mut t StopWatch) restart() { - t.end = 0 - t.pause_time = 0 t.start = time.sys_mono_now() + t.end = 0 + t.elapsed = 0 } pub fn (mut t StopWatch) stop() { t.end = time.sys_mono_now() - t.pause_time = 0 } pub fn (mut t StopWatch) pause() { - t.pause_time = time.sys_mono_now() - t.end = t.pause_time // so elapsed keeps track of actual running time + if t.start > 0 { + if t.end == 0 { + t.elapsed += time.sys_mono_now() - t.start + } else { + t.elapsed += t.end - t.start + } + } + + t.start = 0 } // 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) + if t.start > 0 { + if t.end == 0 { + return Duration(time.sys_mono_now() - t.start + t.elapsed) + } else { + return Duration(t.end - t.start + t.elapsed) + } } + + return Duration(t.elapsed) } diff --git a/vlib/time/stopwatch_test.v b/vlib/time/stopwatch_test.v index ae433bf86a..69c87071be 100644 --- a/vlib/time/stopwatch_test.v +++ b/vlib/time/stopwatch_test.v @@ -4,7 +4,7 @@ import time // time than you have specified. To avoid false positives from CI test // failures, some of the asserts will be run only if you pass `-d stopwatch` fn test_stopwatch_works_as_intended() { - sw := time.new_stopwatch() + sw := time.new_stopwatch({}) // sample code that you want to measure: println('Hello world') time.sleep_ms(1) @@ -14,20 +14,21 @@ fn test_stopwatch_works_as_intended() { } fn test_stopwatch_time_between_pause_and_start_should_be_skipped_in_elapsed() { - sw := time.new_stopwatch() + println('Testing pause function') + sw := time.new_stopwatch({}) time.sleep_ms(10) // A - // eprintln('${sw.elapsed().milliseconds()}ms') + eprintln('Elapsed after 10ms nap: ${sw.elapsed().milliseconds()}ms') assert sw.elapsed().milliseconds() >= 10 sw.pause() time.sleep_ms(10) - // eprintln('${sw.elapsed().milliseconds()}ms') + eprintln('Elapsed after pause and another 10ms nap: ${sw.elapsed().milliseconds()}ms') assert sw.elapsed().milliseconds() >= 10 $if stopwatch ? { assert sw.elapsed().milliseconds() < 20 } sw.start() time.sleep_ms(10) // B - // Here, sw.elapsed() should be ~10ms (from A) + ~10ms (from B) >= 20ms + eprintln('Elapsed after resume and another 10ms nap: ${sw.elapsed().milliseconds()}ms') assert sw.elapsed().milliseconds() >= 20 $if stopwatch ? { assert sw.elapsed().milliseconds() < 30 diff --git a/vlib/v/builder/compile.v b/vlib/v/builder/compile.v index 0870879f55..6b32ef65cd 100644 --- a/vlib/v/builder/compile.v +++ b/vlib/v/builder/compile.v @@ -29,7 +29,7 @@ pub fn compile(command string, pref &pref.Preferences) { println('builder.compile() pref:') // println(pref) } - mut sw := time.new_stopwatch() + mut sw := time.new_stopwatch({}) match pref.backend { .c { b.compile_c() } .js { b.compile_js() }