当前位置:  开发笔记 > 编程语言 > 正文

动态创建类型的性能

如何解决《动态创建类型的性能》经验,为你挑选了1个好方法。

使用C#,我注意到在使用动态生成类型的实例与简单结构填充列表时性能的显着差异.下面的代码包括4种不同的方法,用于填充包含100,000个对象的列表.

每种方法的表现不同:

Button1:15毫秒

Button2:31毫秒

Button3&4:300毫秒

请注意,按钮3和4的代码来自此主题

谁能解释为什么动态创建的对象更慢?

    public struct DataRow
    {
        public double t;
        public double vf;
        public double im;

        public double T { get { return t; } set { t = value; } }
        public double Vf { get { return vf; } set { vf = value; } }
        public double Im { get { return im; } set { im = value; } }
    }

    //Use struct defined above
    private void button1_Click(object sender, EventArgs e)
    {
        int n = 0;

        //adding rows
        List myTable = new List();
        DataRow myRow = new DataRow();

        start = DateTime.Now;

        while (n < 100000)
        {
            myRow.T = n * 1.0;
            myRow.Vf = 2.0;
            myRow.Im = 4.0;

            myTable.Add(myRow);

            n++;
        }
        end = DateTime.Now;
        System.TimeSpan diff = end.Subtract(start);
        label2.Text = diff.Seconds.ToString();
        label4.Text = diff.Milliseconds.ToString();

        dataGridView1.DataSource = myTable;
    }

    //define the list as it is done on buttons 3 & 4 but use the static struct
    private void button2_Click(object sender, EventArgs e)
    {
        Type myType = typeof(DataRow);

        Type listType = typeof(List<>);

        Type myListType = listType.MakeGenericType(myType);

        IList myTable = (IList)Activator.CreateInstance(myListType);

        DataRow bRow = new DataRow();

        int n = 0;
        start = DateTime.Now;
        while (n < 100000)
        {
            bRow.t = n * 1.0;
            bRow.vf = 2.0;
            bRow.im = 4.0;
            myTable.Add(bRow);

            n++;
        }
        end = DateTime.Now;
        System.TimeSpan diff = end.Subtract(start);
        label2.Text = diff.Seconds.ToString();
        label4.Text = diff.Milliseconds.ToString();
        dataGridView1.DataSource = myTable;

    }

    //Create assy at runtime and load dll
    private void button3_Click(object sender, EventArgs e)
    {
        Type myType = CreateDynRow();
        Assembly myAssy = Assembly.LoadFrom("DynaRowAssy.dll");
        Type myRow = myAssy.GetType("DynaRow");

        Type listType = typeof(List<>);

        Type myListType = listType.MakeGenericType(myRow);

        IList myTable = (IList)Activator.CreateInstance(myListType);

        FieldInfo piT = myRow.GetField("t");
        FieldInfo piVf = myRow.GetField("vf");
        FieldInfo piIm = myRow.GetField("im");

        ValueType aRow = (ValueType)Activator.CreateInstance(myRow);

        int n = 0;
        start = DateTime.Now;
        while (n < 100000)
        {
            piT.SetValue(aRow, 1 * n);
            piVf.SetValue(aRow, 2.0);
            piIm.SetValue(aRow, 4.0);
            myTable.Add(aRow);

            n++;
        }
        end = DateTime.Now;
        System.TimeSpan diff = end.Subtract(start);
        label2.Text = diff.Seconds.ToString();
        label4.Text = diff.Milliseconds.ToString();
        dataGridView1.DataSource = myTable;
    }

    //create assy at runtime in memory
    private void button4_Click(object sender, EventArgs e)
    {
        //build the assembly
        Type myType = CreateDynRow();

        Type listType = typeof(List<>);

        Type myListType = listType.MakeGenericType(myType);

        IList myTable = (IList)Activator.CreateInstance(myListType);

        FieldInfo piT = myType.GetField("t");
        FieldInfo piVf = myType.GetField("vf");
        FieldInfo piIm = myType.GetField("im");

        ValueType aRow = (ValueType)Activator.CreateInstance(myType);

        int n = 0;
        start = DateTime.Now;
        while (n < 100000)
        {
            piT.SetValue(aRow, 1 * n);
            piVf.SetValue(aRow, 2.0);
            piIm.SetValue(aRow, 4.0);
            myTable.Add(aRow);

            n++;
        }
        end = DateTime.Now;
        System.TimeSpan diff = end.Subtract(start);
        label2.Text = diff.Seconds.ToString();
        label4.Text = diff.Milliseconds.ToString();
        dataGridView1.DataSource = myTable;
    }

itowlson.. 5

它(主要)不是动态创建:它使用反射(FieldInfo.SetValue)使得button3和button4版本比编译调用时更慢.

解决此问题的一种可能方法是声明代码可以编译的接口,并使动态类型实现此接口.您仍然会通过反射实例化并查询该接口的动态类型,但之后它应该与"静态"引用一样快.



1> itowlson..:

它(主要)不是动态创建:它使用反射(FieldInfo.SetValue)使得button3和button4版本比编译调用时更慢.

解决此问题的一种可能方法是声明代码可以编译的接口,并使动态类型实现此接口.您仍然会通过反射实例化并查询该接口的动态类型,但之后它应该与"静态"引用一样快.


你也可以通过使用`System.Expressions`解决这个问题,所以你只需要为你的整个对象做一次反射.
推荐阅读
手机用户2402852387
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有