[PATCH v4 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. -- v4: msvcrt: Avoid expensive timezone queries from plain time() calls. 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 | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/dlls/msvcrt/time.c b/dlls/msvcrt/time.c index 9b0cbb4969f..352a91fb058 100644 --- a/dlls/msvcrt/time.c +++ b/dlls/msvcrt/time.c @@ -780,11 +780,12 @@ int CDECL _ftime32_s(struct __timeb32 *buf) __time64_t CDECL _time64(__time64_t *buf) { __time64_t curtime; - struct __timeb64 tb; - - _ftime64(&tb); + FILETIME ft; + ULONGLONG time; - curtime = tb.time; + GetSystemTimeAsFileTime(&ft); + time = ((ULONGLONG)ft.dwHighDateTime << 32) | ft.dwLowDateTime; + curtime = time / TICKSPERSEC - SECS_1601_TO_1970; return buf ? *buf = curtime : curtime; } @@ -794,11 +795,10 @@ __time64_t CDECL _time64(__time64_t *buf) __time32_t CDECL _time32(__time32_t *buf) { __time32_t curtime; - struct __timeb64 tb; - - _ftime64(&tb); + __time64_t time; - curtime = (tb.time == (__time32_t)tb.time) ? tb.time : -1; + time = _time64(NULL); + curtime = (time == (__time32_t)time) ? time : -1; return buf ? *buf = curtime : curtime; } -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10893
Rebased & merged into 1 commit. Also, I've just realized that the performance gains (for `time()` calls) are massive for this MR: * initially (0c0d26432084c18213d5c4b343f10939d25eee2c): 5300 ns/call * with _this_ MR !10893: 62 ns/call * the _other_ MR !10892: 3250 ns/call * native: 3 ns/call Measurements were inspired by !10348 with minor changes: 1 warmup call, 100000 iterations. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/10893#note_140274
This merge request was approved by Piotr Caban. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/10893
participants (3)
-
Benjamin Fischer -
Benjamin Fischer (@bfis) -
Piotr Caban (@piotr)