• 技术文章 >后端开发 >C#.Net教程

    C# 性能优化最佳实践

    黄舟黄舟2017-02-25 11:04:45原创1101

    1、显式注册的EvenHandler要显式注销以避免内存泄漏

    将一个成员方法注册到某个对象的事件会造成后者持有前者的引用。在事件注销之前,前者不会被垃圾回收。

    private void Form1_Load()
    {
      ……
      //注册事件
      CommandRemotingContext.CmdChanged += new ReciverCmdStateChangedEventHandler(this.CommandRemotingContext_CmdChanged);
      ……
    }
    private void Form1_FromClosed()
    {
      ……
      //关闭窗体时及时释放事件
      CommandRemotingContext.CmdChanged -= new ReciverCmdStateChangedEventHandler(this.CommandRemotingContext_CmdChanged);
      ……
    }

    由事件引起的内存泄漏问题:


    2、控件绑定的数据源批量操作应避免自动刷新

    3、减少客户端与服务端的通信次数


    4、减少客户端与服务端的通信次数

    如非必要,应尽量避免在循环体内重复调用WebService

    //循环调用了相同的WS  
    List<Person> persons;
    ……
    foreach(string personID in personIDs)
    {
    	person=HRPubWsClient.getPerson(personID);
    	persons.Add(person);
    }
    //合并WS  
    List<Person> persons;
    ……
    persons =HRPubWsClient.getPersonList(personIDs);

    5、使用泛型来避免装箱、拆箱操作(减少垃圾回收压力)

    6、字符串操作:

    C# 字符串操作--减少垃圾回收压力
    7、使用常量避免创建对象

    8、避免不必要的抛出异常

    C# 异常处理(Catch Throw)IL分析

    9、使用RemoveAll而非RemoveAt进行删除多个元素

    10、C# DataSet性能最佳实践

    11、反射与动态绑定--减少CPU占用

    动态创建对象的方式
    与Direct Create
    1.Type.InvokeMember
    慢40倍以上
    2.ContructorInfo.Invoke
    慢40倍以上
    3.Activator.CreateInstance(Type)
    慢7倍
    4.Activator.CreateInstance(assemblyName, typeName)
    慢1000倍以上
    5.Assembly.CreateInstance(typeName)
    慢40倍以上

    1. 使用接口调用方式将动态绑定改造为早期绑定(Direct Call)
    2. 使用 Activator.CreateInstance(Type)方式动态创建对象

    3. 使用typeof操作符代替GetType调用

    小注:

    通过循环创建实例记录时间如下:

    加载程序集、获取类型在循环外部时间如下(这时不同创建方式消耗时间差距挺大):


    代码如下:

     public void TestCreateInstance()
            {
                Stopwatch watch1 = new Stopwatch();
                var asmb = Assembly.LoadFrom("ReflectiveClassLibrary.dll");
                Type type = asmb.GetType("ReflectiveClassLibrary.TestClass");
                int num = 100000;
                watch1.Start();
    
                for (int i = 0; i < num; i++)
                {
                    //var asmb = Assembly.LoadFrom("ReflectiveClassLibrary.dll");
                    //Type type = asmb.GetType("ReflectiveClassLibrary.TestClass");
                    Activator.CreateInstance(type);
                }
                watch1.Stop();
                label1.Text = "Activator.CreateInstance(Type type)时间:" + watch1.ElapsedMilliseconds + "毫秒";
    
                watch1.Reset();
                watch1.Start();
                for (int i = 0; i < num; i++)
                {
                    Activator.CreateInstance("ReflectiveClassLibrary", "ReflectiveClassLibrary.TestClass");
                }
                watch1.Stop();
                label2.Text = "Activator.CreateInstance(string assemblyName,string typeName)时间:" + watch1.ElapsedMilliseconds + "毫秒";
    
                watch1.Reset();
                watch1.Start();
                for (int i = 0; i < num; i++)
                {
                    //var asmb = Assembly.LoadFrom("ReflectiveClassLibrary.dll");
                    //加载程序集                
                    asmb.CreateInstance("TestClass");
                }
                watch1.Stop();
                label3.Text = "assembly.CreateInstance(string typeName)时间:" + watch1.ElapsedMilliseconds + "毫秒";
    
                watch1.Reset();
                watch1.Start();
                for (int i = 0; i < num; i++)
                {
                    //var asmb = Assembly.LoadFrom("ReflectiveClassLibrary.dll");
                    //Type type = asmb.GetType("ReflectiveClassLibrary.TestClass");
                    object obj = type.InvokeMember(null, BindingFlags.Public |
                   BindingFlags.Instance | BindingFlags.CreateInstance, null, null, null);
                }
                watch1.Stop();
                label4.Text = "Type.InvokeMember(string name, BindingFlags invokeAttr, Binder binder, object target, object[] args)时间:" + watch1.ElapsedMilliseconds + "毫秒";
    
                watch1.Reset();
                watch1.Start();
                for (int i = 0; i < num; i++)
                {
                    //var asmb = Assembly.LoadFrom("ReflectiveClassLibrary.dll");
                    //Type type = asmb.GetType("ReflectiveClassLibrary.TestClass");
                    ConstructorInfo constructorInfo = type.GetConstructors()[0];
                    constructorInfo.Invoke(null);
                }
                watch1.Stop();
                label5.Text = "ContructorInfo.Invoke(object[] parameters)时间:" + watch1.ElapsedMilliseconds + "毫秒";
    
            }


    加载程序集、获取类型在循环内部时间如下(这时不同创建方式消耗时间差距比较小)


    代码如下:

     public void TestCreateInstance()
            {
                Stopwatch watch1 = new Stopwatch();
                //var asmb = Assembly.LoadFrom("ReflectiveClassLibrary.dll");
                //Type type = asmb.GetType("ReflectiveClassLibrary.TestClass");
                int num = 100000;
                watch1.Start();
    
                for (int i = 0; i < num; i++)
                {
                    var asmb = Assembly.LoadFrom("ReflectiveClassLibrary.dll");
                    Type type = asmb.GetType("ReflectiveClassLibrary.TestClass");
                    Activator.CreateInstance(type);
                }
                watch1.Stop();
                label1.Text = "Activator.CreateInstance(Type type)时间:" + watch1.ElapsedMilliseconds + "毫秒";
    
                watch1.Reset();
                watch1.Start();
                for (int i = 0; i < num; i++)
                {
                    Activator.CreateInstance("ReflectiveClassLibrary", "ReflectiveClassLibrary.TestClass");
                }
                watch1.Stop();
                label2.Text = "Activator.CreateInstance(string assemblyName,string typeName)时间:" + watch1.ElapsedMilliseconds + "毫秒";
    
                watch1.Reset();
                watch1.Start();
                for (int i = 0; i < num; i++)
                {
                    var asmb = Assembly.LoadFrom("ReflectiveClassLibrary.dll");
                    //加载程序集                
                    asmb.CreateInstance("TestClass");
                }
                watch1.Stop();
                label3.Text = "assembly.CreateInstance(string typeName)时间:" + watch1.ElapsedMilliseconds + "毫秒";
    
                watch1.Reset();
                watch1.Start();
                for (int i = 0; i < num; i++)
                {
                    var asmb = Assembly.LoadFrom("ReflectiveClassLibrary.dll");
                    Type type = asmb.GetType("ReflectiveClassLibrary.TestClass");
                    object obj = type.InvokeMember(null, BindingFlags.Public |
                   BindingFlags.Instance | BindingFlags.CreateInstance, null, null, null);
                }
                watch1.Stop();
                label4.Text = "Type.InvokeMember(string name, BindingFlags invokeAttr, Binder binder, object target, object[] args)时间:" + watch1.ElapsedMilliseconds + "毫秒";
    
                watch1.Reset();
                watch1.Start();
                for (int i = 0; i < num; i++)
                {
                    var asmb = Assembly.LoadFrom("ReflectiveClassLibrary.dll");
                    Type type = asmb.GetType("ReflectiveClassLibrary.TestClass");
                    ConstructorInfo constructorInfo = type.GetConstructors()[0];
                    constructorInfo.Invoke(null);
                }
                watch1.Stop();
                label5.Text = "ContructorInfo.Invoke(object[] parameters)时间:" + watch1.ElapsedMilliseconds + "毫秒";
    
            }


    测试代码如下:

    c# 反射测试demo

    12、序列化与反序列化

    以上就是C# 性能优化最佳实践的内容,更多相关内容请关注PHP中文网(m.sbmmt.com)!


    声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn核实处理。
    专题推荐:C# 性能优化
    上一篇:将勾选数据从dataset中筛选出来 下一篇:自己动手写 PHP MVC 框架(40节精讲/巨细/新人进阶必看)

    相关文章推荐

    • 汇编语言和c语言的区别是什么• C# 动态加载Dll• 从0自学C#04--特性和设计原则• ASP.NET使用Ajax如何返回Json对象的方法具体介绍• asp.net 图片验证码的HtmlHelper
    1/1

    PHP中文网