在C#中的代表意外表现不佳 [英] Unexpected poor performance of delegates in C#

查看:90
本文介绍了在C#中的代表意外表现不佳的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我张贴早些时候href=\"http://stackoverflow.com/questions/10613728/run-dynamically-compiled-c-sharp-code-at-native-speed-how\">这个问题有关动态编译的C#代码,答案已经导致另一个问题。



一个建议是,我使用的代表,我试图和他们工作得很好。然而,他们是在约8.4 X是不同于直接调用,这是没有意义的慢钳工。



什么是错的代码?



我的结果,.NET 4.0,64位,exe文件直接运行:62,514,530

 公开静态INT执行(int i)以{回报我* 2; } 

私人无效button30_Click(对象发件人,EventArgs五)
{
CSharpCodeProvider富=新CSharpCodeProvider();

VAR解析度= foo.CompileAssemblyFromSource(
新System.CodeDom.Compiler.CompilerParameters()
{
GenerateInMemory = TRUE,
CompilerOptions = @ /优化,
},
@公共类FooClass {公共静态INT执行(int i)以{回报我* 2;}}
);

变种类型= res.CompiledAssembly.GetType(FooClass);
VAR OBJ = Activator.CreateInstance(类型);
VAR方法= type.GetMethod(执行);
INT I = 0,T1 = Environment.TickCount,T2;
// VAR输入=新对象[] {2};

//为(INT J = 0; J<千万; J ++)
// {
//输入[0] = j的;
// VAR输出= method.Invoke(OBJ,输入);
// I =(int)的输出;
//}

// T2 = Environment.TickCount;

//MessageBox.Show((t2 - T1)的ToString()+ Environment.NewLine + i.ToString());

T1 = Environment.TickCount;

为(INT J = 0; J<亿; J ++)
{
I =执行(J);
}

T2 = Environment.TickCount;

MessageBox.Show(本机+(T2 - T1)的ToString()+ Environment.NewLine + i.ToString());

VAR FUNC =(Func键< INT,INT>)Delegate.CreateDelegate(typeof运算(Func键< INT,INT>),法);

T1 = Environment.TickCount;

为(INT J = 0; J<亿; J ++)
{
I = FUNC(J);
}

T2 = Environment.TickCount;

MessageBox.Show(动态代表:+(T2 - T1)的ToString()+ Environment.NewLine + i.ToString());

Func键< INT,INT> funcL =执行;

T1 = Environment.TickCount;

为(INT J = 0; J<亿; J ++)
{
I = funcL(J);
}

T2 = Environment.TickCount;

MessageBox.Show(代表:+(T2 - T1)的ToString()+ Environment.NewLine + i.ToString());
}


解决方案

这是有道理的。委托是不是函数指针。他们暗示类型检查,安全和其他很多东西的。他们更接近一个虚函数调用的速度(见的这个帖子),即使对性能的影响,从完全不同的东西派生的。



有关的不同的调用技术的比较好(有些人在未提及问题)阅读这文章


I posted this question earlier about dynamically compiling code in C#, and the answer has lead to another question.

One suggestion is that I use delegates, which I tried and they work well. However, they are benching at about 8.4 X slower than direct calls, which makes no sense.

What is wrong with this code?

My results, .Net 4.0, 64 bit, ran exe directly: 62, 514, 530

public static int Execute(int i) { return i * 2; }

private void button30_Click(object sender, EventArgs e)
{
    CSharpCodeProvider foo = new CSharpCodeProvider();

    var res = foo.CompileAssemblyFromSource(
        new System.CodeDom.Compiler.CompilerParameters()
        {
            GenerateInMemory = true,
            CompilerOptions = @"/optimize",                    
        },
        @"public class FooClass { public static int Execute(int i) { return i * 2; }}"
    );

    var type = res.CompiledAssembly.GetType("FooClass");
    var obj = Activator.CreateInstance(type);
    var method = type.GetMethod("Execute");
    int i = 0, t1 = Environment.TickCount, t2;
    //var input = new object[] { 2 };

    //for (int j = 0; j < 10000000; j++)
    //{
    //    input[0] = j;
    //    var output = method.Invoke(obj, input);
    //    i = (int)output;
    //}

    //t2 = Environment.TickCount;

    //MessageBox.Show((t2 - t1).ToString() + Environment.NewLine + i.ToString());

    t1 = Environment.TickCount;

    for (int j = 0; j < 100000000; j++)
    {
        i = Execute(j);
    }

    t2 = Environment.TickCount;

    MessageBox.Show("Native: " + (t2 - t1).ToString() + Environment.NewLine + i.ToString());

    var func = (Func<int, int>) Delegate.CreateDelegate(typeof (Func<int, int>), method);

    t1 = Environment.TickCount;

    for (int j = 0; j < 100000000; j++)
    {
        i = func(j);
    }

    t2 = Environment.TickCount;

    MessageBox.Show("Dynamic delegate: " + (t2 - t1).ToString() + Environment.NewLine + i.ToString());

    Func<int, int> funcL = Execute;

    t1 = Environment.TickCount;

    for (int j = 0; j < 100000000; j++)
    {
        i = funcL(j);
    }

    t2 = Environment.TickCount;

    MessageBox.Show("Delegate: " + (t2 - t1).ToString() + Environment.NewLine + i.ToString());
}

解决方案

It makes sense. Delegates are not function pointers. They imply type checking, security and a lot of other stuffs. They're more close to the speed of a virtual function call (see this post) even if the performance impact derives from something completely different.

For a good comparison of different invocation techniques (some of them not mentioned in the question) read this article.

这篇关于在C#中的代表意外表现不佳的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆