【发布时间】:2013-09-07 05:38:40
【问题描述】:
我正在研究一个解析器组合器库,并发现了一些我无法解释的行为。我第一次运行组合器时,它的运行速度比我第二次运行它慢得多。我用这个小应用程序重新发布了这个行为(在优化的情况下运行发布)
let (>>=) first callback state =
let reply = first state
callback reply state
let time f =
let start = System.DateTime.Now
f()
printfn "%s" ((System.DateTime.Now - start).ToString())
[<EntryPoint>]
let main args =
let x1 state = "foo"
let compound =
x1 >>= fun i ->
x1 >>= fun j ->
x1 >>= fun a ->
x1 >>= fun b ->
x1 >>= fun c ->
x1 >>= fun d ->
x1 >>= fun e ->
x1 >>= fun f ->
x1 >>= fun j ->
fun _ -> [i;j;a;b;c;d;e;f]
time (fun () -> compound "a" |> ignore)
time (fun () -> compound "b" |> ignore)
time (fun () -> compound "c" |> ignore)
0
运行这个输出我得到
00:00:00.0090009
00:00:00.0010001
00:00:00
为什么第一次迭代比第二次或第三次慢很多?
编辑,所以我也在 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# 在这里更快
【问题讨论】:
-
第一次快还是第二次快?您在原始问题中都说明了。
-
抱歉,第一个比较慢。我会更新问题
-
可能与编译器预加载字节码有关?第三次和第二次一样吗?
-
@mydogisbox,是的,所有后续时间都与第二次一样快。
标签: f#