2016-10-29 1 views
0

ベースのTaskにはResultがなく、Tを指定してダミー値を設定する必要があります。このように:結果が実際に必要でない場合、TaskCompletionSourceに使用するジェネリック型の引数

Task SomethingAsync() { 
var tcs = new TaskCompletionSource<?>(); 
tcs.SetResult(default(?)); //Can happen later as well, this is for demo purposes. 
return tcs.Task; 
} 

パフォーマンスの観点からTのために使用するのに最適なタイプは何ですか?

マイクロベンチマークを実行して純粋にその質問に答えることは難しいようです。答えは残りのアプリケーションに依存していると思います。たとえば、TaskCompletionSource<bool>を使用すると、JITは特殊なコードを生成し、メモリ使用を引き起こします。しかし、アプリケーションが既にブール値ベースのタスクを使用している場合、メモリ使用量は追加されません。 TaskCompletionSource<object>を使用すると、各タスクに(またはランタイムに依存しない)より多くのメモリを使用する可能性があります。

だからこそ、私はベンチマークだけではその質問に答えることができないと思っています。それは推論でも答える必要があります。

答えて

3

最高の解決策が本当に必要な場合は、空の構造体を宣言する必要があります。このようにして、システムはペイロード用のスペースを予約する必要はありません。そこから

https://referencesource.microsoft.com/#System.Core/System/Threading/Tasks/TaskExtensions.cs,6e36a68760fb02e6,references

private struct VoidResult { } 

、あなたがタスクを完了されたものとしてマークするTaskCompletionSource<VoidResult>、およびTrySetResult(default(VoidResult))を使用することができます。これは、基本クラスライブラリで行われているもの、実際にあります。つまり、それはメモリの小さなビットを節約しますが、実行時間(ナノ秒レベルでさえ)には影響しないと思います。 TaskCompletionSource<byte>(ペイロード用に予約された1バイト)またはTaskCompletionSource<object>(ペイロード用に4バイトが予約済み)を使用する場合でも、32ビットCPUは1回の操作で割り当てを実行できます。

+0

良いアイデア。私はバイト、boolとVoidResultオブジェクトのレイアウトが行われる方法のためにすべてのバイトを保存するかどうか疑問に思う。オブジェクトは64ビットで8バイト整列されています(私は思う)。また、これは、これを行う各アセンブリに対してジッタコードの新しいセットを強制します。 – boot4life

+0

@ boot4life答えにくいです。 'TaskCompletionSource 'は1つのフィールド( 'Task 'を格納)を持ち、x86に4バイトのRAMを埋めます。追加のペイロードは、確保されたスペースを次の4バイトの配置にプッシュします。しかし、私は実際に 'VoidResult'のように0バイトの構造体がどのように処理されるのか分かりません。正しく処理されていれば、 'TaskCompletionSource 'と 'TaskCompletionSource 'は8バイトを使用しますが、システムは 'TaskCompletionSource 'を4バイトのスペース(CLR固有のヘッダを含まない)バイト(アライメントのため) –

+1

TaskCompletionSourceはどんな場合でも影響を受けませんが、タスクのサイズは影響を受けません。 4.6では、派生クラスに単一の 'T result'フィールドがあります。理想的には、導かれた部分は空にレイアウトされてしまいます。 – boot4life

関連する問題