F# 为什么此组合器的第二次执行速度比第一次快10倍?
我正在研究一个解析器组合器库,发现了一些无法解释的行为。第一次运行combinator时,它的运行速度明显慢于第二次运行。我用这个小应用程序重现了这个行为(运行带有优化的版本) 为什么第一次迭代比第二次或第三次慢得多F# 为什么此组合器的第二次执行速度比第一次快10倍?,f#,F#,我正在研究一个解析器组合器库,发现了一些无法解释的行为。第一次运行combinator时,它的运行速度明显慢于第二次运行。我用这个小应用程序重现了这个行为(运行带有优化的版本) 为什么第一次迭代比第二次或第三次慢得多 编辑,所以我也在C#中尝试了这个。它运行得更快,但结果相似 using System; namespace fssharp { public delegate string Parser(string state); public delegate Parse
编辑,所以我也在C#中尝试了这个。它运行得更快,但结果相似
using System;
namespace fssharp
{
public delegate string Parser(string state);
public delegate Parser Callback(string result);
public class Combinator
{
public static Parser Combine(Parser p, Callback callback)
{
Parser r = state =>
{
var result = p(state);
return callback(result)(state);
};
return r;
}
public static string X1(string state)
{
return "foo";
}
}
class Program
{
static void Main(string[] args)
{
Parser comb = state =>
Combinator.Combine(Combinator.X1, result =>
Combinator.Combine(Combinator.X1, result2 =>
Combinator.Combine(Combinator.X1, result3 =>
Combinator.Combine(Combinator.X1, result4 =>
Combinator.Combine(Combinator.X1, result5 =>
Combinator.Combine(Combinator.X1, result6 =>
Combinator.Combine(Combinator.X1, result7 =>
Combinator.Combine(Combinator.X1, result8 =>
Combinator.Combine(Combinator.X1, result9 => s => result + result2 + result3 +result4 +result5 +result6 +result7+result8+result9)))
))))))(state);
var now = DateTime.Now;
comb("foo");
Console.WriteLine(DateTime.Now - now);
now = DateTime.Now;
comb("foo2");
Console.WriteLine(DateTime.Now - now);
}
}
}
这是打印出来的
00:00:00.0030003
00:00:00
我现在很好奇为什么C#在这里更快即使很难我也不能确定,它是:
尝试使用其他参数调用它。如果时间不变,则为2;如果时间不同,则为1第一次还是第二次快?你在原来的问题中陈述了这两个问题。对不起,第一个问题比较慢。我将更新这个问题可能与编译器预加载字节码有关?第三次的运行速度与第二次相同吗?@mydogisbox,是的,所有后续时间的运行速度都与第二次相同。已更新示例以使用不同的输入参数。听起来像是A。有没有办法事先强制JIT来验证假设?据我所知,没有办法这么做。这与虚拟机加载字节码的方式有关。摆弄ngen()@VincentHubert我已经尝试过ngen安装这个应用程序,但没什么不同。我得到了同样的结果,也可能与硬件有关。如果代码运行速度足够快,那么它可能会在CPU缓存中停留足够长的时间,以便在第二次运行时出现。如果在两次调用之间休眠()一分钟,是否会得到相同的结果?
using System;
namespace fssharp
{
public delegate string Parser(string state);
public delegate Parser Callback(string result);
public class Combinator
{
public static Parser Combine(Parser p, Callback callback)
{
Parser r = state =>
{
var result = p(state);
return callback(result)(state);
};
return r;
}
public static string X1(string state)
{
return "foo";
}
}
class Program
{
static void Main(string[] args)
{
Parser comb = state =>
Combinator.Combine(Combinator.X1, result =>
Combinator.Combine(Combinator.X1, result2 =>
Combinator.Combine(Combinator.X1, result3 =>
Combinator.Combine(Combinator.X1, result4 =>
Combinator.Combine(Combinator.X1, result5 =>
Combinator.Combine(Combinator.X1, result6 =>
Combinator.Combine(Combinator.X1, result7 =>
Combinator.Combine(Combinator.X1, result8 =>
Combinator.Combine(Combinator.X1, result9 => s => result + result2 + result3 +result4 +result5 +result6 +result7+result8+result9)))
))))))(state);
var now = DateTime.Now;
comb("foo");
Console.WriteLine(DateTime.Now - now);
now = DateTime.Now;
comb("foo2");
Console.WriteLine(DateTime.Now - now);
}
}
}
00:00:00.0030003
00:00:00