/ / Async займає 15x довше, ніж синхронізація - c #, asp.net, asp.net-web-api, async-await, dotnet-httpclient

Async займає 15x довше, ніж синхронізація - c #, asp.net, asp.net-web-api, async-await, dotnet-httpclient

Я порівнюю продуктивність при винесенні 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) коли ви можете