为什么控制台应用程序和 WinForms 之间的性能差异如此之大?
Why do I have such a large performance difference between a Console app and WinForms?
我写了一些简单的 C# 代码来测试一个数是否是素数。当我 运行 WinForms 应用程序中的代码与控制台应用程序中的代码时,我很惊讶地发现性能存在巨大差异。
代码非常简单:
ulong num = 18446744073709551557;
Stopwatch stopwatch = Stopwatch.StartNew();
if (num % 2 == 0)
{
stopwatch.Stop();
MessageBox.Show("Composite " + stopwatch.ElapsedMilliseconds.ToString());
return;
}
for (ulong i = 3; i <= Math.Sqrt(num); i += 2)
{
if (num % i == 0)
{
stopwatch.Stop();
MessageBox.Show("Composite " + stopwatch.ElapsedMilliseconds.ToString());
return;
}
}
stopwatch.Stop();
MessageBox.Show("Prime " + stopwatch.ElapsedMilliseconds.ToString());
对于控制台应用程序,我使用 Console.WriteLine()
而不是 MessageBox.Show()
。现在我原以为性能差异可以忽略不计。但是,控制台应用程序的性能似乎始终不如 windows 表单应用程序。
由 Visual Studio 2022 编译,对于调试版本(运行 无调试),winforms 应用程序需要约 36000 毫秒,但控制台应用程序需要约 156000 毫秒。对于发布版本(运行 无调试),Winforms 约 35500 毫秒,控制台约 137000 毫秒。 (有趣的是,如果 运行 使用 调试,两者似乎 运行 稍微快一点。)这种差异的原因是什么?
我无法重现问题。
这里是我在发布时的发现 运行 的总结,没有调试器(VS 中的 Ctrl-F5)。 Console 和 WinForms 的 32 位和 64 位进程之间存在显着差异。
IDE
Platform
Console
WinForms
VS2017/NET 4.8
x32
43.94 sec
43.21 sec
VS2017/NET 4.8
x64
4.43 sec
4.38 sec
VS2022/NET 4.8
x32
43.62 sec
43.33 sec
VS2022/NET 4.8
x64
4.56 sec
4.45 sec
VS2022/NET 6.0
x64
4.46 sec
4.45 sec
注意:console 和 winforms 之间的差异在噪声范围内。
代码
两个项目的测试代码相同
internal static bool IsPrimeTest(ulong num)
{
if (num == 2)
{
return true;
}
if (num % 2 == 0)
{
return false;
}
for (ulong i = 3; i <= Math.Sqrt(num); i += 2)
{
if (num % i == 0)
{
return false;
}
}
return true;
}
和亚军
private void button1_Click(object sender, EventArgs e)
{
button1.Enabled = false;
ulong x = 18446744073709551557ul;
textBox1.Text = "Burn-in";
Program.IsPrimeTest(x / 16);
textBox1.Text = "Start timming";
var sw = Stopwatch.StartNew();
bool ok = Program.IsPrimeTest(x);
sw.Stop();
string bits = Environment.Is64BitProcess ? "x64" : "x32";
textBox1.Text = $"Bits={bits}, Prime={ok}, Time={sw.Elapsed.TotalSeconds:f2} sec";
button1.Enabled = true;
}
有趣 side-note,使用 Intel Fortran 进行的类似测试产生了 Time = 3.80 sec
,它仅比 C# 快一点。诚然,Fortran 不支持无符号整数,因此必须使用全精度浮点数进行检查。每个 mod(x,p)==0
调用都被翻译成 x/p == int(x/p)
.
我写了一些简单的 C# 代码来测试一个数是否是素数。当我 运行 WinForms 应用程序中的代码与控制台应用程序中的代码时,我很惊讶地发现性能存在巨大差异。
代码非常简单:
ulong num = 18446744073709551557;
Stopwatch stopwatch = Stopwatch.StartNew();
if (num % 2 == 0)
{
stopwatch.Stop();
MessageBox.Show("Composite " + stopwatch.ElapsedMilliseconds.ToString());
return;
}
for (ulong i = 3; i <= Math.Sqrt(num); i += 2)
{
if (num % i == 0)
{
stopwatch.Stop();
MessageBox.Show("Composite " + stopwatch.ElapsedMilliseconds.ToString());
return;
}
}
stopwatch.Stop();
MessageBox.Show("Prime " + stopwatch.ElapsedMilliseconds.ToString());
对于控制台应用程序,我使用 Console.WriteLine()
而不是 MessageBox.Show()
。现在我原以为性能差异可以忽略不计。但是,控制台应用程序的性能似乎始终不如 windows 表单应用程序。
由 Visual Studio 2022 编译,对于调试版本(运行 无调试),winforms 应用程序需要约 36000 毫秒,但控制台应用程序需要约 156000 毫秒。对于发布版本(运行 无调试),Winforms 约 35500 毫秒,控制台约 137000 毫秒。 (有趣的是,如果 运行 使用 调试,两者似乎 运行 稍微快一点。)这种差异的原因是什么?
我无法重现问题。
这里是我在发布时的发现 运行 的总结,没有调试器(VS 中的 Ctrl-F5)。 Console 和 WinForms 的 32 位和 64 位进程之间存在显着差异。
IDE | Platform | Console | WinForms |
---|---|---|---|
VS2017/NET 4.8 | x32 | 43.94 sec | 43.21 sec |
VS2017/NET 4.8 | x64 | 4.43 sec | 4.38 sec |
VS2022/NET 4.8 | x32 | 43.62 sec | 43.33 sec |
VS2022/NET 4.8 | x64 | 4.56 sec | 4.45 sec |
VS2022/NET 6.0 | x64 | 4.46 sec | 4.45 sec |
注意:console 和 winforms 之间的差异在噪声范围内。
代码
两个项目的测试代码相同
internal static bool IsPrimeTest(ulong num)
{
if (num == 2)
{
return true;
}
if (num % 2 == 0)
{
return false;
}
for (ulong i = 3; i <= Math.Sqrt(num); i += 2)
{
if (num % i == 0)
{
return false;
}
}
return true;
}
和亚军
private void button1_Click(object sender, EventArgs e)
{
button1.Enabled = false;
ulong x = 18446744073709551557ul;
textBox1.Text = "Burn-in";
Program.IsPrimeTest(x / 16);
textBox1.Text = "Start timming";
var sw = Stopwatch.StartNew();
bool ok = Program.IsPrimeTest(x);
sw.Stop();
string bits = Environment.Is64BitProcess ? "x64" : "x32";
textBox1.Text = $"Bits={bits}, Prime={ok}, Time={sw.Elapsed.TotalSeconds:f2} sec";
button1.Enabled = true;
}
有趣 side-note,使用 Intel Fortran 进行的类似测试产生了 Time = 3.80 sec
,它仅比 C# 快一点。诚然,Fortran 不支持无符号整数,因此必须使用全精度浮点数进行检查。每个 mod(x,p)==0
调用都被翻译成 x/p == int(x/p)
.