堆栈展开真的需要锁吗?

Posted

技术标签:

【中文标题】堆栈展开真的需要锁吗?【英文标题】:Does stack unwinding really require locks? 【发布时间】:2014-10-08 12:50:35 【问题描述】:

我一直在使用 mutrace 分析我的代码并得到以下有趣/令人担忧的结果:

Mutex #1260690 (0x0x7f87bc8eea40) first referenced by:
    /usr/lib/mutrace/libmutrace.so(pthread_mutex_lock+0x49) [0x7f87be0b76b9]
    /lib/x86_64-linux-gnu/libgcc_s.so.1(_Unwind_Find_FDE+0x26) [0x7f87bc6eb0e6]

mutrace: Showing 10 most contended mutexes:

Mutex #   Locked  Changed    Cont. tot.Time[ms] avg.Time[ms] max.Time[ms]  Flags
1260690 19066789  1509831   109753     3600.883        0.000        0.226 M-.--.

_Unwind_Find_FDE 似乎必须处理堆栈展开。

我的应用程序是高度多线程的,具有非常严格的延迟要求,因此我想尽可能轻松地消除这种情况。是否有任何编译器或环境设置可以用来摆脱这个函数调用,而无需重写我的代码?我们确实在部分流控制中使用了异常(可能是不明智的),但要解决这个问题需要很大的重构工作。

g++ (Ubuntu 4.8.2-19ubuntu1) 4.8.2

【问题讨论】:

“我们确实在部分流程控制中使用了异常”然后你必须付出这个代价(你很幸运没有人向你的窗户扔石头哈哈) 不幸的是,我认为您将不得不纠正您的错误,并且不要在热路径中使用异常来控制流量。其他任何东西都是黑客攻击。 异常应该是正常程序流程的一部分,它们应该是异常。如果你抛出异常,你严格的延迟要求就不会那么严格,因为堆栈展开通常效率不高。 正常的 C++ 约定是在展开堆栈时自动调用对象析构函数。我的水晶球说你只是看到了解决这个问题的管道。 @James:在摘要中,我同意。但是,如果您与 other 线程交互的“单线程”锁定了由类控制的互斥锁的资源,那么我希望类析构函数尝试清理资源,这就是你可能会遇到互斥体。 【参考方案1】:

如果您需要低延迟,请停止使用异常。

【讨论】:

如果不抛出异常,它们不会影响运行时。例外情况下可以安全地实现低延迟。 如果“慢”异常超出您的延迟要求,请停止使用它们。一个好的实现不需要有“慢”的例外。如果你的实现不好,那么,好吧,... @AlexShtof “我们确实在部分流程控制中使用了异常”。这个答案是 100% 正确的。当您将异常用于它们并非专门设计用于处理的事情时,您不能抱怨异常的延迟。

以上是关于堆栈展开真的需要锁吗?的主要内容,如果未能解决你的问题,请参考以下文章

如何使堆栈面板内的按钮展开以占用整个空间?

堆栈展开失败的原因

为啥堆栈展开后程序无法到达正确的返回指令?

如何展开ARM Cortex M3堆栈

gcc 如何在 linux 上实现 C++ 异常的堆栈展开?

在展开操作期间遇到无效或未对齐的堆栈