【发布时间】:2017-05-18 04:41:36
【问题描述】:
正在分析我的代码,发现我们处理彩色控制台文本的方式非常昂贵(大部分运行时)。
DateTime dt = DateTime.Now;
for (int i = 0; i <= 20000; i++)
{
ConsoleColor cf = Console.ForegroundColor;
ConsoleColor cb = Console.BackgroundColor;
Console.ForegroundColor = ConsoleColor.Red;
Console.BackgroundColor = ConsoleColor.Blue;
Console.WriteLine("Hello World");
Console.ForegroundColor = cf;
Console.BackgroundColor = cb;
}
System.Diagnostics.Debug.WriteLine((DateTime.Now - dt).TotalMilliseconds);
这个简单的循环在我的机器上运行需要 2.8 秒。如果我只做 WriteLine,它只有 600 毫秒。
现在,在我得到巨魔答案之前 :) 问为什么我在硬编码时一直设置颜色,这是测试代码,在真实代码中,前景和背景颜色是根据几个不同的因素计算的。那部分无关紧要。这段代码只是假设颜色会发生变化,因此会保存原件,更改颜色,然后将其改回原件。
自从使用 ILSpy 以来,我还尝试通过 pinvoke 使用本机 SetConsoleTextAttribute 方法,似乎 Console.xxx 方法做了很多额外的废话,但我得到的时间大致相同。
【问题讨论】:
-
在控制台中更改一个属性(或者实际上用控制台做任何事情)涉及到 P/Invoking 控制台进程。这样做会引入一些重要的开销是有道理的。
-
@Abion47 我曾经有过 pinvoke 比调用 C# 包装器更快的时候,因为它们做了很多事情来更加防弹,而使用直接 pinvoke 调用,您可以绕过所有这些。 C# 包装器可能只有几百行代码:)。似乎在控制台中更改文本颜色应该是微不足道的。
-
不要使用
DateTime进行时间计算 - 使用Stopwatch。 -
@DanielA.White 虽然一般来说这是一个很好的建议,它不会对 0.6 秒和 2.8 秒产生太大影响。