c#中关于sealed修饰类的性能提升的测试

  在clr var c#一书中,作者描述当用sealed修饰类时,可以提高系统性能而且建议大家也养成用sealed来修饰类的习惯。由于对性能二字比较敏感,所以本文先测试一下用sealed分别修饰和不修饰类时,new1亿次的时间,然后说一下我的看法,如果有更好的测试方法,欢迎大家在此交流。

  首先上我的测试代码:

    class Program
    {
        static void Main(string[] args)
        {
            for (int j = 0; j < 10; j++)
            {
                V t = new T();
                V u = new U();
                t.oo();
                u.oo();

                DateTime startTimeT = DateTime.Now;

                for (int i = 0; i < 100000000; i++)
                {
                    t.oo();
                }

                DateTime endTimeT = DateTime.Now;
                TimeSpan spanT = endTimeT - startTimeT;
                Console.WriteLine("not sealed class:" + spanT.Milliseconds.ToString());

                DateTime startTimeU = DateTime.Now;
                for (int i = 0; i < 100000000; i++)
                {
                    u.oo();
                }
                DateTime endTimeU = DateTime.Now;
                TimeSpan spanU = endTimeU - startTimeU;
                Console.WriteLine("sealed class:" + spanU.Milliseconds.ToString());
                Console.WriteLine();
            }
            Console.ReadKey();
        }
    }

    class T : V
    {
        public override string oo()
        {
             return "Hello Another";
        }
    }

    sealed class U:V
    {
        public override string oo()
        {
            return "Hello Another";
        }
    }

    class V
    {
        public virtual string oo()
        {
            return "Hello Another";
        }
    }

   运行结果:              

  结果让我大吃一惊,用sealed修饰的类除了第一次快了2毫秒外,剩下九次结果都慢大约五六毫秒,为什么修饰完以后效率反而下降了呢。当用sealed修饰类以后, 1.有助于JIT内联;2.消除了协变与逆变和后期绑定,使CLR直接执行这个实例。

  先说说“第1点”,促使JIT内联代码的因素有很多,JIT不会因为一个类是sealed,就去装入其中的内容,而对于sealed类内部方法的内联,很大原因也是由于方法槽映射关系决定的,sealed作用有待考证。

      第2点,由于sealed类不可派生或被继承,所以的确在运行时省去可CLR一些额外的工作,但是这些工作只是一些类似于“寻址”的工作,因为虚拟方法表已经完成了运行时与编译时的对应关系,纯粹的运行时只是在寻找这些关系而已,所以sealed省去的只是一部分较为复杂的寻址关系,因为即使没有继承,也不可避免一个方法表的应用。(上述两点参考http://kb.cnblogs.com/page/73598/)

  之所以CLR via C#一书中会这么写,完全是因为作者本人的编程习惯。Jeffrey Richter不喜欢过分开放的对象,能private的绝对不public,除非确定要作为基类,不然一定会用sealed封死。

  写到这里,我又忍不住多测了几遍,发现有时候修饰候后慢50多毫秒(460 vs 410),结果证明不但没快反而慢了好多,希望有知道原因的大牛指点一下^.^

原文地址:https://www.cnblogs.com/xuekai-to-sharp/p/3407402.html