我已经看了很多,似乎无法找到我想要的东西,但让我首先强调我不寻找高精度的睡眠功能
以下是我要解决的问题的背景:
我制作了一个内存映射库,它的运行方式与命名管道非常相似。您可以将字节放入其中,从中获取字节数,并查询可读/写的字节数,这些都是好事。
使用它的快速(大多数)进程通信平均为4GB / s,如果它们传递的块大小为8KB或更大。当你接近512B的块大小时,性能下降到大约300MB / s。
问题:
非常偶尔,在负载很重的服务器上,会出现非常大的延迟时间(超过5秒)。我对此问题的原因的运行理论是,当发生大型传输(大于映射内存的大小)时,写入数据的进程将严格轮询以等待在已实现的循环缓冲区中有更多空间可用在内存映射之上。没有呼叫睡眠,因此轮询过程可能无缘无故地占用CPU!问题是即使是最小的睡眠呼叫(1ms)也绝对会破坏性能。 memmap大小为16KB,因此如果它每16KB睡眠1ms,性能将下降到16MB / s的最佳情况。
解决方案:
我想要一个可以放弃CPU的函数,但不会限制它何时被操作系统重新安排(在本例中为Windows 7)。
有没有人有任何明智的选择?/有谁知道这样的功能是否存在?
感谢。
答案 0 :(得分:3)
根据MSDN文档,在XP或更新版本上,当您以超时0调用Sleep
时,将产生相同优先级的其他进程。
值为零会导致线程放弃其余部分 时间片到任何其他准备好的相同优先级的线程 跑。如果没有其他具有相同优先级的线程准备好运行,那么 函数立即返回,线程继续执行。
http://msdn.microsoft.com/en-us/library/windows/desktop/ms686298(v=vs.85).aspx
另一个需要更多工作但可以更可靠地工作的选项是在生产者和消费者流程之间共享事件句柄。您可以使用CreateEvent
创建活动,使用DuplicateHandle
将其加入其他流程。当生成器填充缓冲区时,它将在事件句柄上调用ResetEvent
并使用它调用WaitForSingleObject
。当消费者从完整的共享缓冲区中删除了一些数据时,它将调用SetEvent
,这将唤醒正在等待WaitForSingleObject
的生产者。
答案 1 :(得分:1)
std::this_thread::yield()
可能会做你想要的。我相信它在大多数实现中只调用Sleep为0。
答案 2 :(得分:1)
您需要SwitchToThread()
功能(只有 才会放弃其时间片,如果其他内容可以运行), 不 { {1}}(即使没有别的东西可以运行,将放弃其时间片)。
如果您正在编写旨在利用超线程的代码,Sleep(0)
也可能会为您做些什么,但我怀疑这会有所帮助。
答案 3 :(得分:1)
你错误地假设二元选择。你现在总是忙着等待,因为睡觉总是一个坏主意。
更好的解决方案是尝试几次而不睡觉。如果仍然失败(因为地图已满,而另一个线程没有运行),那么您可以发出真正的睡眠。这将是非常罕见的平均你将睡眠微秒。您甚至可以检查实时时钟(RDTSC
)以确定您在放弃时间片之前花了多长时间等待。
答案 4 :(得分:0)
如果您在.Net下运营,则可以查看Thread::Yield()
方法。
它可能会或可能不会对您的特定方案有所帮助,但这是正确的方式通知调度程序您要放弃剩余的时间片。
如果您在pre-.Net环境中运行(如果您使用的是Windows 7),则可以查看Win32 SwitchToThread()
函数。