管理対象vs .Netネイティブコードに奇妙な違いがあります。私はスレッドプールにリダイレクトされた重い仕事をしています。アプリケーションをマネージコードで実行すると、すべてがスムーズに機能しますが、ネイティブコンパイルをオンにするとすぐに、タスクはUIスレッドをハングアップするほど遅く、遅くなります(CPUが非常にオーバーロードされていると思います)。.Netネイティブのスレッドプールで実行される非同期タスクのパフォーマンスが非常に悪い
ここにはデバッグ出力の2つのスクリーンショットがあり、左側のコードはマネージコードのもので、右側のコードはネイティブコンパイルのものです。表示されているように、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ネイティブコンパイラとランタイムチームを担当しています。私たちは通常、この種の調査にPerfViewを使用します。いくつかのetlトレース(1つは.netのネイティブと1つありません)を収集し、私たちの方法([email protected])を送信すると、誰かに見てもらえるようになります。 –
スレッドプールの飢餓である可能性があります。 'ThreadPool.SetMinThreads/SetMaxThreads'で遊んだことはありますか? – Noseratio