我正在寻找一种优化以下代码的方法,对于我开发的开源项目,或者通过将繁重的工作移动到另一个线程来使其更高效.
void ProfilerCommunication::AddVisitPoint(ULONG uniqueId)
{
CScopedLock<CMutex> lock(m_mutexResults);
m_pVisitPoints->points[m_pVisitPoints->count].UniqueId = uniqueId;
if (++m_pVisitPoints->count == VP_BUFFER_SIZE)
{
SendVisitPoints();
m_pVisitPoints->count=0;
}
}
当调用每个访问点时,上面的代码由OpenCover分析器(用C编写的.NET的开源代码覆盖工具)使用.互斥锁用于保护某些共享内存(在多个进程32/64位和C/C++#之间共享的64K块),当它充满时它会向主机进程发出信号.显然,对于每个仪表点而言,这都非常重,我想使影响更轻.
我正在考虑使用由上述方法推送的队列和一个线程来弹出数据并填充共享内存.
问:我可以使用C(Windows STL)中的线程安全队列 – 还是无锁队列,因为我不想用另一个问题替换一个问题?人们认为我的方法合情合理吗?
编辑1:我刚刚在include文件夹中找到concurrent_queue.h – 这可能是我的答案……?
最佳答案
好的,我会添加自己的答案 – concurrent_queue效果很好
使用这个MSDN article中描述的细节,我实现了并发队列(以及任务和我的第一个C lambda表达式:))我没有花很长时间思考,因为它是一个尖峰.
inline void AddVisitPoint(ULONG uniqueId) { m_queue.push(uniqueId); }
...
// somewhere else in code
m_tasks.run([this]
{
ULONG id;
while(true)
{
while (!m_queue.try_pop(id))
Concurrency::Context::Yield();
if (id==0) break; // 0 is an unused number so is used to close the thread/task
CScopedLock<CMutex> lock(m_mutexResults);
m_pVisitPoints->points[m_pVisitPoints->count].UniqueId = id;
if (++m_pVisitPoints->count == VP_BUFFER_SIZE)
{
SendVisitPoints();
m_pVisitPoints->count=0;
}
}
});
结果:
>没有仪器的应用= 9.3
>使用旧仪器处理程序的应用程序= 38.6
>使用新仪器处理程序的应用程序= 16.2
相关文章
转载注明原文:c – 线程安全队列是一种好方法吗? - 代码日志