我有一个带有很多
WriteLine()
功能的控制台应用程序,这个应用程序也应该作为“服务”运行(计划任务,运行时用户未登录)。
在这种情况下,没有实际的 cmd 窗口可显示。在这种情况下,
Console.WriteLine()
仍然会导致明显的性能损失吗?
是的即使控制台不可见也会导致性能损失
我的实验是在控制台可见的情况下运行这段代码,然后在控制台隐藏的情况下再次运行并测量性能
首次运行控制台可见24683毫秒
第二次运行控制台可见23363毫秒
首次运行控制台隐藏167毫秒
第二次运行控制台隐藏162毫秒
static void Main(string[] args)
{
WriteMilionLines();
}
static void WriteMilionLines()
{
Stopwatch sw = new Stopwatch();
sw.Start();
for (int i = 0; i < 1000000; i++)
{
Console.WriteLine(i);
}
sw.Stop();
string message = "ElapsedMilliseconds" + sw.ElapsedMilliseconds;
File.WriteAllText(@"c:\log.txt", message);
}
通过注释
Console.WriteLine(i);
行,将需要零毫秒
不,不会被注意到。除非您的应用程序完成了 99%
Console.WriteLine()
并且几乎没有执行任何其他操作,否则差异可以忽略不计。
如果您仍然担心性能,您可以将控制台调用包装到您可以控制的方法中,并测量应用程序经历的总时间,甚至引入一个开关(布尔变量)来控制其调用。
虽然这是一个老话题,但我为任何重新审视这个问题的人提供这个答案。
答案是:Console.Writeline 总是有成本,但它是否重要,取决于您在 Console.Writeline 中作为参数的内容。
这是因为无论您是否启用了 stdout,Writeline 函数都会被调用,并且会计算其中的参数。因此,当您启用或禁用标准输出时,唯一改变的是写入标准输出(cmd 或文件)的额外成本
为了理解问题,请运行以下示例:
using System;
using System.Diagnostics;
using System.IO;
public class Program
{
public static void Main()
{
Stopwatch sw = new Stopwatch();
Console.SetOut(TextWriter.Null);
sw.Start();
Console.WriteLine("1000000");
sw.Stop();
Console.SetOut(Console.Error);
Console.WriteLine("Elapsed Milliseconds (1): " +
sw.ElapsedMilliseconds);
Console.SetOut(TextWriter.Null);
sw.Restart();
Console.WriteLine(CountToBillion());
sw.Stop();
Console.SetOut(Console.Error);
Console.WriteLine("Elapsed Milliseconds (2): " +
sw.ElapsedMilliseconds);
}
static string CountToBillion()
{
var s = 0;
for (int i = 0; i < 1000000000; i++)
{
s=i;
}
return s.ToString();
}
}
您可以看到,在 stdout 上写入一个简单的字符串需要 0 毫秒(或者可能是 1 毫秒,具体取决于您的硬件),而写入像上面这样的耗时函数的结果则需要 1500-2000 毫秒,即使 stdout 已禁用。
如果您从数据库访问数据,将它们作为 IEnumerable 获取,并错误地在 Console.WriteLine 中调用 ToList(),并且认为如果禁用了 stdout,这不会影响您,则此成本变得更加显着。它不仅可能导致显着的延迟,而且还会导致通过延迟加载应用对数据的任何后续查询。
这就是为什么您应该始终考虑使用记录器而不是 console.writeline,在这种情况下,例如,如果应用程序未在调试模式下运行等,则对 Log.Debug 参数的评估将被完全忽略。