Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/regex/18.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
C#匿名递归与Y-组合器性能_C#_Performance_Functional Programming_Anonymous Recursion - Fatal编程技术网

C#匿名递归与Y-组合器性能

C#匿名递归与Y-组合器性能,c#,performance,functional-programming,anonymous-recursion,C#,Performance,Functional Programming,Anonymous Recursion,下面是匿名递归的函数和测试。第一个是真正的Y-combinator,看起来很好,很简单,但是速度很慢。执行1百万次迭代需要1000毫秒。第二个是非常丑陋的,因为c(c,项),但工作速度比第一个快两倍 我需要使我的代码更简单、更灵活、更稳定(如果需要递归调用,不要创建一组函数等) 有没有更好的方法来组织匿名递归 delegate Action<T> Continuation<T>(Continuation<T> r); [TestMethod]

下面是匿名递归的函数和测试。第一个是真正的Y-combinator,看起来很好,很简单,但是速度很慢。执行1百万次迭代需要1000毫秒。第二个是非常丑陋的,因为c(c,项),但工作速度比第一个快两倍

我需要使我的代码更简单、更灵活、更稳定(如果需要递归调用,不要创建一组函数等)

有没有更好的方法来组织匿名递归

delegate Action<T> Continuation<T>(Continuation<T> r);

    [TestMethod]
    public void TestMethod()
    {
        IObject root = BuildComposite();

        Performance.Measure(1000000, () =>
                {
                    Apply(root, h => t =>
                    {
                        foreach (IObject item in t.Children)
                        {
                            //Console.WriteLine(item.Name);
                            h(item);
                        }
                    });
                }, "Time ");
    }

    private static void Apply(IObject root, Func<Action<IObject>, Action<IObject>> g)
    {
        Continuation<IObject> action = c => thing => { g(c(c))(thing); };

        Action<IObject> target = action(action);

        target(root);
    }

delegate void Continuation<T>(Continuation<T> r, T n);

    [TestMethod]
    public void TestMethod()
    {
        var root = BuildComposite();

        Performance.Measure(1000000, () =>
        {
            Apply(root, (c, thing) =>
            {
                foreach (var item in thing.Children)
                {
                    //Console.WriteLine(item.Name);
                    c(c, item);
                }
            });
        },"Time");
    }


    void Apply(IObject root, Continuation<IObject> f)
    {
        f(f, root);
    }
委托动作延续(延续r);
[测试方法]
公共void TestMethod()
{
IObject root=BuildComposite();
性能度量(1000000,()=>
{
应用(根,h=>t=>
{
foreach(t.Children中的IOObject项)
{
//Console.WriteLine(项目名称);
h(项目1);
}
});
}“时间”);
}
私有静态无效应用(IObject root,Func g)
{
继续动作=c=>thing=>{g(c(c))(thing);};
行动目标=行动(行动);
目标(根);
}
代表无效延续(延续r,T n);
[测试方法]
公共void TestMethod()
{
var root=BuildComposite();
性能度量(1000000,()=>
{
应用(根,(c,事物)=>
{
foreach(thing.Children中的变量项)
{
//Console.WriteLine(项目名称);
c(c,项目);
}
});
}“时间”);
}
无效应用(IOObject根,续f)
{
f(f,根);
}

这件事昨天引起了我的兴趣。我做了一些测试,这是我的尝试,我有一些加速。委托越简单,进行的速度就越快,但一些备忘录起到了作用

Time test   1   542 69%
Time test   2   377 99%
Time test   3   558 67%
Time test   4   505 74%
Time test   5   372 100%
Time test   6   374 99%
Time test   7   452 82%
LinqPad的测试代码

void Main()
{
    foreach(var t in typeof(test).Assembly.GetTypes().Where(t => t.IsSubclassOf(typeof(test))))
        ((test)(Activator.CreateInstance(t))).TestMethod();
}

private abstract class test
{
    public abstract void TestMethod();
}

private class test1 : test
{

    delegate Action<T> Continuation<T>(Continuation<T> r);

    //[TestMethod]
    //The fixed point operator, very slow also.
    public override void TestMethod()
    {
        IObject root = BuildComposite();

        Performance.Measure(1000000, () =>
        {
            Apply(root, h => t =>
            {
                foreach (IObject item in t.Children)
                {
                    //Console.WriteLine(item.Name);
                    h(item);
                }
            });
        }, "Time " + this.GetType().Name);
    }

    private static void Apply(IObject root, Func<Action<IObject>, Action<IObject>> g)
    {
        Continuation<IObject> action = c => thing => { g(c(c))(thing); };

        Action<IObject> target = action(action);

        target(root);
    }

}

private class test2 : test
{

    delegate void Continuation<T>(Continuation<T> r, T n);

    //[TestMethod]
    //Without curry, curring makes things go slow.
    public override void TestMethod()
    {
        var root = BuildComposite();

        Performance.Measure(1000000, () =>
        {
            Apply(root, (c, thing) =>
            {
                foreach (var item in thing.Children)
                {
                    //Console.WriteLine(item.Name);
                    c(c, item);
                }
            });
        }, "Time " + this.GetType().Name);
    }

    void Apply(IObject root, Continuation<IObject> f)
    {
        f(f, root);
    }

}

private class test3 : test
{

    //[TestMethod]
    //Another common definition found on web, this is worse of then all.
    //https://stackoverflow.com/questions/4763690/alternative-y-combinator-definition
    public override void TestMethod()
    {
        var root = BuildComposite();

        Performance.Measure(1000000, () =>
        {
            Y<IObject, int>(f => thing =>
            {
                foreach (var item in thing.Children)
                {
                    //Console.WriteLine(item.Name);
                    f(item);
                }
                return 0;
            })(root);
        }, "Time " + this.GetType().Name);
    }

    public delegate TResult SelfApplicable<TResult>(SelfApplicable<TResult> r);

    public static TResult U<TResult>(SelfApplicable<TResult> r)
    {
        return r(r);
    }

    public static Func<TArg1, TReturn> Y<TArg1, TReturn>(Func<Func<TArg1, TReturn>, Func<TArg1, TReturn>> f)
    {
        return U<Func<TArg1, TReturn>>(r => arg1 => f(U(r))(arg1));
    }

}

private class test4 : test
{

    //[TestMethod]
    //Simpler definition, taken from this SO.
    //This uses inherent compiler recursion, lets see if it speed things up.
    //https://stackoverflow.com/questions/4763690/alternative-y-combinator-definition
    public override void TestMethod()
    {
        var root = BuildComposite();

        Performance.Measure(1000000, () =>
        {
            Y<IObject, int>(f => thing =>
            {
                foreach (var item in thing.Children)
                {
                    //Console.WriteLine(item.Name);
                    f(item);
                }
                return 0;
            })(root);
        }, "Time " + this.GetType().Name);
    }

    public static Func<TArg1, TReturn> Y<TArg1, TReturn>(Func<Func<TArg1, TReturn>, Func<TArg1, TReturn>> f)
    {
        return f(n => Y(f)(n));
    }

}

private class test5 : test
{

    //[TestMethod]
    //Simple way to recurse, is also the fastest
    //but then its no more an anonymous lambda.
    //This defeats the game purpose.
    public override void TestMethod()
    {
        var root = BuildComposite();

        Action<IObject> a = null;
        a = thing =>
            {
                foreach (var item in thing.Children)
                {
                    //Console.WriteLine(item.Name);
                    a(item);
                }
            };

        Performance.Measure(1000000, () =>
        {
            a(root);
        }, "Time " + this.GetType().Name);
    }

}

private class test6 : test
{

    //[TestMethod]
    //Reference test, direct method call
    //There should be no way to get faster than this.
    public override void TestMethod()
    {
        var root = BuildComposite();

        Performance.Measure(1000000, () =>
        {
            a(root);
        }, "Time " + this.GetType().Name);
    }

    public static void a(IObject thing)
    {
        foreach (var item in thing.Children)
        {
            //Console.WriteLine(item.Name);
            a(item);
        }
    }

}

private class test7 : test
{

    //[TestMethod]
    //Lets try some memoization.
    public override void TestMethod()
    {
        var root = BuildComposite();

        Performance.Measure(1000000, () =>
        {
            Y<IObject, int>.Combinator(f => thing =>
            {
                foreach (var item in thing.Children)
                {
                    //Console.WriteLine(item.Name);
                    f(item);
                }
                return 0;
            })(root);
        }, "Time " + this.GetType().Name);
    }

    private class Y<TArg1, TReturn>
    {
        public static Func<TArg1, TReturn> Combinator(Func<Func<TArg1, TReturn>, Func<TArg1, TReturn>> f)
        {
            return f(n => 
                {
                    if (memoized == null) memoized = Combinator(f);
                    return memoized(n);
                });
        }
        private static Func<TArg1, TReturn> memoized;
    }

}

private interface IObject
{
    List<IObject> Children { get; }
}

private class CObject : IObject
{
    private int lvl;
    public CObject(int lvl)
    {
        this.lvl = lvl;
    }
    public List<IObject> Children 
    { 
        get
        {
            var l = new List<IObject>() { BuildComposite(lvl + 1) }; 
            if (lvl > 2) l.Clear();
            return l;
        }
    }
}

private static IObject BuildComposite()
{
    return new CObject(0);
}

private static IObject BuildComposite(int lvl)
{
    return new CObject(lvl);
}

private class Performance
{
    public static void Measure(int count, Action a, string msg)
    {
        using(new WallClock(msg))
            Enumerable.Range(1, count).ToList().ForEach(_ => a());
    }
}

private class WallClock : IDisposable
{   
    private string name;
    private Stopwatch w;
    public WallClock(string name)
    {
        this.name = name;
        w = Stopwatch.StartNew();
    }
    public void Dispose()
    {
        w.Stop();
        Console.WriteLine(name + " : " + w.ElapsedMilliseconds);
    }
}
void Main()
{
foreach(typeof(test).Assembly.GetTypes()中的var t,其中(t=>t.IsSubclassOf(typeof(test)))
((test)(Activator.CreateInstance(t)).TestMethod();
}
私有抽象类测试
{
公共抽象void TestMethod();
}
私有类test1:test
{
代表行动延续(延续r);
//[测试方法]
//定点操作符,速度也很慢。
公共重写void TestMethod()
{
IObject root=BuildComposite();
性能度量(1000000,()=>
{
应用(根,h=>t=>
{
foreach(t.Children中的IOObject项)
{
//Console.WriteLine(项目名称);
h(项目1);
}
});
},“Time”+this.GetType().Name);
}
私有静态无效应用(IObject root,Func


您是否阅读并将您的解决方案与之进行了比较?Curryfication似乎可以让作者得到一个更简单的解决方案。您可能会感兴趣(我再也没有进一步的了解)。是的,我读过。链接上的解决方案很慢谢谢,您让我想:-)