可能由于 std::string 堆分配而受文件解析线程影响的性能?

Posted

技术标签:

【中文标题】可能由于 std::string 堆分配而受文件解析线程影响的性能?【英文标题】:performance influenced by a file parsing thread possibly due to std::string heap allocations? 【发布时间】:2014-07-09 21:28:32 【问题描述】:

我有一个使用 OpenFrameworks 的实时 3d 程序,它在正常条件下在单线程上以 60 fps 的速度轻松运行。我有第二个辅助线程,它在工作时会导致我的主线程更新率下降并间歇性停止。

为了调试情况,我尝试通过以下方式隔离问题:

    在我的测试条件下,主线程做的工作相对较少,辅助线程运行时达到2000fps。

    第二个线程在一个连续循环中运行,并尝试通过以下方式加载一个大的(20Meg)xml文件

    while (true) 
    
        ofXml test;
        test.load("bigfile.xml");
    
    

    主线程和辅助线程之间没有以编程方式共享资源,并且两个线程中都没有锁/互斥锁。

分析似乎给了我一个可能的答案,看起来辅助线程上的堆分配和释放可能会淹没堆分配器,因此主线程的分配/释放速度正在减慢。

我使用了一个采样分析器“,非常困”,先分析我的主线程 30 秒,而辅助线程暂停,然后恢复。

在辅助线程挂起的情况下运行时,top Exclusive%函数如下,看看栈中new所用的时间:

现在在辅助线程处于活动状态时同样运行:

这似乎表明std::string 分配正在被辅助线程中的堆分配减慢,这可能是导致减慢和停滞的原因。这听起来正确吗? ,或者我可能遗漏了什么。在我尝试在没有std::string 的情况下重写我的代码之前,我想确保我的分析是正确的。

【问题讨论】:

也许您的代码使用 std::string 效率低下。尽可能通过 const 引用传递,尽可能重用字符串实例,更喜欢 += 来连接字符串而不是 + 或 stringstream。 @neil 有可能,但我不太担心,因为没有第二个线程,性能非常好。根据分析器,花费的时间占运行时间的百分比从大约 30% 增加到 60% 首先:您是在调试版还是发布版中对此进行测试?如果不发布版本,请执行此操作。是的,在调用期间的某个时刻,堆可能是一种资源,一次只能由一个线程访问。也可能是其他因素。不研究你的 xml 解析框架的代码,谁知道... 您也可以尝试不同的分配器,例如 tcmalloc。 @skimon 你为什么不担心?更少的堆使用量 = 更快,对吧? 【参考方案1】:

由于它允许您查看辅助线程上的各个调用堆栈,因此您可以查看这些堆栈。例如,您展示的那个说超过 20% 的时间都在重新分配字符串的过程中,可能是为了增加它们。如果您还查看其他堆栈示例,我敢打赌它们也在增长字符串的过程中(只是不在new 中)。如果是这样,这意味着在增长字符串上花费了更高的百分比。如果是这样,您可以采取任何措施来增加默认字符串分配或按大小增长应该会有所帮助。

(顺便说一句,您可以从中看出独占时间没有帮助。包含时间是您所需要的,但即使这样也不像简单地检查堆栈样本那么有用,因此您可以了解它为什么正在做它正在做的事情。 这就是this technique 如此有效的原因。 )

【讨论】:

以上是关于可能由于 std::string 堆分配而受文件解析线程影响的性能?的主要内容,如果未能解决你的问题,请参考以下文章

MISRA C ++(规则18-4-1)和动态内存分配 - 是否允许使用std :: string?

清理堆分配对象的良好做法或约定?

为未初始化的std :: string变量分配了多少内存?

C ++如何在堆栈上动态分配内存?

带有自定义分配器的 std::string

为啥 g++ 不关心初始化列表分配给 (const std::string&) a (std::string)?和其他怪异[关闭]