zoukankan      html  css  js  c++  java
  • 也谈枚举ToString()性能的改进

    昨天看到 “性能相差7千倍的ToString方法”这篇文章,对于作者这种良好的性能意识和探索精神很佩服,以前还真没注意到这点。

    不过,用switch的做法,个人觉得虽然性能上去了,但是可维护性就下来了,以后该枚举要增加或删除一项,这段switch代码都要改一下,其实该问题的关键就是反射带来的性能损耗,在调用枚举的ToString()方法时,无非就是要得到一个字符串而已,我个人更倾向于用key-value这种经典的键值对来优化。

    下面是示例代码:

     public static class TestClass
        {
            public static Dictionary<int, string> EnumLoginErrorNames = new Dictionary<int, string>();
    
            //静态私有构造器
            static TestClass()
            {
                AddEnumLoginErrorToDic(); //自动将枚举放入对应的字典中           
            }
    
            public enum EnumLoginError
            {
                用户名不存在,
                密码错误,
                用户被锁定,
                未知错误
            }
    
            private static void AddEnumLoginErrorToDic()
            {
    
                string[] _names = Enum.GetNames(typeof(EnumLoginError));
                int[] _values = Enum.GetValues(typeof(EnumLoginError)) as int[];
    
                for (int i = 0; i < _values.Length; i++)
                {
                    EnumLoginErrorNames.Add(_values[i], _names[i]);
                }            
            }
        }
    

    这样处理后的性能测试代码:(asp.net页中测试的,主要只是对比一下跟传统ToString方法的差异而已)

    protected void Page_Load(object sender, EventArgs e)
            {
                Stopwatch sw = new Stopwatch();
                int _max = 1000000,i=0;
    
                string _temp = TestClass.EnumLoginErrorNames[(int)TestClass.EnumLoginError.用户被锁定];//先调用一次,以便预热
    
                //Dictionary方法 计时开始
                sw.Start();
                for (i = 0; i < _max; i++)
                {
    
                    _temp = TestClass.EnumLoginErrorNames[(int)TestClass.EnumLoginError.用户被锁定]; 
                }
                sw.Stop();
                Debug.WriteLine("Dictionary方法耗时:" + sw.ElapsedMilliseconds);
                sw.Reset();
    
                //反射方法 计时开始
                sw.Start();
                for (i = 0; i < _max; i++)
                {
                    _temp = TestClass.EnumLoginError.用户被锁定.ToString();
                }
                sw.Stop();
    
                Debug.WriteLine("反射方法 耗时:" + sw.ElapsedMilliseconds);
    
    
            }
    

    在我的本本上跑出来的测试结果如下:

    Dictionary方法耗时:28
    反射方法 耗时:1384

    效果还是比较明显的,相对于switch方法而言,没有将结果字符串硬编码在处理函数中,以后枚举中增加或删除某一项,也不影响调用代码,可维护性相对更好一些。但是也应该看到,这是一种空间换时间的做法,避开了反射,但是系统需要额外存储一个字典对象,占用的内存要比原来多一些。

    最后:本文仅为技术探讨,没有哪个最好之说,具体如何使用,大家自己酌情考虑。

    作者:菩提树下的杨过
    出处:http://yjmyzz.cnblogs.com
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
  • 相关阅读:
    用大白话谈谈XSS与CSRF
    Lenet5设计理解——咬文嚼字系列
    【java设计模式】之 责任链(chain of resposibility)模式
    【java设计模式】之 代理(Proxy)模式
    【java设计模式】之 建造者(Builder)模式
    【java设计模式】之 模板方法(Template Method)模式
    【java设计模式】之 抽象工厂(Abstract Factory)模式
    【java设计模式】之 工厂(Factory)模式
    浅谈Arrays.asList()方法的使用
    分布式缓存技术redis学习系列(四)——redis高级应用(集群搭建、集群分区原理、集群操作)
  • 原文地址:https://www.cnblogs.com/yjmyzz/p/1830766.html
Copyright © 2011-2022 走看看