• C#性能优化实践 资料整理


    缓存(Cache)是性能优化中最常用的优化手段.适用的情况是频繁的获取一些数据,而每次获取这些数据需要的时间比较长。这时,第一次获取的时候会用正常的方法,并且在获取之后把数据缓存下来。之后就使用缓存的数据。 如果使用了缓存的优化方法,需要特别注意缓存数据的同步,就是说,如果真实的数据发生了变化,应该及时的清除缓存数据,确保不会因为缓存而使用了错误的数据。 举例:

    1. 使用缓存的情况比较多。最简单的情况就是缓存到一个Field或临时变量里。 
      
      
      forint i = 0; i < gcMultiRow.RowCount; i++)
      {
          // Do something;
      }
       
      以上代码一般情况下是没有问题的,但是,如果GcMultiRow的行数比较大。而RowCount属性的取值又比较慢的时候就需要使用缓存来做性能优化。           
       
      int rowCount = gcMultiRow.RowCount;
      for (int i = 0; i < rowCount; i++)
      {
         // Do something;
      }

        

    2. 使用对象池也是一个常见的缓存方案,比使用Field或临时变量稍微复杂一点。 例如,在MultiRow中,画边线,画背景,需要用到大量的Brush和Pen。这些GDI对象每次用之前要创建,用完后要销毁。创建和销毁的过程是比较慢的。GcMultiRow使用的方案是创建一个GDIPool。本质上是一些Dictionary,使用颜色做Key。所以只有第一次取的时候需要创建,以后就直接使用以前创建好的。以下是GDIPool的代码: 
      public static class GDIPool
      {
          Dictionary<Color, Brush > _cacheBrush = new Dictionary<Color, Brush>();
          Dictionary<Color, Pen> _cachePen = new Dictionary<Color, Pen>();
          public static Pen GetPen(Color color)
         {
             Pen pen;
             if_cachePen.TryGetValue(color, out pen))
             {
                 return pen;
             }
             pen = new Pen(color);
            _cachePen.Add(color, pen);
             return pen;
         }
      }

        

    3. 懒构造 
      有时候,有的对象创建需要花费较长时间。而这个对象可能并不是所有的场景下都需要使用。这时,使用赖构造的方法可以有效提高性能。 举例:对象A需要内部创建对象B。对象B的构造时间比较长。 一般做法: 
      public class A
      {
         public B _b = new B();
      }

        

      一般做法下由于构造对象A的同时要构造对象B导致了A的构造速度也变慢了。优化做法:

      public class A
      {
         private B _b;
         public B BProperty
         {
             get
            {
               if(_b == null)
               {
                   _b = new B();
               }
               return _b;
            }
         }
      }

        

      优化后,构造A的时候就不需要创建B对象,只有需要使用的时候才需要构造B对象。

      1. 了解Framework提供的数据结构 
        我们现在工作的.net framework平台,有很多现成的数据数据结构。我们应该了解这些数据结构,提升我们程序的性能: 举例:
        1. string 的加运算符 VS StringBuilder: 字符串的操作是我们经常遇到的基本操作之一。 我们经常会写这样的代码 string str = str1 + str2。当操作的字符串很少的时候,这样的操作没有问题。但是如果大量操作的时候(例如文本文件的Save/Load, Asp.net的Render),这样做就会带来严重的性能问题。这时,我们就应该用StringBuilder来代替string的加操作。
        2. Dictionary VS List Dictionary和List是最常用的两种集合类。选择正确的集合类可以很大的提升程序的性能。为了做出正确的选择,我们应该对Dictionary和List的各种操作的性能比较了解。 下表中粗略的列出了两种数据结构的性能比较。 

          操作

          List

          Dictionary

          索引

          Find(Contains)

          Add

          Insert

          Remove

        3. TryGetValue 对于Dictionary的取值,比较直接的方法是如下代码: 
          if(_dic.ContainKey("Key")
          {
              return _dic["Key"];
          }

            

          当需要大量取值的时候,这样的取法会带来性能问题。优化方法如下:

          object value;
          if(_dic.TryGetValue("Key", out value))
          {
              return value;
          }

            

          使用TryGetValue可以比先Contain再取值提高一倍的性能。

        4. 为Dictionary选择合适的Key。 Dictionary的取值性能很大情况下取决于做Key的对象的Equals和GetHashCode两个方法的性能。如果可以的话使用Int做Key性能最好。如果是一个自定义的Class做Key的话,最好保证以下两点:1. 不同对象的GetHashCode重复率低。2. GetHashCode和Equals方法立即简单,效率高。
        5. List的Sort和BinarySearch性能很好,如果能满足功能需求的话推荐直接使用,而不是自己重写。 
          List<int> list = new List<int>{3, 10, 15};
          list.BinarySearch(10); // 对于存在的值,结果是1
          list.BinarySearch(8); // 对于不存在的值,会使用负数表示位置,如查找8时,结果是-2, 查找0结果是-1,查找100结果是-4.
  • 相关阅读:
    有线电视网络(最小割)
    太空飞行计划问题(最小割,最大权闭合图,网络流24题)
    攻击装置(最小割,最大权独立集)
    王者之剑(最小割,最大独立集)
    善意的投票(最小割)
    有向图破坏(最小割,最小点权覆盖)
    线性代数(最小割,最大密度子图,TJOI2015)
    codewars--js--counting duplicates
    codewars--js--the highest and lowest number + JS 字符串和数组相关知识
    work
  • 原文地址:https://www.cnblogs.com/wangzhen/p/3447669.html
Copyright © 2020-2023  润新知