我创建了代码,以查看我的静态压缩方法执行所需的速度,我注意到第一次执行耗时8,500,000纳秒,第二次执行耗时约一半,然后所有执行都在0纳秒处执行。为什么?
private void CheckPerformance()
{
while (KeepRunning)
{
//generates a complex random 500 character string
string text = GenerateString(500, 4);
DateTime beginTime = DateTime.Now;
byte[] bytes = Compress(text); // < - timing this
long elapsedTicks = DateTime.Now.Ticks - beginTime.Ticks;
Console.WriteLine(" {0:N0} nanoseconds", elapsedTicks * 100);
//sleep for 5 seconds
Thread.Sleep(5000);
}
}
public static byte[] Compress(string text)
{
using (MemoryStream output = new MemoryStream())
{
using (DeflateStream ds = new DeflateStream(output, CompressionMode.Compress))
{
using (StreamWriter writer = new StreamWriter(ds, Encoding.UTF8))
{
writer.Write(text);
}
}
return output.ToArray();
}
}
在DateTime.Now
每秒约10次(可以根据硬件和软件设置)获取更新,但不要引用我在此。这也很慢,因为它需要弄清楚系统所在的时区。UtcNow
速度更快,但仍会缓存一会儿。因此,它可能在后续调用中使用缓存的版本。
StopWatch
而是使用它来进行更精确的测量。StopWatch
通过使用硬件来使用高精度。您可以使用进行检查Stopwatch.IsHighResolution
。
using System.Diagnostics;
Stopwatch sw = new Stopwatch();
sw.Start();
// code to benchmark
sw.Stop();
让我们看看您是否获得了相同的指标。
编辑
虽然您的方法确实需要进行JIT编译,但是差异不会归因于JIT编译,因为它只会被JIT编译一次(不总是如此,但在您的情况下将是一次),然后再使用。因此,只有第一个呼叫需要更长的时间,后续的呼叫应该相同。要抛弃此假设,只需Compress
在基准测试阶段之外调用一次即可对它进行JIT编译。然后对其进行基准测试,现在将不会进行JIT编译,并且DateTime
由于已被缓存,因此仍会为您提供随机结果。
注意:JIT编译器不一定总是将整个方法编译为机器代码,而是仅在执行通过代码时才进行编译。因此,如果您具有if语句,则在执行通过该块之前,可能不会编译这些块。但是您的if语句不存在,因此这就是将JIT编译一次的原因。
此外,我们不能放心地说这是由于JIT编译引起的,因为可能Compress
已经内联了方法,但是在您的情况下,由于您最有可能启用了调试器,因此很可能没有内联,因此将禁用JIT优化。
尝试使用以下代码,即使执行相同的代码,您也会注意到它给出了经过时间的随机结果:
for (int i = 0; i < 1000; i++)
{
DateTime beginTime = DateTime.UtcNow;
var sw = Stopwatch.StartNew();
while (sw.ElapsedTicks < 100)
{
Console.WriteLine("*");
}
long elapsedTicks = DateTime.UtcNow.Ticks - beginTime.Ticks;
Console.WriteLine(" {0:N0} nanoseconds", elapsedTicks * 100);
}
在我的系统上,如果我将此行更改为sw.ElapsedTicks < 2050
,则始终会报告非零差异。这意味着在附近会有什么时候DateTime.Now
获得一个新值,而不是使用缓存的值。
总之,我不认为JIT编译是您要注意的解释。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句