[PATCH v2 0/1] MR10348: ntdll: Avoid expensive inverted DST check on get_timezone_info() cache hit path
inverted DST detection (two mktime() calls) out of the cache hit fast path in get_timezone_info(). Keep the cache key based on the cheap raw bias value and only compute inverted_dst/adjusted_bias on cache miss. Preserve the inverse DST correctness fix by still applying adjusted_bias to tzi->Bias in the slow path. This restores fast-path behavior for frequent GetTimeZoneInformation callers without regressing inverse DST handling. Fixes regression: bfae6eb8b4f6 ("ntdll: Fix get_timezone_info() for timezones defined with inverse DST on Unix.") Fixes: https://bugs.winehq.org/show_bug.cgi?id=59514 ## Test results Using a simple test demo: [time_bench.c](/uploads/700a5b087b09a0d93388dbcf437ad42d/time_bench.c) On AMD Ryzen 5800H with power connected it's **24 times** faster. Wine 11.4 without this fix: ``` iterations: 10000 time() : 1.093640 s (109364 ns/call) localtime() : 1.109118 s (110912 ns/call) sink=17736685140379 ``` With this fix: ``` iterations: 10000 time() : 0.046216 s (4622 ns/call) localtime() : 0.046636 s (4664 ns/call) sink=17736685140000 ``` -- v2: ntdll: Avoid expensive inverted DST check on get_timezone_info() cache hit path https://gitlab.winehq.org/wine/wine/-/merge_requests/10348
From: Zhou Qiankang <wszqkzqk@qq.com> inverted DST detection (two mktime() calls) out of the cache hit fast path in get_timezone_info(). Keep the cache key based on the cheap raw bias value and only compute inverted_dst/adjusted_bias on cache miss. Preserve the inverse DST correctness fix by still applying adjusted_bias to tzi->Bias in the slow path. This restores fast-path behavior for frequent GetTimeZoneInformation callers without regressing inverse DST handling. Fixes regression: bfae6eb8b4f6 ("ntdll: Fix get_timezone_info() for timezones defined with inverse DST on Unix.") Fixes: https://bugs.winehq.org/show_bug.cgi?id=59514 Signed-off-by: Zhou Qiankang <wszqkzqk@qq.com> --- dlls/ntdll/unix/system.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/dlls/ntdll/unix/system.c b/dlls/ntdll/unix/system.c index 22f8b496220..d2cd1d1b980 100644 --- a/dlls/ntdll/unix/system.c +++ b/dlls/ntdll/unix/system.c @@ -3012,12 +3012,6 @@ static void get_timezone_info( RTL_DYNAMIC_TIME_ZONE_INFORMATION *tzi ) bias = (LONG)(mktime(tm) - year_start) / 60; tm = localtime(&year_start); - tm1 = tm2 = *tm; - tm1.tm_isdst = 0; - tm2.tm_isdst = 1; - inverted_dst = mktime(&tm1) < mktime(&tm2); - if (inverted_dst) bias += 60; - if (current_year == tm->tm_year && current_bias == bias) { *tzi = cached_tzi; @@ -3025,10 +3019,16 @@ static void get_timezone_info( RTL_DYNAMIC_TIME_ZONE_INFORMATION *tzi ) return; } + tm1 = tm2 = *tm; + tm1.tm_isdst = 0; + tm2.tm_isdst = 1; + inverted_dst = mktime(&tm1) < mktime(&tm2); + current_bias = bias; + if (inverted_dst) bias += 60; + memset(tzi, 0, sizeof(*tzi)); TRACE("tz data will be valid through year %d, bias %d, inverted_dst %d\n", tm->tm_year + 1900, bias, inverted_dst); current_year = tm->tm_year; - current_bias = bias; tzi->Bias = bias; -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10348
Paul Gofman (@gofman) commented about dlls/ntdll/unix/system.c:
return; }
+ tm1 = tm2 = *tm; + tm1.tm_isdst = 0; + tm2.tm_isdst = 1; + inverted_dst = mktime(&tm1) < mktime(&tm2); + current_bias = bias;
that doesn't affect functionality, but for better readability I'd suggest to keep assigning current_year and current_bias together and not split those across the code. Also probably move those assignments right after the 'if' checking those, before 'tm1 = tm2= *tm;'. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/10348#note_132386
participants (3)
-
Paul Gofman (@gofman) -
Zhou Qiankang -
Zhou Qiankang (@wszqkzqk)