我正在开发一个分析实时财务数据的应用程序。目前我的主要计算周期有以下设计:
long cycle_counter=0;
while (process_data)
{
(analyse data, issue instruction - 5000 lines of straightforwasrd code with computations)
cycle_counter++;
Thread.Sleep(5);
}
当我在我的笔记本(一个Core i5)处理器上运行此应用程序时,该循环每秒运行200-205次 - 这是一种预期的(如果你不打扰为什么它每秒运行超过200次)。
但是,当我在具有2个6核Xeon处理器和24 GB快速RAM的“真实”工作站上部署应用程序,并且在大约3秒内加载Win7时,应用程序每秒运行大约67次。
我的问题是:
为什么会这样?
在这种情况下,如何影响每秒的运行次数?
有没有更好的解决方案,每秒运行200-1000次循环?我现在正在考虑删除Thread.Sleep()(我在这里使用它的方式受到了很多批评)。有12个内核,我只使用一个内核就可以解决这个问题。但是我的解决方案有些不足之处?
感谢您的想法。
答案 0 :(得分:6)
你所采取的方法根本就是打破了。轮询策略通常是一种不好的方法,任何时候你因为“我想把剩下的时间片还给操作系统”以外的原因而进行睡眠,你可能做错了。
解决问题的更好方法是:
如何使用这些属性构建队列是一个着名的问题,称为生产者/消费者问题。关于如何执行阻塞生产者 - 消费者队列的任何许多实现,有很多文章。我建议找一个现有的调试版,而不是试着写自己的;做得对可能很棘手。
答案 1 :(得分:3)
睡眠的分辨率由当前的计时器滴答间隔决定,通常为10或15毫秒,具体取决于Windows的版本。但是,可以通过发出timeBeginPeriod命令来更改此设置。请参阅this answer。
答案 2 :(得分:3)
Windows不是RTOS(实时操作系统),因此您无法准确确定线程何时恢复。 Thread.Sleep(5)
真的意味着“在5毫秒之后叫醒我”。实际的休眠时间由特定硬件决定,主要由系统负载决定。您可以尝试running your application on a higher priority解决system load
问题。
顺便说一句,System.Threading.Timer是一种更好的方法(尽管评论仍然适用)。
答案 3 :(得分:1)
检查计时器的实际频率:许多硬件计时器具有实际分辨率
65536 ticks per hour = 65536 / 3600 = 18.204 ticks per second
所谓的“18.2”常数,这就是实际计时器的分辨率 1 / 18.2 = 55 ms 的原因;在Sleep(5)
的情况下,这意味着可能是Sleep(0)
或Sleep(55)
,具体取决于整理。
答案 4 :(得分:1)
不确定这是最好的方法,而是另一种方法 尝试BlockingCollection,你在制作人中所做的只是添加和睡眠 如果需要,消费者可以选择全职工作 这仍然无法解释为什么更高功率的PC运行更少的周期。
答案 5 :(得分:1)
你可以平均每秒运行200次 吗?
var delay = TimeSpan.FromMillseconds(5);
while (process_data) {
Console.WriteLine("do work");
var now = DateTime.Now;
if (now < nextDue)
System.Threading.Thread.Sleep(nextDue - now);
nextDue = nextDue.Add(delay);
}
使用这种技术,你的循环会有点磕磕绊绊,但平均来说应该没问题,因为代码既不依赖Sleep
的分辨率也不依赖于DateTime.Now
的分辨率。
您甚至可以将此方法与计时器结合使用。