我创建了代码,以查看我的静态压缩方法执行的速度,我注意到第一个执行需要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汇编的一次(并非总是总是,但在您的情况下它将是一次),然后再利用。因此,只有第一个呼叫应花费更长的时间,并且随后的呼叫应相同。要丢弃此假设,只需在基准测试阶段之外调用Compress
,就可以编译JIT。然后基准测试,现在不会发生JIT汇编,DateTime
仍然会给您随机结果。
注意:JIT编译器不一定总是将整个方法汇编为机器代码,而仅当执行通过代码时。因此,如果您有if语句,则可能不会汇编块,直到执行通过块。但是您的没有语句,所以这就是为什么它将被汇编一次。
此外,我们不能自信地说,这是由于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汇编是您注意到的内容的解释。
第一次击打时,它会被打在一起。所以这需要时间。不知道为什么第二次和第三次有所不同。