.Net Core のユビキタスな Async/Await はどのようにパフォーマンスを向上させるのでしょうか?

1. はじめに

Async/Await は .Net Core では実際に広く普及しており、どこにでも非同期操作が存在します。なぜそれを使用するのでしょうか? 効果は何ですか?パフォーマンスが向上する可能性があると言う人もいますか?インターネット上の記事をたくさん読んだ後、めまいがしてよくわかりませんでした。

そこで、ここでは理論、実践、原理からこれらの疑問を一つずつ解決していきます。

2. Async/Await の用途は何ですか?

1. Async/Awaitの使用例

使い方は非常に簡単なので、ここでは詳細な使い方は説明しませんが、例を示し、その機能を研究することが目的です。

 public class AsyncAwaitTest
    {
        public void Start()
        {
            Console.WriteLine($"aaa,线程Id:{Thread.CurrentThread.ManagedThreadId}");
            AsyncMethod();
            Console.WriteLine($"eee,线程Id:{Thread.CurrentThread.ManagedThreadId}");
            Console.ReadLine();
        }
        public async Task<bool> AsyncMethod()
        {
            Console.WriteLine($"bbb,线程Id:{Thread.CurrentThread.ManagedThreadId}");
            await Task.Run(() => {

                Thread.Sleep(500);
                Console.WriteLine($"ccc,线程Id:{Thread.CurrentThread.ManagedThreadId}");
            });
            Console.WriteLine($"ddd,线程Id:{Thread.CurrentThread.ManagedThreadId}");
            return true;
        }
    }

2. async/awaitの特徴

1) スレッドをブロックしません

この例の実行シーケンスから、async/await メソッドが実行されると、メイン スレッドが await キーワードに遭遇し、メイン スレッドが "eee" の実行に戻り、待機する代わりに新しいメソッドを解放することがわかります。サブスレッドは 6 を実行するために開かれます。 他のビジネスの場合、await 前のメソッドは引き続きメイン スレッドによって実行され、await の後のメソッドはスレッド 6 の実行が終了した後も実行され続けます。

2) 同期方式で非同期に書き込む

非同期が使用されていますが、実行結果を待ってから続行され、実行プロセスは同期されます。

3. async/await はパフォーマンスを向上させることができますか?

これは誰もが最大の懸念を抱いているはずです。

単一リクエストのパフォーマンスを向上させることはできますか?

答えはいいえだ。await は結果を待って後続のロジックを実行していることがわかりますが、シリアルのままで、何秒実行すればよいのか、途中でスレッドが処理に切り替わります。同期に比べてロスが多くなります。スレッドを切り替えます。

では、async/await には何の意味があるのでしょうか?

複数のリクエストが同時に処理され、リソースが制限されている場合、スループット (単位時間あたりに処理されるリクエスト) が増加し、CPU 使用率が増加する可能性があります。

簡単に言えば、スレッドが 10 個あり、各スレッドの速度が改善されていない場合、QPS は改善できるでしょうか?

Microsoftの公式Webサイトの説明を見てみましょう

  このモデルは、一般的なサーバー シナリオのワークロードを適切に処理します。未処理のタスクをブロックする専用のスレッドがないため、サーバー スレッド プールはより多くの Web リクエストを処理できます。

  2 つのサーバーの使用を検討してください。1 つは非同期コードを実行し、もう 1 つは非同期コードを実行しません。この例では、サーバー要求に使用できるスレッドはサーバーごとに 5 つだけです。この単語数は実用するには少なすぎるため、デモンストレーションのみを目的としています。

  両方のサーバーが 6 つのリクエストを同時に受信するとします。各リクエストは I/O 操作を実行します。非同期コードを実行していないサーバーは、5 つのスレッドのうちの 1 つが I/O 集中型の作業を完了するまで、6 番目のリクエストをキューに入れる必要があります。

そして返事を書きました。この時点で 20 番目のリクエストが受信され、長いキューによりサーバーの速度が低下し始める可能性があります。

  非同期コードを実行しているサーバーも 6 番目のリクエストをキューに入れる必要がありますが、async と await を使用しているため、I/O 集中型の作業が開始されると、作業の終了を待たずにすべてのスレッドが解放されます。

20 番目のリクエストが受信されるまでに、受信リクエストのキューは (それ以上ある場合でも) 小さくなり、サーバーは遅くなりません。

  これは不自然な例ですが、現実の世界でも同様に機能します。実際、async と await を使用すると、サーバーは受信する各リクエストに専用のスレッドを割り当てることができます。

サーバーは桁違いのリクエストを処理します。

  上記の公式 Web サイトで説明されている I/O 集中に注意してください。I/O集中型とは何ですか? つまり、CPU のパフォーマンスはハードディスク メモリよりもはるかに優れており、ほとんどの時間、CPU は IO 読み取りおよび書き込み操作を待機しています。たとえば、ファイルを読み取る場合、CPU はファイルの読み取りに参加する必要はありません。ハードディスクにコマンドを送信するだけで済みます。ハードディスクがファイルを読み取ると、CPU に処理を続行するように通知されます。は DMAテクノロジーと呼ばれます。

  DMA (ダイレクト メモリ アクセス) は、現代のすべてのコンピュータの重要な機能です。これは、CPU を介したり、CPU の介入を必要とせずに、外部デバイスとメモリの間でデータを直接読み書きできる高速データ転送操作を指します。 。

  このとき、非同期の利点が現れ、ファイルの読み込みに 1 秒かかりますが、同期操作の場合は、1 秒待ってから実行するスレッドが存在します。非同期の場合、ファイルが読み取られるとスレッドが解放されます。ファイルが読み取られた後、ハードディスクは CPU に別のスレッドを送信して処理を続行するように通知します。中央の 1 秒間は、元のスレッドが他のリクエストを処理できます。

4. コード比較命令

同期リクエストの処理は、

 ハードディスクがファイルを読み取っている間、スレッドは待機していることがわかりますが、このとき、スレッド 1 はこの 1 秒間は動作せず、アイドル状態になっています。

非同期リクエストの処理は、

 非同期リクエストが行われると、スレッド 1 は await キーワードに遭遇し、コマンド発行後に戻り、解放します。ハードディスクがデータを読み取った後、CPU に通知します。このとき、CPU は新しいスレッドを処理を続行します。

そのため、ファイルを読み込む 1 秒間は、スレッド 1 が他のリクエストを処理でき、待ち時間がなくなるため、cpu の使用率が向上し、単位時間あたりに処理されるリクエストの数が増加します。

CPU を大量に使用する非同期では QPS を向上させることはできません。次のコードは CPU を大量に使用します。

CPU 集約型:計算集約型、ハードディスク、メモリのパフォーマンスが CPU よりもはるかに優れているか、I/O デバイスへのアクセスの必要性が低くなります。

public class HomeController : Controller
    {
        /// <summary>
        /// 同步请求
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        public string GetData()
        {
            var result = System.IO.File.ReadAllBytes(@"F:\package\package.rar");
            return "ok";
        }

        /// <summary>
        /// 异步请求
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        public async Task<string> GetDataAsync2()
        {
            var result = await System.IO.File.ReadAllBytesAsync(@"F:\package\package.rar");
            return "ok";
        }
    }
     /// <summary>
        /// 异步请求
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        public async Task<string> GetDataAsync2()
        {
            await Task.Run(() => {
                Thread.Sleep(100);//模拟业务处理耗时
            });
            return "ok";
        }

ここで、メインスレッドは await に遭遇しましたが、解放されましたが、動作を継続するために await 内に別のスレッドがあり、CPU (スレッド) はアイドル状態ではありません。

I/O 集中型の IO 操作とは何ですか?

ファイルの読み取りと書き込み、http リクエスト、データベース リクエスト、redis リクエスト。

 開発における非同期にはどれが推奨されますか?

非同期 API、アクション、フィルター、データベース アクセス、ミドルウェアなどを使用した Web 開発の推奨事項


転載元: https://www.cnblogs.com/wei325/p/15957951.html

おすすめ

転載: blog.csdn.net/u014683833/article/details/123430370