Улучшит ли производительность асинхронный метод контроллера? В чем выгода? - PullRequest
1 голос
/ 03 мая 2019

Отказ от ответственности: Я тщательно продумал, является ли этот вопрос основанным на мнениях, потому что я понимаю важность соблюдения правил сайта.Мой вывод заключается в том, что это достаточно конкретно, чтобы ответить здесь.Мои самые глубокие извинения, если я буду исправлен.

Я решил написать свой контроллер без async и Task .Как я понял, в асинхронизации операции было нечего получить по двум причинам:

  1. Вся модель представления обслуживается одновременно, и значимой информации для представления до полного содержимого нет.готов к визуализации (т. е. список не передается постепенно).

  2. Операции в сервисе должны выполнять большой объем данных и основаны на логике, предполагающей знание всех найденных элементов.а также хранит определенную информацию до ее раскрытия (т. е. SaveChangesAsync () или подобное невозможно, при этом используется AsNoTracking () ).

Класс, описывающий модель представления, выглядит примерно так.

public class TheViewModel
{
  public string Name { get; set; }
  public byte[] Pieces { get; set; }
  public Guid Id { get; set; }
  public Dictionary<int, Info> { get; set; }
}

public class Info
{
  public Guid Id { get; set; }
  public Guid ParentLeftId { get; set; }
  public Guid ParentRightId { get; set; }
  public Guid ParentRandId { get; set; }
  public int[] Data { get; set; }
  public List<DateTime> { get; set; }
}

Мой коллега покачал взглядом, реагируя на мой выбор, и утверждал, что:

a.это не рекомендуемый способ, б.операция будет выполнена менее эффективно, c.это против лучших практик.

Мы гуглили и читали довольно много блогов.Общее впечатление говорит о том, что аргумент действителен.Однако я ставлю под сомнение его актуальность в нашем случае.Prestanda не является демократической проблемой и не может основываться на мнениях.

Когда я пытался найти реальные ссылки (MSDN, SO и т. Д.), Где указано , как именно производительность будетбыть затронутым, я получил очень мало.Я также не нашел много информации о том, как надежно проверить это.

Ответы [ 2 ]

3 голосов
/ 03 мая 2019

Вся модель представления обслуживается сразу, и нет существенной информации для представления, пока весь контент не будет готов к визуализации

На самом деле это не проблема.

Где-то вы, вероятно, получаете информацию из базы данных (вы упомянули сохранение изменений). Если вы взаимодействуете с базой данных асинхронно (например, ExecuteDataReaderAsync), то ожидание ее означает, что во время выполнения запросапоток, который выполнил запрос, может делать другие вещи.Когда запрос завершит выполнение, этот поток (или другой, неважно) завершится.

Разрешение потоку делать что-то еще, в то время как запрос вместо того, чтобы делать что-либо, кроме ожидания, увеличивает производительность приложения.

Здесь я думаю, что возникает путаница: как async/await делаетВаш метод контроллера выполняется быстрее? Это не .Не за что.Фактически, переключение потоков между такими задачами может сделать его чуть-чуть медленнее.(Как правило, это настолько тривиально, что вам не стоит об этом беспокоиться.)

Но в целом производительность вашего приложения может быть выше, поскольку доступно много потоков - , даже если это всего один - есть шанс, что они могут что-то делать, а не ждать.

Отдельные вещи, которые вы делаете (например, выполняете метод контроллера), не быстрее, но вы даете своему приложению шанс сделать больше с каждым потоком, который у него есть.Однако, если что-то займет много времени, оно может начаться раньше, потому что оно не ожидает потока, что означает, что он завершает раньше , а не быстрее.

Даже если ваше приложение получало по одному запросу за раз и обрабатывалопри использовании только одного потока, вот сценарий: что делать, если вы делаете два запроса к базе данных или API, где ни один из них не зависит от результатов другого?Если вы обрабатываете их синхронно, вы ждете, пока один из них завершится, начнете следующий и дождитесь следующего, чтобы закончить.Если вы обрабатываете их асинхронно, вы запускаете один, и пока вы ждете, вы можете запустить следующий.Ни одна отдельная задача не происходит быстрее.Разница в том, что вторая задача запускается раньше - хотя с первой она не связана, кроме как с ожиданием.

Так что, пока мы говорим о «потоках», на самом деле речь идет не о нескольких потоках.Речь идет о том, как используется каждый отдельный поток.

1 голос
/ 03 мая 2019

Я попробую объяснить это по-другому.

Async / await обычно помогает при операциях ввода-вывода. К ним относятся (но не ограничиваются ими): доступ к файлам, доступ к БД, вызов веб-службы, выполнение действий с сетевыми сокетами или даже доступ к некоторому специальному оборудованию, например, сканеру. В основном, есть моменты времени, когда вашему коду нужно ждать результата какой-либо внешней операции - операции чтения файла, SQL-запроса, HTTP-запроса и т. Д.

И это то, что помогает async / await. Без этого ваш поток застрял бы в ожидании результатов, что обычно занимает много времени. Но с этим ваш поток может переключиться на выполнение чего-то еще, пока он ждет. Таким образом, ваш процессор может использоваться более эффективно.

Примечание - это не многопоточность. Не существует дополнительной темы, которая «на самом деле делает работу». Вместо этого, глубоко под всеми уровнями абстракции, компьютер ждет некоторой части оборудования, чтобы сообщить - жесткий диск, сетевой адаптер, что угодно. (Ну, да, вы можете также подождать, пока другой поток завершит выполнение своих действий, но это довольно необычный сценарий)

В вашем сценарии, используя async / await, вы можете обслуживать два входящих REST-запроса в одном потоке. Вы начнете с первого, затем он дойдет до того момента, когда ему нужно ждать (скажем, потому что он выполнял SQL-запрос), и ASP.NET переключится на выполнение второго. Затем, когда второй получает ожидание (или, возможно, завершает), ASP.NET проверит, есть ли результаты SQL, и может ли продолжить с первым. Ваш поток никогда не будет обрабатывать более одного запроса одновременно, но он будет переключаться между ними - всякий раз, когда кто-то будет ждать, он продолжит другой. Таким образом вы получаете эффективность.

Имейте в виду, что если ваши запросы тратят больше времени на вычисление чего-либо на процессоре, чем на ожидание какого-либо внешнего ввода-вывода, ваши выгоды от async / await будут меньше. И если вы вообще делаете no IO (например, ваши результаты зависят только от содержимого запроса), то вам действительно не нужен какой-либо асинхронный вызов / ожидание, потому что ждать нечего.

Даже если вы найдете применение async / await, это не поможет ни одному отдельному запросу быстрее - оно просто позволит вам обрабатывать больше запросов одновременно.

...