We have some code that wants to call localtime
very often from multiple threads. (Relevant background: it's a server where one of the things you can ask it for is the local time as a string, and it wants to be able to serve 100Ks of requests per second.)
We have discovered that on Ubuntu Linux 12.04, the glibc function localtime_r
("reentrant localtime") calls __tz_convert
, which still takes a global lock!
(Also, it looks like FreeBSD makes localtime_r
call tzset
on every single invocation, because they're paranoid that the program might have done a setenv("TZ")
and/or the user downloaded a new version of /etc/localtime
between now and the last time localtime_r
was called. (This is the opposite of the situation described here; it seems that glibc calls tzset
on every invocation of localtime
but not localtime_r
, just to be confusing.)
Obviously, this is terrible for performance. For our purposes, we would like to basically "snapshot" the rules for our current timezone when the server starts running, and then use that snapshot forever afterward. So we'd continue to respect Daylight Savings Time rules (because the rules for when to switch to DST would be part of the snapshot), but we would never go back to the disk, take mutexes, or do anything else that would cause threads to block. (We are fine with not respecting downloaded updates to tzinfo and not respecting changes to /etc/localtime
; we don't expect the server to physically change timezones while it's running.)
However, I can't find any information online about how to deal with timezone rules — whether there's a userspace API for working with them, or whether we'll be forced to reimplement a few hundred lines of glibc code to read the timezone data ourselves.
Do we have to reimplement everything downstream of __tz_convert
— including tzfile_read
, since it doesn't seem to be exposed to users? Or is there some POSIX interface and/or third-party library that we could use for working with timezone rules?
(I've seen http://www.iana.org/time-zones/repository/tz-link.html but I'm not sure it's helpful.)