View Bug Activity | Format For Printing
I have an application (syslog-ng) that calls localtime() related functions a lot. After some performance profiling localtime/strftime seems to be a root of a lot of CPU consumption because of the fact that they call tzset() unconditionally. I understand that POSIX requires that localtime()/strftime() notice that timezone information was changed, but calling tzset() unconditionally to do so seems overly expensive to me. What I did to work around the problem was to cache the previous results of localtime() and not call localtime() if the same second was requested. This results in about one localtime() call per second. But still, tzset is on the profile list: ------------------------------------------------------------------------------- 759 100.000 libc-2.6.1.so libc-2.6.1.so __tz_convert 2948 1.5846 libc-2.6.1.so libc-2.6.1.so getenv 2948 100.000 libc-2.6.1.so libc-2.6.1.so getenv [self] ------------------------------------------------------------------------------- 924 100.000 libc-2.6.1.so libc-2.6.1.so __tz_convert 2686 1.4438 libc-2.6.1.so libc-2.6.1.so strcmp 2686 100.000 libc-2.6.1.so libc-2.6.1.so strcmp [self] ------------------------------------------------------------------------------- ------------------------------------------------------------------------------- 2 0.1980 libc-2.6.1.so libc-2.6.1.so tzset 1008 99.8020 libc-2.6.1.so libc-2.6.1.so __tz_convert 1065 0.5725 libc-2.6.1.so libc-2.6.1.so tzset_internal 1065 99.8126 libc-2.6.1.so libc-2.6.1.so tzset_internal [self] 2 0.1874 libc-2.6.1.so libc-2.6.1.so __tzfile_read ------------------------------------------------------------------------------- Hopefully the profile data can be recognized in this bugzilla entry. To sum it up, the CPU use might be decreased somewhat if this unconditional call to tzset() would be tightened a bit: * only call tzset if /etc/localtime or the TZ environment variable changed * the latter can still be optimized somewhat as putenv() reallocates the environment area, thus any change in TZ will result in a new value of the __environ pointer
This is the expected behavior. If you want to avoid the tzset calls, use localtime_r etc.