3

虽然检查输入是否为字符串类型的问题已关闭,但其中两个答案在我脑海中引发了一个微优化问题:以下两种解决方案中哪一种表现更好?

Reed Copsey提供了一个解决方案,使用Char.IsLetter

string myString = "RandomStringOfLetters";
bool allLetters = myString.All( c => Char.IsLetter(c) );

使用来自Mark Byers的正则表达式改编的解决方案:

string s = "RandomStringOfLetters";
bool allLetters = Regex.IsMatch(s, "^[a-z]+$", RegexOptions.IgnoreCase);

不想只问 Reed 或 Mark 的问题,我想我会写一个快速测试来确定哪个表现更好。问题是我没有做很多代码优化(我倾向于把代码可读性放在首位)。

除了在每个运行之前和之后获取时间戳之外,还有哪些其他(更好的?)选项可以确定哪个解决方案运行得更快?

编辑

我修改了Martin 的答案以使用Console.WriteLine(...)并将其作为控制台应用程序运行。不确定LinqPad如何运行应用程序,但结果大致相同:

41
178
4

6 回答 6

7

您需要这样做,使用Stopwatch测量运行时间。此外,在进行分析时,请记住以下一些非常重要的事情:

  1. 始终运行测试超过 1 次。第一次运行它时,JIT 会产生开销,而且时间可能会产生误导。多次运行并取平均值是一个好方法(例如,我经常会运行这样的测试 100,000 次。)
  2. 始终在 Visual Studio 托管过程之外使用完整的发布版本运行测试。(默认情况下,您可以为此使用 Ctrl+F5。)Visual Studio 主机会显着影响时间。
于 2010-07-21T16:04:07.787 回答
2

你应该看看System.Diagnostics.Stopwatch

http://msdn.microsoft.com/en-us/library/system.diagnostics.stopwatch.aspx

你应该在一个循环中多次运行这个东西,以减少时序错误和其他不可控因素。

希望有帮助。

于 2010-07-21T16:01:35.500 回答
2

我只是把它放在LINQPad中作为我如何做的一个例子(因此调用 Dump() - 如果你不使用这个方便的工具,请用 Console.WriteLine(...) 替换)。

看起来 LINQ 的方式稍微快了四倍多:

System.Diagnostics.Stopwatch stopwatch = new Stopwatch();

stopwatch.Start();
for (int i = 0; i < 100000; i++)
{
 string myString = "RandomStringOfLetters";
 bool allLetters = myString.All( c => Char.IsLetter(c) );
}
stopwatch.Stop();
stopwatch.ElapsedMilliseconds.Dump();

stopwatch.Reset();

stopwatch.Start();
for (int i = 0; i < 100000; i++)
{
 string s = "RandomStringOfLetters";
 bool allLetters = Regex.IsMatch(s, "^[a-z]+$", RegexOptions.IgnoreCase);
}
stopwatch.Stop();
stopwatch.ElapsedMilliseconds.Dump();

输出:

47 
196
于 2010-07-21T16:06:59.653 回答
0

有一个可以使用的 System.Diagnostics.Stopwatch 类。

无论您测试什么代码,都运行一次测试以消除 JIT 成本,然后再次运行它以获得最终时间。由于 PC 上的其他因素,大多数单独的计时计数可能不具代表性 - 因此运行多次迭代,然后从中计算平均运行时间。

于 2010-07-21T16:02:49.207 回答
0

使用 System.Diagnostics.Stopwatch 类。

启动 StopWatch 并运行数千次迭代,停止它并检查已过去的总毫秒数

于 2010-07-21T16:03:04.260 回答
0

确定哪个更快的步骤:-

  1. 获取一组计算机,应该有几百台,AMD/Intel/其他,32 位/64 位,...

  2. 在它们每个上安装您关心的每个 .NET 框架(依次)

  3. 尝试每种优化选项的组合进行编译(依次)

  4. 使用 StopWatch 测试每个运行的大型运行

  5. 监控每个内存的使用情况,因为这可能会对应用程序的其余部分产生更大的影响。以增加内存消耗和更多垃圾收集活动为代价来节省几个周期通常是一个糟糕的“优化”。

可能会让您知道在实践中哪个更快,至少对于当前版本的编译器。对编译器的每个新版本重复此操作。

于 2010-07-21T16:08:58.877 回答