From c936218d48e7d04f21985c9b30907e391d3b1547 Mon Sep 17 00:00:00 2001 From: Curtis Vogt Date: Fri, 27 Nov 2015 14:21:06 -0600 Subject: [PATCH] Implementation of now() with milliseconds Created the jl_timeval helper function rather than make a Windows version of gettimeofday to give us certainty as to the number of bits used by sec and usec fields. Additional changes include: - Inlining tv2float function - Adding additional testcases for now - Renaming `clock_now` to `jl_clock_now` --- base/dates/conversions.jl | 5 +++-- base/libc.jl | 14 +++++++++++++- base/version.jl | 2 +- src/flisp/builtins.c | 2 +- src/gc.c | 18 +++++++++--------- src/julia.expmap | 1 - src/support/timefuncs.c | 36 ++++++++++++++++-------------------- src/support/timefuncs.h | 8 +++++++- test/dates/conversions.jl | 5 +++++ 9 files changed, 55 insertions(+), 36 deletions(-) diff --git a/base/dates/conversions.jl b/base/dates/conversions.jl index c37e86837464b..f9502ecd3f889 100644 --- a/base/dates/conversions.jl +++ b/base/dates/conversions.jl @@ -20,8 +20,9 @@ end # Returns unix seconds since 1970-01-01T00:00:00 datetime2unix(dt::DateTime) = (value(dt) - UNIXEPOCH)/1000.0 function now() - tm = Libc.TmStruct(time()) - return DateTime(tm.year+1900,tm.month+1,tm.mday,tm.hour,tm.min,tm.sec) + tv = Libc.TimeVal() + tm = Libc.TmStruct(tv.sec) + return DateTime(tm.year+1900,tm.month+1,tm.mday,tm.hour,tm.min,tm.sec,div(tv.usec,1000)) end today() = Date(now()) now(::Type{UTC}) = unix2datetime(time()) diff --git a/base/libc.jl b/base/libc.jl index a6ab779aa2192..a7076c29df283 100644 --- a/base/libc.jl +++ b/base/libc.jl @@ -77,6 +77,18 @@ flush_cstdio() = ccall(:jl_flush_cstdio, Void, ()) @unix_only systemsleep(s::Real) = ccall(:usleep, Int32, (UInt32,), round(UInt32,s*1e6)) @windows_only systemsleep(s::Real) = (ccall(:Sleep, stdcall, Void, (UInt32,), round(UInt32,s*1e3)); return Int32(0)) +immutable TimeVal + sec::Int64 + usec::Int64 +end + +function TimeVal() + tv = Ref{TimeVal}() + status = ccall(:jl_gettimeofday, Cint, (Ref{TimeVal},), tv) + status != 0 && error("unable to determine current time: ", status) + return tv[] +end + type TmStruct sec::Int32 min::Int32 @@ -143,7 +155,7 @@ end # system date in seconds time(tm::TmStruct) = Float64(ccall(:mktime, Int, (Ptr{TmStruct},), &tm)) -time() = ccall(:clock_now, Float64, ()) +time() = ccall(:jl_clock_now, Float64, ()) ## process-related functions ## diff --git a/base/version.jl b/base/version.jl index 9c0fed92d0762..3f63dcdc6bf2f 100644 --- a/base/version.jl +++ b/base/version.jl @@ -219,7 +219,7 @@ function banner(io::IO = STDOUT) elseif GIT_VERSION_INFO.commit == "" commit_string = "" else - days = Int(floor((ccall(:clock_now, Float64, ()) - GIT_VERSION_INFO.fork_master_timestamp) / (60 * 60 * 24))) + days = Int(floor((ccall(:jl_clock_now, Float64, ()) - GIT_VERSION_INFO.fork_master_timestamp) / (60 * 60 * 24))) days = max(0, days) unit = days == 1 ? "day" : "days" distance = GIT_VERSION_INFO.fork_master_distance diff --git a/src/flisp/builtins.c b/src/flisp/builtins.c index 05380644338c3..2efafc6635777 100644 --- a/src/flisp/builtins.c +++ b/src/flisp/builtins.c @@ -307,7 +307,7 @@ static value_t fl_time_now(value_t *args, u_int32_t nargs) { argcount("time.now", nargs, 0); (void)args; - return mk_double(clock_now()); + return mk_double(jl_clock_now()); } static value_t fl_path_cwd(value_t *args, uint32_t nargs) diff --git a/src/gc.c b/src/gc.c index f692e89b76945..02e9aa9c36347 100644 --- a/src/gc.c +++ b/src/gc.c @@ -1355,21 +1355,21 @@ static gcval_t** sweep_page(pool_t* p, gcpage_t* pg, gcval_t **pfl, int sweep_ma static void gc_sweep_once(int sweep_mask) { #ifdef GC_TIME - double t0 = clock_now(); + double t0 = jl_clock_now(); mallocd_array_total = 0; mallocd_array_freed = 0; #endif sweep_malloced_arrays(); #ifdef GC_TIME - jl_printf(JL_STDOUT, "GC sweep arrays %.2f (freed %d/%d)\n", (clock_now() - t0)*1000, mallocd_array_freed, mallocd_array_total); - t0 = clock_now(); + jl_printf(JL_STDOUT, "GC sweep arrays %.2f (freed %d/%d)\n", (jl_clock_now() - t0)*1000, mallocd_array_freed, mallocd_array_total); + t0 = jl_clock_now(); big_total = 0; big_freed = 0; big_reset = 0; #endif sweep_big(sweep_mask); #ifdef GC_TIME - jl_printf(JL_STDOUT, "GC sweep big %.2f (freed %d/%d with %d rst)\n", (clock_now() - t0)*1000, big_freed, big_total, big_reset); + jl_printf(JL_STDOUT, "GC sweep big %.2f (freed %d/%d with %d rst)\n", (jl_clock_now() - t0)*1000, big_freed, big_total, big_reset); #endif } @@ -1377,7 +1377,7 @@ static void gc_sweep_once(int sweep_mask) static int gc_sweep_inc(int sweep_mask) { #ifdef GC_TIME - double t0 = clock_now(); + double t0 = jl_clock_now(); #endif skipped_pages = 0; total_pages = 0; @@ -1430,7 +1430,7 @@ static int gc_sweep_inc(int sweep_mask) } #ifdef GC_TIME - double sweep_pool_sec = clock_now() - t0; + double sweep_pool_sec = jl_clock_now() - t0; double sweep_speed = ((((double)total_pages)*GC_PAGE_SZ)/(1024*1024*1024))/sweep_pool_sec; jl_printf(JL_STDOUT, "GC sweep pools %s %.2f at %.1f GB/s (skipped %d%% of %d, done %d pgs, %d freed with %d lazily) mask %d\n", finished ? "end" : "inc", sweep_pool_sec*1000, sweep_speed, total_pages ? (skipped_pages*100)/total_pages : 0, total_pages, page_done, freed_pages, lazy_freed_pages, sweep_mask); #endif @@ -1847,7 +1847,7 @@ static void visit_mark_stack(int mark_mode) void jl_mark_box_caches(void); #if defined(GCTIME) || defined(GC_FINAL_STATS) -double clock_now(void); +double jl_clock_now(void); #endif extern jl_module_t *jl_old_base_module; @@ -2407,7 +2407,7 @@ void jl_print_gc_stats(JL_STREAM *s) { double gct = total_gc_time/1e9; malloc_stats(); - double ptime = clock_now()-process_t0; + double ptime = jl_clock_now()-process_t0; jl_printf(s, "exec time\t%.5f sec\n", ptime); if (n_pause > 0) { jl_printf(s, "gc time \t%.5f sec (%2.1f%%) in %d (%d full) collections\n", @@ -2489,7 +2489,7 @@ void jl_gc_init(void) } #endif #ifdef GC_FINAL_STATS - process_t0 = clock_now(); + process_t0 = jl_clock_now(); #endif #ifdef _P64 diff --git a/src/julia.expmap b/src/julia.expmap index 2da919929999e..7934ace576597 100644 --- a/src/julia.expmap +++ b/src/julia.expmap @@ -4,7 +4,6 @@ __stack_chk_guard; asprintf; bitvector_*; - clock_now; ev_break; get_exename; getlocalip; diff --git a/src/support/timefuncs.c b/src/support/timefuncs.c index 00e4302e3ef6a..4548577de719f 100644 --- a/src/support/timefuncs.c +++ b/src/support/timefuncs.c @@ -28,31 +28,27 @@ extern "C" { #endif -#if defined(_OS_WINDOWS_) -static double floattime(void) +JL_DLLEXPORT int jl_gettimeofday(struct jl_timeval *jtv) { - struct timeb tstruct; - - ftime(&tstruct); - return (double)tstruct.time + (double)tstruct.millitm/1.0e3; -} +#if defined(_OS_WINDOWS_) + struct __timeb64 tb; + errno_t code = _ftime64_s(&tb); + jtv->sec = tb.time; + jtv->usec = tb.millitm * 1000; #else -static double tv2float(struct timeval *tv) -{ - return (double)tv->tv_sec + (double)tv->tv_usec/1.0e6; -} + struct timeval tv; + int code = gettimeofday(&tv, NULL); + jtv->sec = tv.tv_sec; + jtv->usec = tv.tv_usec; #endif + return code; +} -double clock_now(void) +JL_DLLEXPORT double jl_clock_now(void) { -#if defined(_OS_WINDOWS_) - return floattime(); -#else - struct timeval now; - - gettimeofday(&now, NULL); - return tv2float(&now); -#endif + struct jl_timeval now; + jl_gettimeofday(&now); + return now.sec + now.usec * 1e-6; } void sleep_ms(int ms) diff --git a/src/support/timefuncs.h b/src/support/timefuncs.h index d012e83d34feb..45d22184d29b1 100644 --- a/src/support/timefuncs.h +++ b/src/support/timefuncs.h @@ -7,7 +7,13 @@ extern "C" { #endif -JL_DLLEXPORT double clock_now(void); +struct jl_timeval { + int64_t sec; /* seconds */ + int64_t usec; /* microseconds */ +}; + +JL_DLLEXPORT int jl_gettimeofday(struct jl_timeval *jtv); +JL_DLLEXPORT double jl_clock_now(void); void sleep_ms(int ms); #ifdef __cplusplus diff --git a/test/dates/conversions.jl b/test/dates/conversions.jl index 9d749c8d94994..649ebfff7e9b7 100644 --- a/test/dates/conversions.jl +++ b/test/dates/conversions.jl @@ -47,6 +47,11 @@ @test typeof(Dates.today()) <: Dates.Date @test typeof(Dates.now(Dates.UTC)) <: Dates.DateTime +@osx_only withenv("TZ" => "UTC") do + @test abs(Dates.now() - now(Dates.UTC)) < Dates.Second(1) +end +@test abs(Dates.now() - now(Dates.UTC)) < Dates.Hour(16) + # Issue #9171, #9169 let t = Dates.Period[Dates.Week(2), Dates.Day(14), Dates.Hour(14*24), Dates.Minute(14*24*60), Dates.Second(14*24*60*60), Dates.Millisecond(14*24*60*60*1000)] for i = 1:length(t)