[PATCH 0/1] MR10893: msvcrt: Avoid expensive timezone queries from plain time() calls
The implementations of `_time32` & `_time64` internally used `_ftime64`, which also needs to query timezone information via `GetTimeZoneInformation()` which can be fairly expensive i.e. somewhere down the line is a `localtime()` call that practically always triggers at least a `stat` syscall, which is a lot of overhead for merely querying the time. This is workaround mentioned in MR !10892, for further details of the underlying issue see the description there. This MR should be fully transparent, since the return value of the `time` function(s) does not depend on the current timezone information at all. Even with MR !10892 applied, this change may still result in a speedup, just less severe since only function calls but no (further) syscall(s) are avoided. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/10893
From: Benjamin Fischer <bfis@gmx.net> The implementations of _time32 & _time64 internally used _ftime64, which also needs to query timezone information via GetTimeZoneInformation() which can be fairly expensive i.e. somewhere down the line is a localtime() call that practically always triggers at least a stat syscall, which is a lot of overhead for merely querying the time. --- dlls/msvcrt/time.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/dlls/msvcrt/time.c b/dlls/msvcrt/time.c index 9b0cbb4969f..1bca5ec6495 100644 --- a/dlls/msvcrt/time.c +++ b/dlls/msvcrt/time.c @@ -780,11 +780,16 @@ int CDECL _ftime32_s(struct __timeb32 *buf) __time64_t CDECL _time64(__time64_t *buf) { __time64_t curtime; - struct __timeb64 tb; + FILETIME ft; + ULONGLONG time; + + _tzset_init(); + + GetSystemTimeAsFileTime(&ft); - _ftime64(&tb); + time = ((ULONGLONG)ft.dwHighDateTime << 32) | ft.dwLowDateTime; - curtime = tb.time; + curtime = time / TICKSPERSEC - SECS_1601_TO_1970; return buf ? *buf = curtime : curtime; } @@ -794,11 +799,11 @@ __time64_t CDECL _time64(__time64_t *buf) __time32_t CDECL _time32(__time32_t *buf) { __time32_t curtime; - struct __timeb64 tb; + __time64_t time; - _ftime64(&tb); + time = _time64(NULL); - curtime = (tb.time == (__time32_t)tb.time) ? tb.time : -1; + curtime = (time == (__time32_t)time) ? time : -1; return buf ? *buf = curtime : curtime; } -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10893
Piotr Caban (@piotr) commented about dlls/msvcrt/time.c:
__time64_t CDECL _time64(__time64_t *buf) { __time64_t curtime; - struct __timeb64 tb; + FILETIME ft; + ULONGLONG time; + + _tzset_init(); Is there any reason for calling `_tzset_init` here? Could you please also remove some blank lines from the function?
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/10893#note_140002
participants (3)
-
Benjamin Fischer -
Benjamin Fischer (@bfis) -
Piotr Caban (@piotr)