dotnet程序优化心得(二)
下面以实际例子具体解释相关技巧。
(2) 分析问题
写测试程序测试在我的1.5M迅驰本本测试,替换效率为30万字/s,该程序采用Replace,这样对每一个字符都要扫描GB_Lib字符串中的几千个字符,性能自然上不去。需要寻找更好的数据结构和算法,降低每一个字符串的操作时间。
.net类库里有一个很好的东西可以拿来直接用:Hashtable。也就是说,把每一个简体字作为key,每一个繁体字作为value。这样处理每个字符的时候只需要看它在不在Hashtable的key里面,在的话就找出对应的value替换,否则就不做任何操作。这样做的代价是Hashtable初始化的耗时,不过初始化顶多也就一次嘛。程序如下:
(1)缘起
bfax@smth.org发了一个字符串转换程序,引起了热烈讨论。原程序如下:
1![](https://xiaotie.cnblogs.com/Images/OutliningIndicators/None.gif)
2
Function B2G(prestr As String) As String
3
Dim i, j As Integer
4
Const GB_Lib = "
" //几千个字符吧,因为字符串长度限制,原程序是由GB_lib1,GB_lib2
GB_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
18
End Function
![](https://xiaotie.cnblogs.com/Images/OutliningIndicators/None.gif)
2
![](https://xiaotie.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
3
![](https://xiaotie.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
4
![](https://xiaotie.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/dot.gif)
![](https://www.cnblogs.com/Images/dot.gif)
5
![](https://xiaotie.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/dot.gif)
6
![](https://xiaotie.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
7
![](https://xiaotie.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
8
![](https://xiaotie.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
9
![](https://xiaotie.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
10
![](https://xiaotie.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
11
![](https://xiaotie.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
12
![](https://xiaotie.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
13
![](https://xiaotie.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
14
![](https://xiaotie.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
15
![](https://xiaotie.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
16
![](https://xiaotie.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
17
![](https://xiaotie.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
18
![](https://xiaotie.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
(2) 分析问题
写测试程序测试在我的1.5M迅驰本本测试,替换效率为30万字/s,该程序采用Replace,这样对每一个字符都要扫描GB_Lib字符串中的几千个字符,性能自然上不去。需要寻找更好的数据结构和算法,降低每一个字符串的操作时间。
.net类库里有一个很好的东西可以拿来直接用:Hashtable。也就是说,把每一个简体字作为key,每一个繁体字作为value。这样处理每个字符的时候只需要看它在不在Hashtable的key里面,在的话就找出对应的value替换,否则就不做任何操作。这样做的代价是Hashtable初始化的耗时,不过初始化顶多也就一次嘛。程序如下:
1
public class ConvertDemo
2
{
3
private static Hashtable _libTable;
4![](https://xiaotie.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
5
static ConvertDemo()
6
{
7
InitHashTable();
8
}
9![](https://xiaotie.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
10
static string GB_lib="
";
11![](https://xiaotie.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
12
static string BIG5_lib="
";
13![](https://xiaotie.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
14
private static void InitHashTable()
15
{
16
_libTable = new Hashtable();
17
PushIntoHashtable(_libTable,GB_lib,BIG5_lib);
18
}
19![](https://xiaotie.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
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![](https://xiaotie.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
28
private static char ConvertChar(char input)
29
{
30
if (_libTable.ContainsKey(input)) return (char)_libTable[input];
31
else return input;
32
}
33![](https://xiaotie.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
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
}
![](https://xiaotie.cnblogs.com/Images/OutliningIndicators/None.gif)
2
![](https://xiaotie.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
3
![](https://xiaotie.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
4
![](https://xiaotie.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
5
![](https://xiaotie.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
6
![](https://xiaotie.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
7
![](https://xiaotie.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
8
![](https://xiaotie.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
9
![](https://xiaotie.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
10
![](https://xiaotie.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/dot.gif)
11
![](https://xiaotie.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
12
![](https://xiaotie.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/dot.gif)
13
![](https://xiaotie.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
14
![](https://xiaotie.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
15
![](https://xiaotie.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
16
![](https://xiaotie.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
17
![](https://xiaotie.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
18
![](https://xiaotie.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
19
![](https://xiaotie.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
20
![](https://xiaotie.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
21
![](https://xiaotie.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
22
![](https://xiaotie.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
23
![](https://xiaotie.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
24
![](https://xiaotie.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
25
![](https://xiaotie.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
26
![](https://xiaotie.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
27
![](https://xiaotie.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
28
![](https://xiaotie.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
29
![](https://xiaotie.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
30
![](https://xiaotie.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
31
![](https://xiaotie.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
32
![](https://xiaotie.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
33
![](https://xiaotie.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
34
![](https://xiaotie.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
35
![](https://xiaotie.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
36
![](https://xiaotie.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
37
![](https://xiaotie.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
38
![](https://xiaotie.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
39
![](https://xiaotie.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
40
![](https://xiaotie.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
41
![](https://xiaotie.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
42
![](https://xiaotie.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
43
![](https://xiaotie.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
测试性能,结果为300万字/秒。性能提高了10倍。
(3)用relector看Hashtable源代码,消除无用操作,继续优化
还能不能继续优化呢?ConvertChar (char input)执行次数最多,是对性能最有影响的方法。用reflector反编译Hashtable的get_Item(object key)方法:
1
public 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
}
![](https://xiaotie.cnblogs.com/Images/OutliningIndicators/None.gif)
2
![](https://xiaotie.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
3
![](https://xiaotie.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
4
![](https://xiaotie.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
5
![](https://xiaotie.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
6
![](https://xiaotie.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
7
![](https://xiaotie.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
8
![](https://xiaotie.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
9
![](https://xiaotie.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
10
![](https://xiaotie.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
11
![](https://xiaotie.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
12
![](https://xiaotie.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
13
![](https://xiaotie.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
14
![](https://xiaotie.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
15
![](https://xiaotie.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
16
![](https://xiaotie.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
17
![](https://xiaotie.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
18
![](https://xiaotie.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
19
![](https://xiaotie.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
20
![](https://xiaotie.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
21
![](https://xiaotie.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
22
![](https://xiaotie.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
23
![](https://xiaotie.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
24
![](https://xiaotie.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
25
![](https://xiaotie.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
26
![](https://xiaotie.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
27
![](https://xiaotie.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
28
![](https://xiaotie.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
29
![](https://xiaotie.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
我的天天天天天天天天天天天天天........好长呀,先不管这个。哦,方法并不抛出异常,如果key不存在就直接返回null。这样的话,采用ContainsKey(...)判断key是否存在就是多次一举了。
把ConvertChar (char input)改为:
1
private static char ConvertChar(char input)
2
{
3
object temp = _libTable[input];
4
return temp == null?input:(char)temp;
5
}
![](https://xiaotie.cnblogs.com/Images/OutliningIndicators/None.gif)
2
![](https://xiaotie.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
3
![](https://xiaotie.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
4
![](https://xiaotie.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
5
![](https://xiaotie.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
这样大概能节省一半的操作。
测试结果验证了我这一想法。性能一下提高了40%,达到了500万字/s
注:上面程序有小bug,后来发现的。
申明
非源创博文中的内容均收集自网上,若有侵权之处,请及时联络,我会在第一时间内删除.再次说声抱歉!!!
博文欢迎转载,但请给出原文连接。