我在管理的vs .net本機代碼中觀察到了一個奇怪的差異。我有一個重要的工作重定向到線程池。在託管代碼中運行應用程序時,一切運行平穩,但只要我打開本機編譯 - 任務運行速度會慢幾倍,速度太慢,導致UI線程掛起(我猜CPU太重了)。在.Net本身的線程池上運行異步任務的性能很差
這裏有兩個來自調試輸出的截圖,左邊的一個來自託管代碼,右邊的來自本地編譯。正如你所看到的,在這兩種情況下,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和機器碼。 – Rob
我在.NET Native Compiler和Runtime團隊工作。我們通常使用PerfView進行這些調查。如果你可以收集一些etl的痕跡(一個是.net native和一個沒有的),然後以我們的方式發送給我們([email protected]),我們會讓人們看看它。 –
可能是一個線程池飢餓。你玩過「ThreadPool.SetMinThreads/SetMaxThreads」嗎? – Noseratio