Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/325.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 以毫秒为单位测量.net中的代码速度_C#_.net - Fatal编程技术网

C# 以毫秒为单位测量.net中的代码速度

C# 以毫秒为单位测量.net中的代码速度,c#,.net,C#,.net,我想获得执行循环所需的最大计数,以使它花费x毫秒完成 例如 int GetIterationsForExecutionTime(int ms) { int count = 0; /* pseudocode do some code here count++; until executionTime > ms */ return count; } 我如何完成这样的任务?您也可以使用该类: int-GetIt

我想获得执行循环所需的最大计数,以使它花费x毫秒完成

例如

int GetIterationsForExecutionTime(int ms)
{
    int count = 0;
    /* pseudocode 
    do
        some code here
        count++;
    until executionTime > ms
    */

    return count;
}
我如何完成这样的任务?

您也可以使用该类:

int-GetIterationForExecutionTime(int-ms)
{
整数计数=0;
秒表秒表=新秒表();
秒表。开始();
做
{
//这里有一些代码
计数++;
}while(秒表延时毫秒<毫秒);
秒表;
返回计数;
}
我想获得执行循环所需的最大计数,以使它花费x毫秒完成

首先,不要这样做。如果需要等待一定的毫秒数,请不要忙着在循环中等待。相反,启动计时器并返回。当计时器滴答作响时,让它调用一个方法,从您停止的地方继续。
Task.Delay
方法可能是一个好方法;它为您处理计时器的详细信息

如果您的问题实际上是关于如何计算某些代码所花费的时间,那么您需要的不仅仅是一个好的计时器。要获得准确的计时,有很多艺术和科学


首先,您应该始终使用秒表,并且永远不要使用日期时间。现在,这些计时应使用日期时间。秒表被设计成一个高精度计时器,用来告诉你经过了多少时间<代码>日期时间。现在是一个低精度计时器,用于告诉您是否该看医生了。你不会用挂钟来计时奥运比赛;你会用你能拿到的最高精度的秒表。因此,请使用为您提供的

其次,你需要记住C代码是及时编译的。因此,由于分析循环调用的代码的抖动成本,第一次通过循环的成本可能比以后每次都高出数百倍或数千倍。如果您打算测量循环的“热”成本,那么您需要在开始计时之前运行循环一次。如果你打算测量平均成本,包括jit时间,那么你需要决定多少次构成合理的试验次数,这样平均值才能正确计算出来

第三,你需要确保你在跑步时没有佩戴任何铅锤。调试时切勿进行性能测量。做这件事的人数量惊人。如果您在调试器中,那么运行时可能会与调试器来回对话,以确保您获得所需的调试体验,并且这种对话需要时间。抖动会产生比正常情况下更糟糕的代码,因此您的调试体验更加一致。垃圾收集器收集的攻击性较低。等等始终在调试器外部运行性能度量,并启用优化

第四,请记住,虚拟内存系统的成本与抖动的成本相似。如果您已经在运行一个托管程序,或者最近运行了一个托管程序,那么您需要的CLR页面很可能是“热的”——已经在RAM中了——它们的速度很快。如果不是,那么页面可能是冷的,在磁盘上,并且需要出现页面错误。这可以极大地改变时间安排

第五,记住抖动可以进行您意想不到的优化。如果您试图节省时间:

// Let's time addition!
for (int i = 0; i < 1000000; ++i) { int j = i + 1; }
//让我们来计时添加!
对于(int i=0;i<1000000;++i){int j=i+1;}
抖动完全在其权限范围内,可以移除整个环路。它可以实现循环不计算程序中其他任何地方使用的值,并将其完全删除,使其时间为零。是这样吗?大概也许不是。这取决于抖动。您应该度量实际代码的性能,其中计算的值实际上是以某种方式使用的;然后抖动将知道它无法优化它们

第六,垃圾收集器可以丢弃产生大量垃圾的测试计时。假设您有两个测试,一个是制造大量垃圾的测试,另一个是制造少量垃圾的测试。如果幸运的是,第一个测试能够在没有收集的情况下运行,但是第二个测试触发了收集,那么第一个测试产生的垃圾收集成本可以“计入”运行第二个测试所花费的时间。如果你的测试产生了大量的垃圾,那么考虑(1)我的测试是现实的吗?对一个不切实际的程序进行性能度量是没有任何意义的,因为你不能很好地推断出你真正的程序将如何运行。(2)我是否应该向产生垃圾的测试收取垃圾收集的费用?如果是这样,那么请确保在测试计时完成之前强制进行完整的收集


第七,您正在一个多线程、多处理器环境中运行代码,在这个环境中,线程可以随意切换,线程数量(操作系统将给另一个线程的时间量,直到您有机会再次运行)大约为16毫秒。16毫秒大约是5000万个处理器周期。如果线程切换发生在您试图测量的数百万个处理器周期中的一个周期内,那么要精确计算亚毫秒级操作的计时可能非常困难。考虑到这一点。

埃里克·利珀特的观点很好。 我已经进行了一段时间的基准测试和单元测试,我建议您应该放弃代码的每一个第一步,因为JIT编译。 因此,在使用循环和秒表的基准测试代码中,请记住将其放在循环的末尾:

                // JIT optimization.
                if (i == 0)
                {
                    // Discard every result you've collected.
                    // And restart the timer.
                    stopwatch.Restart();
                }

DateTime.Now
具有毫秒分辨率(尽管有些不精确),您可以通过
(DateTime.Now-startTime).totalmillimes获得大致的计时。您需要精确到什么程度?偏差大约为-100/+100毫秒。
DateTime。现在
在mos上精确到大约1/64秒
// Let's time addition!
for (int i = 0; i < 1000000; ++i) { int j = i + 1; }
                // JIT optimization.
                if (i == 0)
                {
                    // Discard every result you've collected.
                    // And restart the timer.
                    stopwatch.Restart();
                }