Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/fsharp/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
F# 为什么此组合器的第二次执行速度比第一次快10倍?_F# - Fatal编程技术网

F# 为什么此组合器的第二次执行速度比第一次快10倍?

F# 为什么此组合器的第二次执行速度比第一次快10倍?,f#,F#,我正在研究一个解析器组合器库,发现了一些无法解释的行为。第一次运行combinator时,它的运行速度明显慢于第二次运行。我用这个小应用程序重现了这个行为(运行带有优化的版本) 为什么第一次迭代比第二次或第三次慢得多 编辑,所以我也在C#中尝试了这个。它运行得更快,但结果相似 using System; namespace fssharp { public delegate string Parser(string state); public delegate Parse

我正在研究一个解析器组合器库,发现了一些无法解释的行为。第一次运行combinator时,它的运行速度明显慢于第二次运行。我用这个小应用程序重现了这个行为(运行带有优化的版本)

为什么第一次迭代比第二次或第三次慢得多


编辑,所以我也在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#在这里更快

即使很难我也不能确定,它是:

  • JIT:函数在第一次运行时进行JIT,然后使用已编译的版本

  • 它检测到使用相同的参数调用相同的函数,并缓存结果


  • 尝试使用其他参数调用它。如果时间不变,则为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