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,后来发现的。

    申明

    非源创博文中的内容均收集自网上,若有侵权之处,请及时联络,我会在第一时间内删除.再次说声抱歉!!!

    博文欢迎转载,但请给出原文连接。

  • 相关阅读:
    HDU 1022 Train Problem I
    HDU 1702 ACboy needs your help again!
    HDU 1294 Rooted Trees Problem
    HDU 1027 Ignatius and the Princess II
    HDU 3398 String
    HDU 1709 The Balance
    HDU 2152 Fruit
    HDU 1398 Square Coins
    HDU 3571 N-dimensional Sphere
    HDU 2451 Simple Addition Expression
  • 原文地址:https://www.cnblogs.com/Athrun/p/823366.html
Copyright © 2011-2022 走看看