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

Вид: 15343|Ответ: 2

[Связь] [перевод]. NET — использовать разницу между ValueTask и Task

[Скопировать ссылку]
Опубликовано 17.03.2022 11:21:50 | | | |


Использование классов Task или Task имеет узкое место производительности, о котором мы не упоминали в предыдущих статьях. Короче говоря, эти классы лидируют тогда, когда результаты сразу доступныНенужное распределение。 Это означает, что новый объект задачи или задача всегда будет создан, даже если результат уже доступен. Мы упомянули, что концепция async/await, которую мы использовали в предыдущих статьях, существует с релиза .NET 4.5. Эта функция была усовершенствована с C#7 с версией .NET 4.7 со структурой ValueTask, которая может использоваться как возврат для асинхронных функций.

Структура ValueTask


Структура ValueTask впервые появилась в репозитории corefxlab в 2015 году. Этот репозиторий используется для экспериментов и изучения новых идей, которые могут попасть в основной репозиторий corefx, а могут и нет. Репозиторий Corefx — это репозиторий, в котором расположены все базовые библиотеки .NET Core. Он был разработан и предложен Стивеном Таубом для библиотеки System.Threading.Tasks.Channels. В то время Стивен дал краткое объяснение:

Адрес библиотеки corefxlab:Вход по гиперссылке виден.


ValueTask — это отдельное объединение T и задачи, позволяющее ReadAsync свободно выделять для синхронного возврата доступных значений T (в отличие от использования Task.FromResult, где требуется выделение экземпляра задачи). ValueTask можно ожидать, поэтому потребление большинства экземпляров неотличимо от потребления задач.
Многие видят преимущества использования этой структуры, которая включена в C# 7 в пакет System.Threading.Tasks.Extensions NuGet. Итак, прежде чем перейти к структуре ValueTask, давайте рассмотрим проблему, которую она решает. Поскольку Task(Task) — это тип ссылки, начните сАсинхронный метод, возвращающий объект задачи, означает, что он выделяется на кучу каждый раз。 Это необходимо во многих случаях.

Однако в некоторых случаях асинхронные методы возвращают результаты сразу или завершают синхронно. В таких случаях такое распределение не нужно и может стать дорогостоящим в критически важных для производительности частях кода. До релиза .NET 4.7 избежать этого не было, так как асинхронные методы должны были возвращать Task, <T>Task или void (последний обычно был нежелательным). В этой версии .NET это расширено, то есть асинхронный метод может возвращать любой тип, если у него есть доступный метод GetAwaiter. ValueTask — конкретный пример такого типа, и он также был добавлен в этот релиз.

Вы можете просмотреть репозиторий corefx и увидеть полную реализацию ValueTask, вот раздел API, который нас интересует:



В качестве структуры ValueTask позволяет создавать асинхронные методы, которые не выделяют память во время синхронного выполнения. Согласованность API концепции async/await не нарушается таким образом. Кроме того, эта конструкция работает сама по себе, что делает её удобной в использовании. Например, если запустить этот простой код:

В методе MultiplyAsync мы моделируем ситуацию, когда хотим избежать использования задачи и вернуть только простое целое число. Это делается в операторе if метода, где мы фактически проверяем, равен ли переданный параметр нулю. Проблема в том, чтоДаже если наше условие в операторе if верно, приведённый выше код создаёт объект задачи。 Решаем эту задачу следующим образом:

ValueTask и Task



Как уже упоминалось, использование ValueTask имеет два основных преимущества:

  • Улучшения производительности
  • Повышение гибкости внедрения


Итак, каковы цифры, стоящие за улучшением производительности? Обратите внимание на этот код:


Если мы запускаем этот код, JIT выполняется 120 нс. Теперь если заменить Задачу на ValueTask следующим образом:

С JIT мы получим время выполнения 65 нс. Действительно, из-за Task.Delay мы не выполняемся синхронно, но наблюдаем улучшение времени выполнения.

Ещё одно преимущество, о котором мы говорили, — большая гибкость внедрения. Итак, что это вообще значит? Реализации асинхронных интерфейсов, которые должны быть синхронизированы, будут вынуждены использовать Task.Run или Task.FromResult. Конечно, это приводит к тем проблемам с производительностью, о которых мы говорили ранее. Когда мы используем ValueTask, мы чаще выбираем между синхронными и асинхронными реализациями. Имейте в виду, что это может быть признаком того, что ваш код может быть плохо спроектирован, если с вами такое случится.

Например, посмотрим на этот интерфейс:


Допустим, вы хотите назвать его из кода вот так:

Поскольку мы используем ValueTask в интерфейсе, реализация интерфейса может быть синхронной или асинхронной. Это преимущество можно получить, просто пропустив добавление некоторых функций в IThing, которые обрабатывают поведение синхронизации. Таким образом гораздо проще использовать этот интерфейс. Вот синхронная реализация вышеуказанного интерфейса:

Вот асинхронная реализация того же интерфейса:

Однако перед использованием ValueTask необходимо учитывать некоторые компромиссы. Легко подумать, что по умолчанию стоит использовать ValueTask, а не Task, но это совсем не так. Например, хотя ValueTask помогает избежать ненужных назначений при доступной синхронизации результатов, он также содержит два поля.

Важно помнить, что именно такую структуру мы используем здесь, то есть используем типы значений и все их нагрузки. Задача, напротив, — это тип ссылки с одним полем.Когда вы используете ValueTask, у нас появляется больше данных для обработки и обработки. Если такой метод ожидается в асинхронном методе, то асинхронный метод имеет видАвтомат также будет больше, потому что хранение всей структуры обычно требует больше пространства, чем сохранение одной ссылки.

Вот почему в Microsoft рекомендуют использовать Task или Task в качестве стандартного типа возврата для асинхронных методов. Только после анализа производительности стоит рассмотреть переход на ValueTask.


сводка

ValueTask — это структура, введённая в .NET 4.7, которая даёт нам множество возможностей для использования асинхронных методов в .NET. Однако это не обходится без цены. Это полезно для критически важных для производительности методов, которые выполняются синхронно. С ними мы можем избежать назначения ненужных объектов. Тем не менее, как тип ценности, он связан со всеми проблемами, которые обычно сталкиваются у типов ценности. Поэтому мы можем получить выгоду от этой структуры, но должны быть осторожны.

Оригинальный адрес:Вход по гиперссылке виден.




Предыдущий:【Practical Action】Используйте Docker для создания IPsec VPN-сервера
Следующий:Попробуйте использовать OpenConnect вместо Cisco AnyConnect, чтобы избежать замков таблицы маршрутизации
Опубликовано 18.03.2022 22:21:57 |
Приходи учиться снова.
Опубликовано 22.03.2022 14:05:53 |
Узнайте суть обученияНеплохо
Отказ:
Всё программное обеспечение, программные материалы или статьи, публикуемые Code Farmer Network, предназначены исключительно для учебных и исследовательских целей; Вышеуказанный контент не должен использоваться в коммерческих или незаконных целях, иначе пользователи несут все последствия. Информация на этом сайте взята из Интернета, и споры по авторским правам не имеют отношения к этому сайту. Вы должны полностью удалить вышеуказанный контент с компьютера в течение 24 часов после загрузки. Если вам нравится программа, пожалуйста, поддержите подлинное программное обеспечение, купите регистрацию и получите лучшие подлинные услуги. Если есть нарушение, пожалуйста, свяжитесь с нами по электронной почте.

Mail To:help@itsvse.com