【问题标题】:c++ time() function performance in solarisc++ time()函数在solaris中的性能
【发布时间】:2013-07-25 13:29:38
【问题描述】:

我们有一个在 Solaris(5.10,sparc 平台)上运行的多线程 C++ 应用程序。根据“pstack”,大多数线程似乎经常在下面的调用中等待太久。这对应于应用程序代码中的“time_t currentTime = time(NULL) ;”函数获取当前时间(以秒为单位)。

ffffffff76cdbe1c __time (0, 23e8, 1dab58, ffffffff76c63508, ffffffff76e3e000, 2000) + 8

时区是“亚洲/利雅得”。我尝试将 TZ 变量设置为“Asia/Riyadh”以及“<GMT+3>-3”。但是这两种选择都没有明显的改善。此时更改服务器代码(即使有替代方法)相当困难。一个有 100 万次“time(NULL)”调用的测试程序(单线程,编译时没有 -O2)很快就出来了。应用程序和测试程序使用gcc 4.5.1 编译。

还有什么我可以尝试的吗?

我同意这是一个相当广泛的问题。一旦有足够的改进来处理当前负载,我将尝试有效的建议并关闭它。

编辑 1:

请忽略上面对 time(NULL) 的引用,作为 __time 堆栈的可能原因。我根据签名进行了推断,并在源方法中找到了相同的调用。

下面是另一个导致 __time 的堆栈。

ffffffff76cdbe1c __time (0, 23e8, 1dab58, ffffffff773e5cc0, ffffffff76e3e000, 2000) + 8
ffffffff76c9c7f0 getnow (ffffffff704fb180, ffffffff773c6384, 1a311c, 2, ffffffff76e4eae8, fffc00) + 4
ffffffff76c9af0c strptime_recurse (ffffffff76e4cea0, 1, 104980178,   ffffffff704fb938, ffffffff704fb180, ffffffff704fb1a4) + 34
ffffffff76c9dce8 __strptime_std (ffffffff76e4cea0, 10458b2d8, 104980178, ffffffff704fb938, 2400, 1a38ec) + 2c

【问题讨论】:

  • 时区对time()的返回值没有影响,至少在Unix下是这样。始终是 UTC。
  • 您应该提供更多证据time 确实是罪魁祸首。 truss -c command 或 dtrace procsystime -aTn yourApp 输出会有所帮助。顺便说一句,设置 TZ 对时间调用本身没有任何影响。 (编辑:后一条评论为时已晚......)
  • @JoachimPileborg 我很惊讶编译器优化了对time 的调用。它是一个外部函数,编译器看不到它的行为,因此编译器必须假设它可能具有可观察到的行为。
  • 我认为我对导致上述堆栈的实际函数是错误的。我在 time() 调用下面的方法中也看到了 localtime() 调用,我认为它依赖于 TZ。我尝试根据我们很久以前遇到的类似问题更改 TZ。

标签: c++ performance time solaris


【解决方案1】:

您(和我们)无法让time 更快。 从你的信息中,我推测你是从许多人那里打电话来的 一次不同的线程。这可能是个问题;相当 Solaris 可能会序列化这些调用,因此您最终会得到 很多线程等待其他线程完成。

您需要多少准确度?一个可能的解决方案可能是 在读取时间时有一个线程循环,可能会休眠 10 毫秒 在每次读取之间,并将结果放入全局变量中, 其他线程读取的。 (别忘了你需要 同步对变量的所有访问,除非你有一些 某种原子变量,例如 C++11 中的 std::atomic<time_t>。)

【讨论】:

  • 是的,它是从多个线程调用的。准确性非常重要。不幸的是,此时我也无法更改服务器代码。
【解决方案2】:

请记住,pstack 不仅会立即中断您的程序并生成堆栈。它必须获得调试级别的控制,如果time 调用足够频繁,它可能会大大过度指示对time 的调用,因为它利用这些系统调用来控制您的应用程序来打印堆栈。

time 调用很可能不是您真正的性能问题的根源。我怀疑您会想要使用诸如gprof(使用g++ -p)之类的分析器。或者,您可以利用一些 dtrace 工具包并使用 hotuser dtrace 脚本,该脚本将对您正在运行的应用程序的用户代码进行基本的统计分析。

time 返回 UTC 时间,因此对 TZ 的任何更改都不会影响其调用时间。

如果在分析之后发现 time 确实是罪魁祸首,您可能能够缓存来自 time 调用的值,因为它每秒不会更改一次以上。

【讨论】:

  • pstack 观察基于过去几天的快照。在代码的不同部分有时间相关的调用。 pstack 几乎总是显示 __time,尽管来自我们代码中的不同方法。代码中还有相当多的其他操作,这些操作在 pstack 中并不经常出现。分析将需要重新编译(在生产机器中观察到此问题)。关于 TZ,如上所述,我可能对 time() 调用有误。还有一个 localtime() 调用。不过我不确定。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-02-07
  • 1970-01-01
相关资源
最近更新 更多