繁体中文
设为首页
加入收藏
当前位置:.Net技术首页 >> Asp.Net开发 >> dotnet程序优化心得(二)

dotnet程序优化心得(二)

2007-09-15 08:00:00  作者:  来源:互联网  浏览次数:0  文字大小:【】【】【
简介:下面以实际例子具体解释相关技巧。 (1)缘起 bfax@smth.org发了一个字符串转换程序,引起了热烈讨论。原程序如下: 1 2Function B2G()Function B2G(prestr As String) As String 3 Dim i, j As Integer 4 C...
关键字:优化 心得 程序 dotnet

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

(1)缘起

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

1

2Function B2G()Function B2G(prestr As String) As 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

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

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

责任编辑:admin
相关文章