zoukankan      html  css  js  c++  java
  • dotnet程序优化心得(二)

      下面以实际例子具体解释相关技巧。

     (1)缘起

    bfax@smth.org发了一个字符串转换程序,引起了热烈讨论。原程序如下:

     1
     2Function B2G(prestr As StringAs String
     3    Dim i, j As Integer
     4    Const GB_Lib = ""    //几千个字符吧,因为字符串长度限制,原程序是由GB_lib1,GB_lib2GB_lib4四个字符串构成的,为了简化问题,只用一个字符串代替。
     5    Const BIG5_Lib = ""    //与GB_Lib中简体字一一对应的繁体字
     6    
     7    For i = 1 To prestr.Length
     8        j= Instr(1, BIG5_Lib1, GetChar(prestr, i)) 
     9        If j<>0 Then prestr=prestr.Replace(GetChar(BIG5_Lib1,j),GetChar(GB_Lib1,j))
    10        j= Instr(1, BIG5_Lib2, GetChar(prestr, i)) 
    11        If j<>0 Then prestr=prestr.Replace(GetChar(BIG5_Lib2,j),GetChar(GB_Lib2,j))
    12        j= Instr(1, BIG5_Lib3, GetChar(prestr, i)) 
    13        If j<>0 Then prestr=prestr.Replace(GetChar(BIG5_Lib3,j),GetChar(GB_Lib3,j))
    14        j= Instr(1, BIG5_Lib4, GetChar(prestr, i)) 
    15        If j<>0 Then prestr=prestr.Replace(GetChar(BIG5_Lib4,j),GetChar(GB_Lib4,j))
    16    Next
    17    Return prestr
    18End Function


    (2) 分析问题

    写测试程序测试在我的1.5M迅驰本本测试,替换效率为30万字/s,该程序采用Replace,这样对每一个字符都要扫描GB_Lib字符串中的几千个字符,性能自然上不去。需要寻找更好的数据结构和算法,降低每一个字符串的操作时间。

    .net类库里有一个很好的东西可以拿来直接用:Hashtable。也就是说,把每一个简体字作为key,每一个繁体字作为value。这样处理每个字符的时候只需要看它在不在Hashtable的key里面,在的话就找出对应的value替换,否则就不做任何操作。这样做的代价是Hashtable初始化的耗时,不过初始化顶多也就一次嘛。程序如下:

     1public class ConvertDemo
     2{
     3    private static Hashtable _libTable;
     4
     5    static ConvertDemo()
     6    {
     7        InitHashTable();
     8    }

     9
    10    static string GB_lib="";
    11
    12    static string BIG5_lib="";
    13
    14    private static void InitHashTable()
    15    {
    16        _libTable = new Hashtable();
    17        PushIntoHashtable(_libTable,GB_lib,BIG5_lib);
    18    }

    19
    20    private static void PushIntoHashtable(Hashtable t, string g , string b)
    21    {
    22        for (int i=0;i<g.Length;i++)
    23        {
    24            t.Add(g[i],b[i]);
    25        }

    26    }

    27
    28    private static char ConvertChar(char input)
    29    {
    30        if (_libTable.ContainsKey(input)) return (char)_libTable[input];
    31        else return input;
    32    }

    33
    34    public static string ConvertText(string inputString)
    35    {
    36        StringBuilder sb = new StringBuilder(inputString);
    37        for (int i=0;i<inputString.Length;i++)
    38        {
    39            sb[i] = ConvertChar(inputString[i]);
    40        }

    41        return sb.ToString();
    42    }

    43}


    测试性能,结果为300万字/秒。性能提高了10倍。

    (3)用relector看Hashtable源代码,消除无用操作,继续优化

    还能不能继续优化呢?ConvertChar (char input)执行次数最多,是对性能最有影响的方法。用reflector反编译Hashtable的get_Item(object key)方法:

     1public virtual object get_Item(object key)
     2{
     3      uint num1;
     4      uint num2;
     5      Hashtable.bucket bucket1;
     6      if (key == null)
     7      {
     8            throw new ArgumentNullException("key", Environment.GetResourceString("ArgumentNull_Key"));
     9      }

    10      Hashtable.bucket[] bucketArray1 = this.buckets;
    11      uint num3 = this.InitHash(key, bucketArray1.Length, out num1, out num2);
    12      int num4 = 0;
    13      int num5 = (int) (num1 % bucketArray1.Length);
    14      do
    15      {
    16            bucket1 = bucketArray1[num5];
    17            if (bucket1.key == null)
    18            {
    19                  return null;
    20            }

    21            if (((bucket1.hash_coll & 0x7fffffff== num3) && this.KeyEquals(key, bucket1.key))
    22            {
    23                  return bucket1.val;
    24            }

    25            num5 = (int) ((num5 + num2) % ((ulong) bucketArray1.Length));
    26      }

    27      while ((bucket1.hash_coll < 0&& (++num4 < bucketArray1.Length));
    28      return null;
    29}


    我的天天天天天天天天天天天天天........好长呀,先不管这个。哦,方法并不抛出异常,如果key不存在就直接返回null。这样的话,采用ContainsKey(...)判断key是否存在就是多次一举了。

    把ConvertChar (char input)改为:

    1private static char ConvertChar(char input)
    2{
    3object temp = _libTable[input];
    4return temp == null?input:(char)temp;
    5}


    这样大概能节省一半的操作。

    测试结果验证了我这一想法。性能一下提高了40%,达到了500万字/s

    注:上面程序有小bug,后来发现的。

    版权所有,欢迎转载
  • 相关阅读:
    聚焦WCF行为的扩展
    软件设计经典书籍推荐
    善变者常新
    开发WCF/Silverlight须知
    面向对象设计讲义
    站立会议变形记
    敏捷开发思想之拥抱变化
    WCF 4.0中的WSDiscovery
    QCon日记
    创投“黑帮”,必须的
  • 原文地址:https://www.cnblogs.com/xiaotie/p/215258.html
Copyright © 2011-2022 走看看