我想获得最大计数我必须执行一个循环,它需要x毫秒才能完成.
例如.
int GetIterationsForExecutionTime(int ms)
{
int count = 0;
/* pseudocode
do
some code here
count++;
until executionTime > ms
*/
return count;
}
Run Code Online (Sandbox Code Playgroud)
我如何完成这样的事情?
Eri*_*ert 28
我想获得最大计数我必须执行一个循环,它需要x毫秒才能完成.
首先,根本不要这样做.如果你需要等待一定的毫秒数,请不要忙于等待循环.相反,启动计时器并返回.当计时器滴答时,让它调用一个从你离开的地方恢复的方法.该Task.Delay方法可能是一个很好的使用方法; 它会为您处理计时器详细信息.
如果您的问题实际上是关于如何计算某些代码所花费的时间,那么您需要的不仅仅是一个好的计时器.获得准确的时间安排有很多艺术和科学.
首先,你应该总是使用Stopwatch,永远不要使用DateTime.Now这些时间.秒表设计为高精度计时器,用于告诉您经过了多长时间.DateTime.Now是一个低精度计时器,告诉你是否是时候观看神秘博士了.你不会用挂钟来计时奥运会; 你可以使用最高精度的秒表,你可以得到你的手.所以使用为您提供的那个.
其次,您需要记住C#代码是及时编译的.因此,由于分析环路调用的代码的抖动成本,第一次通过循环可能比后续每个时间贵几百或几千倍.如果您打算测量循环的"温暖"成本,那么您需要在开始计时之前运行循环一次.如果您打算测量包括jit时间在内的平均成本,那么您需要确定合理数量的试验次数,以便平均值正常运行.
第三,你需要确保在跑步时没有佩戴任何铅块.调试时切勿进行性能测量.这样做的人数惊人.如果您在调试器中,则运行时可能会与调试器来回交谈,以确保您获得所需的调试体验,并且该聊天需要时间.抖动产生的代码比通常情况更糟,因此您的调试体验更加一致.垃圾收集器的收集性较低.等等.始终在调试器外部运行性能测量,并启用优化.
第四,请记住,虚拟内存系统的成本与抖动相似.如果您已经在运行托管程序,或者最近运行过一个程序,那么您需要的CLR页面可能"很热" - 已经在RAM中 - 它们很快.如果没有,那么页面可能是冷的,在磁盘上,并且需要被页面故障.这可以极大地改变时间.
第五,请记住,抖动可以进行您不期望的优化.如果你试着时间:
// Let's time addition!
for (int i = 0; i < 1000000; ++i) { int j = i + 1; }
Run Code Online (Sandbox Code Playgroud)
抖动完全在其删除整个循环的权利范围内.它可以意识到循环不计算程序中任何其他地方使用的值,并将其完全删除,给它一个零时间.它会这样吗?也许.也许不吧.这取决于抖动.您应该测量实际代码的性能,其中计算的值实际上以某种方式使用; 然后,抖动将知道它无法优化它们.
第六,垃圾收集器可以抛弃产生大量垃圾的测试时间.假设你有两个测试,一个产生大量垃圾,一个产生一点点.第一次测试产生的垃圾收集的成本可以"收取"到运行第二次测试所花费的时间,如果幸运的话,第一次测试设法在没有收集的情况下运行但第二次测试触发一次.如果您的测试产生大量垃圾,那么考虑(1)我的测试是否真实?对不切实际的程序进行性能测量没有任何意义,因为你无法对真实程序的表现做出很好的推断.(2)我应该将垃圾收集的费用计入生产垃圾的测试中吗?如果是这样,那么请确保在测试完成之前强制完整收集.
第七,您在多线程,多处理器环境中运行代码,其中线程可以随意切换,并且线程量(操作系统将给予另一个线程直到您的机会再次运行的时间量)是关于的16毫秒.16毫秒是大约五千万个处理器周期.如果线程切换发生在您尝试测量的数百万个处理器周期之一内,那么提供精确的亚毫秒操作时序可能会非常困难.考虑到这一点.
Phi*_*rie 14
var sw = new Stopwatch();
sw.Start();
...
long elapsedMilliseconds = sw.ElapsedMilliseconds;
Run Code Online (Sandbox Code Playgroud)
您也可以使用秒表类:
int GetIterationsForExecutionTime(int ms)
{
int count = 0;
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
do
{
// some code here
count++;
} while (stopwatch.ElapsedMilliseconds < ms);
stopwatch.Stop();
return count;
}
Run Code Online (Sandbox Code Playgroud)