上周参加完微软的CTEC会后,紧接着又参加了TechEd 2004,回来后,看到很多人已经写了不少感想,我就不再多说什么了。最遗憾的一件事就是在展波的课堂上答对问题,可因为展波没有带奖品,所以只得到一张免费饮料券(还没舍得用)。
言归正传,TechEd 2004最后一天,卢斌的“透视公共语言运行库”课堂上的一个例子让我记忆犹新,写下来,让大家一起分享(不知算不算侵权?)
这个例子主要是关于开发高效托管代码的例子,程序比较了String与StringBuilder的运行效率。代码如下(凭记忆写的,或许会有所出入):
using System;
using System.Text;
class Test
{
public static void Main(string[] argvs)
{
string s = "";
int n = 0;
if(argvs.Length < 2)
{
PrintHelp();
return;
}
try
{
s = argvs[0];
n = int.Parse(argvs[1]);
}
catch
{
PrintHelp();
}
if(argvs.Length > 2 && argvs[2] == "/o")
StringBuilderTest(s, n);
else
StringTest(s,n);
}
static void PrintHelp()
{
Console.WriteLine("usage: Test <sString> <nTimes> [/o]");
}
static void StringTest(string s, int n)
{
DateTime beginTime = DateTime.Now;
string temp = "";
for(int i=0; i<n; i++)
temp += s;
DateTime endTime = DateTime.Now;
Console.WriteLine(temp);
TimeSpan ts = endTime - beginTime;
Console.WriteLine(" " + ts.TotalMilliseconds + " ms");
}
static void StringBuilderTest(string s, int n)
{
DateTime beginTime = DateTime.Now;
string temp = "";
StringBuilder sb = new StringBuilder(temp, n*s.Length);
for(int i=0; i<n; i++)
sb.Append(s);
temp = sb.ToString();
DateTime endTime = DateTime.Now;
Console.WriteLine(temp);
TimeSpan ts = endTime - beginTime;
Console.WriteLine(" " + ts.TotalMilliseconds + " ms");
}
}
using System.Text;
class Test
{
public static void Main(string[] argvs)
{
string s = "";
int n = 0;
if(argvs.Length < 2)
{
PrintHelp();
return;
}
try
{
s = argvs[0];
n = int.Parse(argvs[1]);
}
catch
{
PrintHelp();
}
if(argvs.Length > 2 && argvs[2] == "/o")
StringBuilderTest(s, n);
else
StringTest(s,n);
}
static void PrintHelp()
{
Console.WriteLine("usage: Test <sString> <nTimes> [/o]");
}
static void StringTest(string s, int n)
{
DateTime beginTime = DateTime.Now;
string temp = "";
for(int i=0; i<n; i++)
temp += s;
DateTime endTime = DateTime.Now;
Console.WriteLine(temp);
TimeSpan ts = endTime - beginTime;
Console.WriteLine(" " + ts.TotalMilliseconds + " ms");
}
static void StringBuilderTest(string s, int n)
{
DateTime beginTime = DateTime.Now;
string temp = "";
StringBuilder sb = new StringBuilder(temp, n*s.Length);
for(int i=0; i<n; i++)
sb.Append(s);
temp = sb.ToString();
DateTime endTime = DateTime.Now;
Console.WriteLine(temp);
TimeSpan ts = endTime - beginTime;
Console.WriteLine(" " + ts.TotalMilliseconds + " ms");
}
}
编译完成后,在命令行下分别通过输入:
Test Hello,China 10000
Test Hello,China 10000 /o
测试String与StringBuilder的效率。你会发现两者效率差异在几千倍以上(我自己的测试结果,相信随着n的增加,这个差异还会增加)。在卢斌的演示中,StringTest会占用近10M的内存并在程序运行期间触发18次垃圾回收。而StringBuilderTest占用几十K内存,没有垃圾回收。
至于为什么会这样,大家可以自己考虑一下。