几年前,我注意到当时.Net DateTime类仅以10-15毫秒的增量变化。这恰好与我所理解的windows中线程上下文的典型持续时间相吻合(这就是为什么线程的睡眠时间从来不会少于这一点)。那里公开的低分辨率窗口时钟真的是在线程上下文开关上精确更新的吗?它们可以作为一种廉价而肮脏的方法来检测上下文切换吗?
发布于 2013-10-31 18:06:43
事实上,我会给出一个实际的答案:
那里公开的低分辨率窗口时钟真的是在线程上下文开关上精确更新的吗?
不-你倒过来了。低分辨率的Windows时钟可能会导致上下文的改变,例如。如果有超时超时的API调用,或者睡眠()调用过期。
它们可以作为一种廉价而肮脏的方法来检测上下文切换吗?
不,因为上下文开关可能不会发生在每个定时器中断上,并且经常发生在所有其他硬件中断和API调用上。
发布于 2013-10-31 18:57:58
你做了几个无效的或者至少是毫无根据的假设。
首先,假设用于更新.NET的DateTime.Now限制为15 ms,这是Windows的限制。可能是,但可能不是。
假设Thread.Sleep()的分辨率与DateTime.Now有某种关系。事实并非如此。您还假设15 ms的最低睡眠是Windows的限制。事实并非如此。
此外,本声明的最后一部分是:
这恰好与我所理解的windows中线程上下文的典型持续时间相吻合(这就是为什么线程的睡眠时间从来不会少于这一点)。
完全是假的。线程可以放弃剩余的时间,这意味着可以安排另一个线程在这段时间内执行。即使在.NET程序中,线程也可以睡眠不到15 ms。
更重要的是,DateTime.Now和用于进行上下文切换的机制几乎是完全无关的。DateTime.Now返回的值可能甚至不会更新,除非您请求它,就像Stopwatch类不维护Elapsed字段一样,而是计算请求时所用的时间。
因此,不可能使用时钟来检测上下文切换。
而且,事实证明,DateTime.Now分辨率为15毫秒的神话是错误的。该方案表明:
var results = new List<double>();
var startTime = DateTime.Now;
var endTime = startTime.AddSeconds(10);
var lastTime = startTime;
var nowTime = startTime;
while (nowTime < endTime)
{
nowTime = DateTime.Now;
if (nowTime != lastTime)
{
results.Add((nowTime - lastTime).TotalMilliseconds);
lastTime = nowTime;
}
}
Console.WriteLine("Total changes = {0}", results.Count);
var avg = results.Average();
var min = results.Min();
var max = results.Max();
Console.WriteLine("Min: {0}, Max: {1}, Avg: {2}", min, max, avg);该程序在一个紧循环中检查DateTime.Now 10秒,并在返回的值发生变化时向列表中添加一个项。对于我来说,典型的运行会产生非常类似于以下内容的输出:
Total changes = 9980
Min: 0.9999, Max: 19.998, Avg: 1.00210418837676所以它在10,000毫秒内进行了9,980次更新。在我看来,似乎只有一次没有更新每毫秒。这可能是因为线程在此期间被交换掉了。
我经常得到:
Total changes = 10000
Min: 1, Max: 1, Avg: 1这意味着时钟每毫秒更新一次。
https://stackoverflow.com/questions/19713417
复制相似问题