匿名メソッドの実装

delegateと通常メソッドの比較は過去に取り上げましたが、今回は、それが目的ではありません。

using System;

delegate bool F(int x, int y);

static class Program {
    static bool less (int x, int y) {
        return x < y;
    }

    public static void Main () {
        DateTime t0;

        t0 = DateTime.Now;
        for (int i = 0; i < 1000000000; ++i)
            less (i, i);
        Console.WriteLine (DateTime.Now - t0);

        F lt = delegate (int x, int y) { return x < y; };
        t0 = DateTime.Now;
        for (int i = 0; i < 1000000000; ++i) 
            lt (i, i);
        Console.WriteLine (DateTime.Now - t0);
    }
}

/* mono --optimize=all
00:00:02.9370000
00:00:14.5000000
 */

5倍くらい遅い・・・。

で、Nemerleで書いた同等なコード。

using System;

module M {
    less (x : int, y : int) : bool {
        x < y
    }

    Main () : void {
        def t0 = DateTime.Now;
        for (mutable i = 0; i < 1000000000; ++i)
            less (i, i);
        Console.WriteLine (DateTime.Now - t0);

        def lt = fun (x, y) { x < y }

        def t0 = DateTime.Now;
        for (mutable i = 0; i < 1000000000; ++i)
            lt (i, i);
        Console.WriteLine (DateTime.Now - t0);
    }
}

/* mono --optimize=all
00:00:02.9530000
00:00:06.0940000
 */

匿名メソッドが遅いのは一緒ですが、通常メソッドの半分くらいのパフォーマンスが出ています。Nemerleコンパイラが優秀でバリバリに最適化が掛かっているのでしょうか? そうではなく、実はNemerleの匿名メソッドはdelegateではなく独自のFunctionクラスを使っているのでした。(^^;

monoで実験しましたが、これがMS.NETになってもdelegateと通常メソッドの速度比は変わりません。(パフォーマンス自体は倍くらい良くなりますけどね)

このような結果を見ると、C#にももーちょっと軽量な匿名メソッドの仕組みが欲しいですね。