リアルタイムWebAPIと通信するネットワーククライアントを作成しています。
クライアントは、1秒あたり多くの異なる呼び出しを行い、Task<TResult>
各クライアントコンポーネントにフィードバックして、クライアントがブロックするかどうかを決定できるようにする必要があります。
public Task<TResult> Execute<TResult>(IOperation<TResult> operation);
API呼び出しを行うプロセスは、次のように実行されます。
- (小さい、1KB未満)リクエストをJsonにシリアル化します
- を使用してリクエストを送信します
HttpClient
- 成功したら、デシリアライズして
TResult
(Jsonのサイズは数百KBになる可能性がありますが、通常ははるかに小さくなります)、
私のテストでは、タスクワークフロー内のどこに各ステップを含めるか(したがって、どのスレッドに含めるか)を選択すると、パフォーマンスに大きな影響があります。
私がこれまでに見つけた最速のセットアップはこれです(半疑似コード、簡潔にするためにジェネリック型パラメーターを省略):
// serialize on main thread
var requestString = JsonConvert.SerializeObject(request);
// create message - omitted
var post = Task.Factory.StartNew(() => this.client.SendAsync(requestMessage)).Unwrap();
return post.ContinueWith(response =>
{
var jsonString = response.Result.Content.ReadAsStringAsync();
return JsonConvert.DeserializeObject(jsonString.Result);
});
最も遅いのは、プロセス全体が単一のタスク内で実行されるこのセットアップです。
return Task.Factory.StartNew((request) =>
{
var requestString = JsonConvert.SerializeObject(request);
// create message - omitted
var post = client.SendAsync(requestMessage);
var jsonString = post.Result.Content.ReadAsStringAsync();
return JsonConvert.DeserializeObject(jsonString.Result);
})
リクエストごとに1つのバックグラウンドスレッドを作成するため、最後の方法が最も速いと思いました。私の仮定では、これでは、呼び出しがブロックされているため、TPLが使用可能なスレッドを最も効率的に使用することはできません。
それで、タスクに何を入れるべきか、タスクの外に何を置くべきか、または継続するかについての一般的なルールはありますか?
この特定のケースでは、私が試すことができるさらなる最適化はありますか?