From e523540f3a54c7eafeb9c158cb6aed2065215bee Mon Sep 17 00:00:00 2001 From: Delyan Angelov Date: Sun, 26 Apr 2020 20:36:38 +0300 Subject: [PATCH] profile: use specialized time__vpc_now --- cmd/tools/preludes/profiled_program.v | 2 +- vlib/time/time_darwin.c.v | 22 +++++++--------- vlib/time/time_nix.c.v | 16 +++++++++++ vlib/time/time_windows.c.v | 38 +++++++++++++-------------- vlib/v/gen/fn.v | 6 ++--- 5 files changed, 48 insertions(+), 36 deletions(-) diff --git a/cmd/tools/preludes/profiled_program.v b/cmd/tools/preludes/profiled_program.v index 783ff32e25..66bb209465 100644 --- a/cmd/tools/preludes/profiled_program.v +++ b/cmd/tools/preludes/profiled_program.v @@ -3,5 +3,5 @@ module main import time const ( - profiled_program_time_used = time.sys_mono_now() + profiled_program_time_used = time.seconds_per_minute ) diff --git a/vlib/time/time_darwin.c.v b/vlib/time/time_darwin.c.v index 808f5f971d..11436cc186 100644 --- a/vlib/time/time_darwin.c.v +++ b/vlib/time/time_darwin.c.v @@ -10,31 +10,29 @@ const ( [typedef] struct C.mach_timebase_info_data_t { - numer u64 - denom u64 + numer u32 + denom u32 } fn C.mach_absolute_time() u64 fn C.mach_timebase_info(&C.mach_timebase_info_data_t) +fn C.clock_gettime_nsec_np(int) u64 struct InternalTimeBase { - numer u64 - denom u64 + numer u32 = 1 + denom u32 = 1 } fn init_time_base() InternalTimeBase { - mut tb := C.mach_timebase_info_data_t{} + 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 + if time_base.denom == 0 { + C.mach_timebase_info(&time_base) + } + return (tm - start_time) * time_base.numer / time_base.denom } diff --git a/vlib/time/time_nix.c.v b/vlib/time/time_nix.c.v index 5dc8e02fbf..8d81ba568c 100644 --- a/vlib/time/time_nix.c.v +++ b/vlib/time/time_nix.c.v @@ -39,3 +39,19 @@ fn sys_mono_now() u64 { } } +// NB: vpc_now is used by `v -profile` . +// It should NOT call *any other v function*, just C functions and casts. +[inline] +fn vpc_now() u64 { + $if macos { + tm := C.mach_absolute_time() + if time_base.denom == 0 { + C.mach_timebase_info(&time_base) + } + return (tm - start_time) * time_base.numer / time_base.denom + } $else { + ts := C.timespec{} + C.clock_gettime(C.CLOCK_MONOTONIC, &ts) + return u64(ts.tv_sec) * 1_000_000_000 + u64(ts.tv_nsec) + } +} diff --git a/vlib/time/time_windows.c.v b/vlib/time/time_windows.c.v index 4d4d13f884..66b7324e66 100644 --- a/vlib/time/time_windows.c.v +++ b/vlib/time/time_windows.c.v @@ -12,48 +12,46 @@ struct C.tm { 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.QueryPerformanceCounter(&C.LARGE_INTEGER) C.BOOL +fn C.QueryPerformanceCounter(&u64) C.BOOL -fn C.QueryPerformanceFrequency(&C.LARGE_INTEGER) C.BOOL +fn C.QueryPerformanceFrequency(&u64) C.BOOL fn make_unix_time(t C.tm) int { return int(C._mkgmtime(&t)) } fn init_win_time_freq() u64 { - mut f := C.LARGE_INTEGER{} - _ := C.QueryPerformanceFrequency(&f) - return u64(f.QuadPart) + f := u64(0) + C.QueryPerformanceFrequency(&f) + return f } fn init_win_time_start() u64 { - mut s := C.LARGE_INTEGER{} - _ := C.QueryPerformanceCounter(&s) - return u64(s.QuadPart) + s := u64(0) + C.QueryPerformanceCounter(&s) + return s } 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) + tm := u64(0) + C.QueryPerformanceCounter(&tm) // XP or later never fail + return (tm - 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 +// NB: vpc_now is used by `v -profile` . +// It should NOT call *any other v function*, just C functions and casts. +[inline] +fn vpc_now() u64 { + tm := u64(0) + C.QueryPerformanceCounter(&tm) + return tm } diff --git a/vlib/v/gen/fn.v b/vlib/v/gen/fn.v index 8a207fe994..c60ef4261a 100644 --- a/vlib/v/gen/fn.v +++ b/vlib/v/gen/fn.v @@ -109,14 +109,14 @@ fn (mut g Gen) gen_fn_decl(it ast.FnDecl) { g.writeln('\tatexit(vprint_profile_stats);') g.writeln('') } - if it.name == 'time.sys_mono_now' { + if it.name == 'time.vpc_now' { g.defer_profile_code = '' } else { fn_profile_counter_name := 'vpc_${g.last_fn_c_name}' g.writeln('') - g.writeln('\tdouble _PROF_FN_START = time__sys_mono_now(); ${fn_profile_counter_name}_calls++; // $it.name') + g.writeln('\tdouble _PROF_FN_START = time__vpc_now(); ${fn_profile_counter_name}_calls++; // $it.name') g.writeln('') - g.defer_profile_code = '\t${fn_profile_counter_name} += time__sys_mono_now() - _PROF_FN_START;' + g.defer_profile_code = '\t${fn_profile_counter_name} += time__vpc_now() - _PROF_FN_START;' g.pcs_declarations.writeln('double ${fn_profile_counter_name} = 0.0; u64 ${fn_profile_counter_name}_calls = 0;') g.pcs[g.last_fn_c_name] = fn_profile_counter_name }