我们有一些代码需要从多个线程中经常调用
我们发现在Ubuntu Linux 12.04上,glibc库函数
显然,这对性能来说是很糟糕的。为了我们的目的,我们希望在服务器开始运行时“快照”当前时区的规则,然后在以后的所有时间里都使用该快照。因此,我们将继续遵守夏令时规则(因为切换到夏令时的规则将成为快照的一部分),但我们将永远不会回到磁盘、锁定互斥锁或执行任何其他可能导致线程阻塞的操作。(我们可以不考虑下载的tzinfo更新以及
然而,我在网上找不到有关如何处理时区规则的任何信息 - 是否有一个用户空间API可用于处理它们,或者我们将被迫重新实现几百行glibc代码以自己读取时区数据。
我们必须重新实现
我看过http://www.iana.org/time-zones/repository/tz-link.html,但不确定它是否有帮助。
localtime
函数。(相关背景:这是一个服务器,你可以向它请求本地时间作为字符串,并且它希望能够每秒处理数十万个请求。)我们发现在Ubuntu Linux 12.04上,glibc库函数
localtime_r
("可重入的本地时间")调用了__tz_convert
函数,而__tz_convert
函数仍然使用了全局锁!
(此外,看起来FreeBSD让localtime_r
函数在每次调用时都调用tzset
函数,因为他们担心程序可能已经执行了setenv("TZ")
操作,或者用户在上次调用localtime_r
函数之后下载了新版本的/etc/localtime
文件。(这与这里描述的情况相反;似乎glibc在每次调用localtime
函数时都会调用tzset
函数,但不会在每次调用localtime_r
函数时调用,这非常令人困惑。)显然,这对性能来说是很糟糕的。为了我们的目的,我们希望在服务器开始运行时“快照”当前时区的规则,然后在以后的所有时间里都使用该快照。因此,我们将继续遵守夏令时规则(因为切换到夏令时的规则将成为快照的一部分),但我们将永远不会回到磁盘、锁定互斥锁或执行任何其他可能导致线程阻塞的操作。(我们可以不考虑下载的tzinfo更新以及
/etc/localtime
更改;我们不希望服务器在运行时物理更改时区。)然而,我在网上找不到有关如何处理时区规则的任何信息 - 是否有一个用户空间API可用于处理它们,或者我们将被迫重新实现几百行glibc代码以自己读取时区数据。
我们必须重新实现
__tz_convert
函数及其下游的所有内容,包括tzfile_read
函数吗?还是有一些POSIX接口和/或第三方库可用于处理时区规则?我看过http://www.iana.org/time-zones/repository/tz-link.html,但不确定它是否有帮助。
tzset
中的全局锁 “对性能非常糟糕”这一点并不明显 - 你是否真的进行了基准测试?除非你做过基准测试,否则这似乎是一个俗语般的过早优化案例。据我所知,tzset
有一种快速路径,如果时区实际上没有改变,它基本上什么也不做。在实际应用中,我预计锁永远不会争用。 - user4815162342__tz_convert
时,锁就会被争夺;请检查代码。是的,我们之所以知道这个锁存在,是因为在性能测试中它成为了瓶颈(特定测试服务于大量本地时间请求)。 - Quuxplusone