Я порівнюю продуктивність при винесенні await
ключове слово з мого методу, і це дає мені більше 15x кращу продуктивність.
Наведений нижче метод значно краще виконує:
private static async Task<HttpResponseMessage> AwaitResponse(HttpRequest proxy)
{
foreach (var header in proxy.Request.Headers)
{
Client.Instance.DefaultRequestHeaders.Add(header.Key, header.Value);
}
var response = Client.Instance.SendAsync(proxy.Request).Result;
return response;
}
ніж цей:
private static async Task<HttpResponseMessage> AwaitResponse(HttpRequest proxy)
{
foreach (var header in proxy.Request.Headers)
{
Client.Instance.DefaultRequestHeaders.Add(header.Key, header.Value);
}
var response = Client.Instance.SendAsync(proxy.Request);
return await response;
}
Зверніть увагу на те, як я телефоную .Результат у першому варіанті методу.
Чому це відбувається? Чому існує настільки велике покарання ефективності?
Будь ласка, зверніть увагу, що Client
просто статична екземпляр HttpClient
.
Відповіді:
4 для відповіді № 1При використанні await
, контекст виконання коду призупинено до повернення методу async. За замовчуванням, await
намагається відновити новий потік доконтекст вхідної синхронізації, в якому він виник. Це іноді може мати наслідки для продуктивності, оскільки CLR має почекати, доки початковий синхронізація не з'явиться.
Взагалі кажучи, якщо ви не маєте певної потреби повертатися до того ж контексту потоку, що ви залишили (скажімо, у клієнтській програмі, щоб повернутися до потоку інтерфейсу користувача), краще ConfigureAwait(false)
і продовжувати на будь-якому довільному потоці.
4 для відповіді № 2
Враховуючи, що ви фактично не використовуєте відповідь на що-небудь у фрагментах, немає необхідності реально використовувати async / await або викликати .Result
. Ви можете просто повернути Task
для того, щоб абонент чекав або дзвонив .Result
на більш високому рівні.
private static Task<HttpResponseMessage> AwaitResponse(HttpRequest proxy) {
foreach (var header in proxy.Request.Headers) {
Client.Instance.DefaultRequestHeaders.Add(header.Key, header.Value);
}
return Client.Instance.SendAsync(proxy.Request);
}
Я б також запропонував переглянути
Async / Await - найкращі практики в асинхронному програмуванні від Стівена Клірі
питання навколо не змішування блокування та коду async, а також про те, як і коли ConfigureAwait(false)
коли ви можете