【发布时间】:2016-04-12 11:50:19
【问题描述】:
我观察到托管代码与 .Net 本机代码的奇怪差异。我有一项繁重的工作被重定向到线程池。在托管代码中运行应用程序时,一切都很顺利,但只要我打开本机编译 - 任务运行速度会慢几倍,而且速度很慢,以至于它挂起了 UI 线程(我猜 CPU 已经超载了)。
这里有两张来自调试输出的截图,左边一张来自托管代码,右边一张来自本机编译。如您所见,两种情况下 UI 任务消耗的时间几乎相同,直到线程池作业启动时 - 然后在托管版本中,UI 运行时间会增加(实际上 UI 被阻塞,您无法采取任何操作)。线程池工作的时间不言自明。
重现问题的示例代码:
private int max = 2000;
private async void UIJob_Click(object sender, RoutedEventArgs e)
{
IProgress<int> progress = new Progress<int>((p) => { MyProgressBar.Value = (double)p / max; });
await Task.Run(async () => { await SomeUIJob(progress); });
}
private async Task SomeUIJob(IProgress<int> progress)
{
Stopwatch watch = new Stopwatch();
watch.Start();
for (int i = 0; i < max; i++)
{
if (i % 100 == 0) { Debug.WriteLine($" UI time elapsed => {watch.ElapsedMilliseconds}"); watch.Restart(); }
await Task.Delay(1);
progress.Report(i);
}
}
private async void ThreadpoolJob_Click(object sender, RoutedEventArgs e)
{
Debug.WriteLine("Firing on Threadpool");
await Task.Run(() =>
{
double a = 0.314;
Stopwatch watch = new Stopwatch();
watch.Start();
for (int i = 0; i < 50000000; i++)
{
a = Math.Sqrt(a) + Math.Sqrt(a + 1) + i;
if (i % 10000000 == 0) { Debug.WriteLine($"Threadpool -> a value = {a} got in {watch.ElapsedMilliseconds} ms"); watch.Restart(); };
}
});
Debug.WriteLine("Finished with Threadpool");
}
如果您需要完整的样本 - 那么您可以download it here。
正如我测试的那样,无论是在调试版本还是发布版本中,优化/非优化代码都会出现差异。
有人知道什么会导致问题吗?
【问题讨论】:
-
可能需要看看发出的 IL 和机器码。
-
我在 .NET Native Compiler and Runtime 团队工作。我们通常使用 PerfView 进行此类调查。如果您可以收集一些 etl 跟踪(一个带有 .net native 和一个不带)并将它们发送到我们的方式 (dotnetnative@microsoft.com),我们会找人看一看。
-
可能是线程池不足。你玩过
ThreadPool.SetMinThreads/SetMaxThreads吗? -
@Noseratio 好像在 UWP 中没有控制线程数的选项。
-
@MattWhilden 我已经向您提到的地址发送了一封电子邮件。我观察到这主要是针对部署在 ARM 设备上的应用程序 - 是否可以为此类进程运行 perview?
标签: c# async-await win-universal-app uwp .net-native