C# 我的静态方法似乎在重用时执行得更快。为什么?它会被缓存吗?
我创建了代码来查看静态压缩方法的执行速度,我注意到第一次执行需要850万纳秒,第二次大约需要一半,之后的所有操作都以0纳秒的速度执行。为什么?C# 我的静态方法似乎在重用时执行得更快。为什么?它会被缓存吗?,c#,performance,time,compression,benchmarking,C#,Performance,Time,Compression,Benchmarking,我创建了代码来查看静态压缩方法的执行速度,我注意到第一次执行需要850万纳秒,第二次大约需要一半,之后的所有操作都以0纳秒的速度执行。为什么? private void CheckPerformance() { while (KeepRunning) { //generates a complex random 500 character string string text = GenerateString(500, 4);
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();
}
}
private void CheckPerformance()
{
同时(继续修剪)
{
//生成一个500个字符的复杂随机字符串
字符串文本=生成器字符串(500,4);
DateTime beginTime=DateTime.Now;
字节[]字节=压缩(文本);//<-计时
long elapsedTicks=DateTime.Now.Ticks-beginTime.Ticks;
Console.WriteLine(“{0:N0}纳秒”,elapsedTicks*100);
//睡5秒钟
睡眠(5000);
}
}
公共静态字节[]压缩(字符串文本)
{
使用(MemoryStream输出=新的MemoryStream())
{
使用(DeflateStream ds=新的DeflateStream(输出,CompressionMode.Compress))
{
使用(StreamWriter=newstreamwriter(ds,Encoding.UTF8))
{
作者:写(文本);
}
}
返回输出.ToArray();
}
}
日期时间。现在每秒更新10次左右,但不要引用我的话(可能取决于硬件和软件设置)。它的速度也很慢,因为它需要计算出系统所在的时区UtcNow
速度更快,但仍会被缓存一段时间。因此,它可以在后续调用中使用缓存版本
使用秒表进行更精确的测量<代码>秒表利用硬件实现高精度。您可以使用秒表.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);
}
for(int i=0;i<1000;i++)
{
DateTime beginTime=DateTime.UtcNow;
var sw=Stopwatch.StartNew();
而(西南ElapsedTicks<100)
{
Console.WriteLine(“*”);
}
long elapsedTicks=DateTime.UtcNow.Ticks-beginTime.Ticks;
Console.WriteLine(“{0:N0}纳秒”,elapsedTicks*100);
}
在我的系统上,如果我将该行更改为sw.ElapsedTicks<2050
,则始终存在非零的差异。这意味着当DateTime.Now
获取一个新值而不是使用缓存的值时,就会出现这种情况
总之,我不认为JIT编译可以解释您所注意到的问题。日期时间。现在,每秒更新10次左右,但不要引用我的话(可能取决于硬件和软件设置)。它的速度也很慢,因为它需要计算出系统所在的时区
UtcNow
速度更快,但仍会被缓存一段时间。因此,它可以在后续调用中使用缓存版本
使用秒表进行更精确的测量<代码>秒表利用硬件实现高精度。您可以使用秒表.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);
}
for(int i=0;i<1000;i++)
{
DateTime beginTime=DateTime.UtcNow;
var sw=Stopwatch.StartNew();
当(