profile: use specialized time__vpc_now
							parent
							
								
									50a83736ff
								
							
						
					
					
						commit
						e523540f3a
					
				|  | @ -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 | ||||
| ) | ||||
|  |  | |||
|  | @ -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 | ||||
| } | ||||
|  |  | |||
|  | @ -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) | ||||
| 	} | ||||
| } | ||||
|  |  | |||
|  | @ -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 | ||||
| } | ||||
|  |  | |||
|  | @ -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 | ||||
| 		} | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue