我的静态方法似乎通过重用执行得更快。为什么?它会被缓存吗?
My static method seems to perform faster with reuse. Why? Does it become cached?
我创建了代码来查看我的静态压缩方法的执行速度,我注意到第一次执行需要 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
方法可能是 inlined 但在您的情况下,它很可能没有内联,因为您很可能启用了调试器,因此将禁用 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 编译是对您注意到的内容的解释。
当你第一次击中它时,它会感到紧张。所以这需要时间。不确定为什么第二次和第三次不同。
我创建了代码来查看我的静态压缩方法的执行速度,我注意到第一次执行需要 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
方法可能是 inlined 但在您的情况下,它很可能没有内联,因为您很可能启用了调试器,因此将禁用 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 编译是对您注意到的内容的解释。
当你第一次击中它时,它会感到紧张。所以这需要时间。不确定为什么第二次和第三次不同。