为什么Console.WriteLine的速度比Debug.WriteLine更不一致?

Why is the speed of Console.WriteLine more inconsistent than Debug.WriteLine?

此代码输出几乎全为 0,偶尔输出 3-5。

For i As Integer = 1 To 1000
    Dim Watch As Stopwatch = Stopwatch.StartNew()
    Debug.WriteLine(Watch.ElapsedMilliseconds & " - Processing Time1")
    Debug.WriteLine(Watch.ElapsedMilliseconds & " - Processing Time2")
Next

此代码输出几乎全为 0,偶尔输出 200。

For i As Integer = 1 To 1000
    Dim Watch As Stopwatch = Stopwatch.StartNew()
    Console.WriteLine(Watch.ElapsedMilliseconds & " - Processing Time1")
    Console.WriteLine(Watch.ElapsedMilliseconds & " - Processing Time2")
Next

知道为什么吗?

唯一的区别是 Console.WriteLine。此外,出于某种原因,似乎每个循环有两个 WriteLines 很重要。

我在尝试对我的代码速度进行计时时发现了这一点,并且在一个循环中出现了看似随机的 150 毫秒尖峰。

幸运的是微软已经发布了.NET平台的源代码here

快速检查显示 Debug.Writeline 使用 TraceInternal class 的 Writeline 方法。你可以看一个例子here and the TraceInternal method here

如您所见,有很多事情正在发生,涉及挂钩的 TraceListeners、锁等。所以我们可以假设 Debug.WriteLine 通常应该更慢,但前提是有任何 "extra"配置的 TraceListeners,当然还有其他 IDE 参数,它们以某种方式干扰调试基础结构。

Console.WriteLine method uses the TextWriter.WriteLine 方法被设计为快速(至少尽可能快,看看他们的评论)。

关于您提出的不一致问题不容易回答(在我看来您不应该尝试回答),原因有以下三个:

  1. 当您使用高级语言或平台进行开发时 .NET 那你就不用管多少时间了 "internals" 采取,因为你不能对他们有任何控制。我的意思是你 除非您自己编写,否则无法使 WriteLine 方法更快 "faster" 个版本,但这超出了使用高级别的目的 无论如何平台。我希望你能在这里看到我的观点。
  2. 当你使用一些方法(比如WriteLine)来输出 你的一些其他代码执行的时间那么你应该 不在乎输出方法需要多少时间来完成 因为结果是准确的。例如,如果 WriteLine 需要 2 秒来向您显示您正在测量的代码需要 1 毫秒才能完成,那么即使您等待 2 秒才能找到它,1 毫秒也很重要。如果输出方法太慢,那么你应该改变你的测量方法,例如,在你的循环中有一个计数器变量并在它的末尾显示(WriteLine)结果可能会更快。
  3. 当您开发旨在 运行 进行多任务处理的软件时 像 windows 这样的系统你不应该期望相同的代码会 总是每次都花同样的时间执行,因为有 有大量其他(在您的应用程序之外)可以(并且将会)的参数 影响系统的整体性能。这就是为什么(我相信你已经知道了)我们在一个非常容易访问的地方(LOL)有重启选项。

尽管如此,为了最终确定我的答案,您的时间不一致取决于许多因素,这些因素使得找出它发生的原因变得毫无价值。但是,在您的代码中,我注意到您使用的是语句:

Dim Watch As Stopwatch = Stopwatch.StartNew()

在循环内部这是一件坏事,因为正如您在秒表代码中看到的那样 here 它每次都会创建一个新实例,这是一项耗时的操作。我相信如果你把它放在循环之外,比如:

Dim Watch As Stopwatch = Stopwatch.StartNew()
For i As Integer = 1 To 1000
    Debug.WriteLine(Watch.ElapsedMilliseconds & " - Processing Time1")
    Debug.WriteLine(Watch.ElapsedMilliseconds & " - Processing Time2")
Next

您会得到更多 "consistent" 结果,但我还没有测试过。此外,使用像

这样的更高的时间分辨率可能更明智
Watch.ElapsedTicks

因为它会给你更准确的结果,因为如果你查看源代码 here ElapsedMilliseconds 使用略有不同的版本(可能更慢)的 ElapsedTicks 来计算毫秒数。

希望这对您有所帮助。