我正在研究一个解析器组合库,发现了一些我无法解释的行为.我第一次运行组合器时运行速度明显慢于第二次运行组合器.我用这个小应用程序重新启动了行为(运行Release并进行了优化)
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
Run Code Online (Sandbox Code Playgroud)
运行此输出我得到
00:00:00.0090009
00:00:00.0010001
00:00:00
Run Code Online (Sandbox Code Playgroud)
为什么第一次迭代比第二次或第三次慢得多?
编辑,所以我在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);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)
打印出来
00:00:00.0030003
00:00:00
Run Code Online (Sandbox Code Playgroud)
我现在好奇为什么C#在这里更快
即使是艰难的我也无法确定,它是:
JIT:该函数在第一次运行时是JIT,然后它使用已编译的版本
它检测到使用相同参数调用相同的函数并缓存结果.
尝试使用其他参数调用它.如果时间保持不变,则为2,如果时间不同,则为1