Oh, wow! For us, setting `TZ` is a speedup, but perhaps that's unique to unique situation. (/etc is a FUSE mount in our setting, which is much slower.)
Let me know if it would be helpful for me to do something else here---though I have to confess that gnulib's time code is a little baffling to me! Cheers, Michael On 2024-11-26 at 10:01:56 PM, Pádraig Brady wrote: > On 26/11/2024 03:34, Michael Greenberg wrote: >> If TZ is unset, the date utility will call newfstat("/etc/localtime") >> each time it reads a time using date --date or date -f. If reading from >> /etc is expensive, you can experience significant slowdowns. >> >> I didn't write a new test---you can observe the phenomenon by running >> the following: >> >> $ cat dates # 4 isn't enough for slowness, but enough to make the trace >> clear >> Mon Nov 25 09:14:54 PM EST 2024 >> Mon Nov 25 09:15:01 PM EST 2024 >> Mon Nov 25 09:15:01 PM EST 2024 >> Mon Nov 25 09:15:01 PM EST 2024 >> $ strace date -f dates +%a >> ... see 4 calls to newfstatat on /etc/localtime >> $ strace coreutils/src/date -f dates +%a # use the patched version >> ... see 1 call to newfstatat on /usr/share/zoneinfo/YOURTIMEZONEHERE ... > > Indeed: > > $ yes 1 | head -n100 | strace -e newfstatat -c date -f- > /dev/null > % time seconds usecs/call calls errors syscall > ------ ----------- ----------- --------- --------- ---------------- > 100.00 0.000071 0 100 newfstatat > > Also if specifying TZ in the date, it gets worse! > > $ yes 'TZ="UTC" 1' | head -n100 | strace -e newfstatat -c date -f- > > /dev/null > % time seconds usecs/call calls errors syscall > ------ ----------- ----------- --------- --------- ---------------- > 100.00 0.005097 5 999 newfstatat > >> It might be possible to achieve the same effect by patching gnulib, but >> I haven't dug into it. > > Thanks for the info. It does seem like we could improve here. > I won't be able to dig into this, this week at least. > > thanks, > Pádraig. > >> >> Cheers, >> Michael >> >> --- >> src/date.c | 8 ++++++++ >> 1 file changed, 8 insertions(+) >> >> diff --git a/src/date.c b/src/date.c >> index ee32403ef..45b111c4e 100644 >> --- a/src/date.c >> +++ b/src/date.c >> @@ -575,6 +575,14 @@ main (int argc, char **argv) >> char *format_copy = adjust_resolution (format); >> char const *format_res = format_copy ? format_copy : format; >> char const *tzstring = getenv ("TZ"); >> + /* If TZ is unset, set it to the system timezone. This caches the >> + value, so batch_convert won't have to do it over and over >> + again. */ >> + if (tzstring == NULL) { >> + tzset(); >> + tzstring = tzname[0]; >> + setenv("TZ", tzstring, 0); >> + } >> timezone_t tz = tzalloc (tzstring); >> >> if (batch_file != nullptr)