この記事は機械翻訳のミラー記事です。元の記事にジャンプするにはこちらをクリックしてください。

眺める: 15343|答える: 2

[通信] [翻訳] ValueTaskとTaskの違いを用いるためのNET

[リンクをコピー]
2022年3月17日 11:21:50に投稿 | | | |


タスクやタスククラスの使用には、以前の記事で触れなかったパフォーマンスのボトルネックがあります。 要するに、これらのクラスは結果がすぐに出るときにリードします不必要な割り当て。 つまり、結果がすでに利用可能であっても、常に新しいタスクやタスクオブジェクトが作成されます。 さて、以前の記事で使った非同期/待機の概念は.NET 4.5リリース以来続いていると述べました。 この機能はC# 7以降、非同期関数のリターンとして使えるValueTask構造を持つ.NET 4.7バージョンで強化されています。

ValueTaskの構造


ValueTask構造は2015年にcorefxlabリポジトリに初めて登場しました。 このリポジトリは、メインのcorefxリポジトリに届くかどうかは分からない新しいアイデアを実験し探求するために使われます。 Corefxリポジトリは、すべての.NET Coreベースライブラリが収められているリポジトリです。 これはStephen TaubによってSystem.Threading.Tasks.Channelsライブラリのために開発・提案されました。 その時、スティーブンは簡単な説明をしました。

coreFXlabライブラリアドレス:ハイパーリンクのログインが見えます。


ValueTaskはTとタスクの独立した合同であり、ReadAsyncは利用可能なT値を自由に割り当てて同期的に返すことができます(Task.FromResultを使う場合とは異なり、タスクインスタンスの割り当てが必要です)。 ValueTaskは待機可能なので、ほとんどのインスタンスの消費はタスクの消費と区別がつきません。
多くの人がこの構造を使う利点を感じており、System.Threading.Tasks.ExtensionsのNuGetパッケージの一部としてC# 7に含まれています。 では、ValueTaskの構造に入る前に、解決するために使われる問題を見てみましょう。 Task(Task)は参照タイプなので、まず非同期メソッドがタスクオブジェクトを返すということは、タスクオブジェクトが毎回ヒープに割り当てられることを意味します。 これは多くの場合必要なことです。

しかし、場合によっては非同期メソッドが即時または同期的に結果を返すこともあります。 このような場合、この割り当ては不要であり、コードの性能に重要な部分ではコストがかかることがあります。 .NET 4.7リリースまでは、非同期メソッドはTask、Task、またはvoidを返す必要があり<T>(後者は通常望ましくない)、これを回避する方法はありませんでした。 この.NETバージョンでは、非同期メソッドがGetAwaiterメソッドにアクセスできる限り任意の型を返すことができます。 ValueTaskはこのタイプの具体例であり、このリリースにも追加されました。

corefxリポジトリを閲覧すると、ValueTaskの完全な実装を見ることができます。こちらが私たちが興味を持っているAPIセクションです:



構造として、ValueTaskは同期実行時にメモリを割り当てない非同期メソッドの作成を可能にします。 非同期/awaitの概念のAPI一貫性はこの方法で損なわれません。 さらに、この構造は単独で待機できるため、使いやすくなっています。 例えば、次の簡単なコードを実行すると:

MultiplyAsyncメソッドでは、Taskを使わず単純な整数だけを返したい状況をシミュレートしています。 これはメソッドのif文で行い、基本的にパスされたパラメータがゼロかどうかを確認します。 問題はif文の条件が真であっても、上記のコードはタスクオブジェクトを作成します。 この問題をこう解決します:

ValueTaskとTask



前述の通り、ValueTaskを使う主な利点は2つあります。

  • 性能向上
  • 実装の柔軟性を高める


では、パフォーマンス向上の背後にある数字とは何でしょうか? このコードをご覧ください:


このコードを実行すると、JITの実行に120nsかかります。 ここで、TaskをValueTaskに置き換えると、次のようにします。

JITでは実行時間が65nsとなります。 確かにTask.Delayのため同期実行はしていませんが、実行時間は改善されています。

もう一つの利点は、実施の柔軟性が高まることです。 では、これは具体的に何を意味するのでしょうか? 同期されるべき非同期インターフェースの実装は、Task.RunやTask.FromResultを強制的に使わざるを得なくなります。 もちろん、これが先ほど話したパフォーマンスの問題につながります。 ValueTaskを使うと、同期型か非同期型のどちらかを選ぶ傾向が強いです。 もしそうなら、コードがうまく設計されていないサインかもしれません。

例えば、次のインターフェースを見てください:


例えば、コードからこう呼びたいとしましょう:

インターフェースでValueTaskを使用しているため、インターフェースの実装は同期型または非同期型で行うことができます。 この利点は、同期動作を処理する関数をIThingに追加するのを基本的に省略することで得られます。 この方法の方がはるかに使いやすいインターフェースです。 以下は上記のインターフェースの同期実装です:

同じインターフェースの非同期実装例はこちらです:

しかし、ValueTaskを使用する前にいくつかのトレードオフを考慮する必要があります。 ValueTaskをデフォルトで使うべきだと思いがちですが、実際はそうではありません。 例えば、ValueTaskは結果同期が可能な場合に不要な割り当てを避けるのに役立ちますが、同時に2つのフィールドも含んでいます。

ここで使っている構造は、価値タイプとそのすべての負担を使っていることを忘れてはなりません。 一方、タスクはフィールドが1つだけの参照タイプです。ValueTaskを使うと、より多くのデータを処理・処理できます。 このようなメソッドが非同期方式で待機される場合、非同期メソッドは次のようになります。状態機械もより大きくなります、構造全体を格納するには単一の参照を格納するよりも通常多くのスペースが必要になるためです。

だからこそ、Microsoftの人々は非同期メソッドのデフォルトリターンタイプとしてTaskやTaskを使うことを推奨しているのです。 パフォーマンス分析の後で初めてValueTaskへの切り替えを検討すべきです。


概要

ValueTaskは.NET 4.7で導入された構造で、.NETで非同期メソッドを使える多くの可能性を提供します。 しかし、それには代償が伴います。 これは同期実行されるパフォーマンスクリティカルメソッドに有用です。 これらを使うことで、不要なオブジェクトの割り当てを避けられます。 それでも、価値タイプとしては通常抱える問題を抱えています。 したがって、この構造から恩恵を受けることはできますが、注意が必要です。

元の住所:ハイパーリンクのログインが見えます。




先の:【実践的行動】Dockerを使ってIPsec VPNサーバーを構築する
次に:ルーティングテーブルロックを避けるためにCisco AnyConnectではなくOpenConnectを使うようにしましょう
2022年3月18日 22:21:57に投稿 |
また学びに来た。
2022年3月22日 14:05:53に投稿 |
学びの本質を学びましょう悪くありません
免責事項:
Code Farmer Networkが発行するすべてのソフトウェア、プログラミング資料、記事は学習および研究目的のみを目的としています。 上記の内容は商業的または違法な目的で使用されてはならず、そうでなければ利用者はすべての結果を負うことになります。 このサイトの情報はインターネットからのものであり、著作権紛争はこのサイトとは関係ありません。 ダウンロード後24時間以内に上記の内容を完全にパソコンから削除してください。 もしこのプログラムを気に入ったら、正規のソフトウェアを支持し、登録を購入し、より良い本物のサービスを受けてください。 もし侵害があれば、メールでご連絡ください。

Mail To:help@itsvse.com