Новости

22.04.2021

Книга «C# 8 и .NET Core. Разработка и оптимизация»

Несколько глав посвящено .NET Standard API, применяемым для запроса данных и управления ими, отслеживания производительности и ее повышения, работы с файловой системой, асинхронными потоками, сериализацией и шифрованием. Кроме того, на примерах кроссплатформенных приложений вы сможете собрать и развернуть собственные. Например, веб-приложения с использованием ASP.NET Core или мобильные приложения на Xamarin Forms.

Также вы познакомитесь с технологиями, применяемыми при создании приложений Windows для ПК, в частности с Windows Forms, Windows Presentation Foundation (WPF) и Universal Windows Platform (UWP).

Улучшение производительности и масштабируемости с помощью многозадачности


Данная глава посвящена способам одновременного выполнения нескольких действий в целях повышения производительности, масштабируемости и эффективности работы конечных пользователей.

В этой главе:

  • процессы, потоки и задачи;
  • мониторинг производительности и использования ресурсов;
  • асинхронное выполнение задач;
  • синхронизация доступа к общим ресурсам;
  • ключевые слова async и await.

 

Процессы, потоки и задачи


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

Windows и большинство других современных операционных систем используют режим вытесняющей многозадачности, которая имитирует параллельное выполнение задач. Данный режим делит процессорное время между потоками, выделяя «интервал времени» для каждого потока один за другим. Текущий поток приостанавливается, когда заканчивается его «интервал времени». Затем процессор выделяет другому потоку еще один «интервал времени».

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

Потоки имеют свойства Priority и ThreadState. Кроме того, существует класс ThreadPool, предназначенный для управления пулом фоновых рабочих потоков, как показано на следующей схеме (рис. 13.1).

Если вы как разработчик имеете дело со сложными действиями, которые должны быть выполнены вашим кодом, и хотите получить полный контроль над ними, то можете создавать отдельные экземпляры класса Thread и управлять ими. При наличии одного основного потока и нескольких небольших действий, которые можно выполнять в фоновом режиме, вы можете добавить экземпляры делегатов, указывающие на эти фрагменты, реализованные в виде методов в очередь, и они будут автоматически распределены по потокам с помощью пула потоков.

Дополнительную информацию о пуле потоков можно получить на сайте docs.microsoft.com/ru-ru/dotnet/standard/threading/the-managed-thread-pool.

Потокам, возможно, придется конкурировать и ждать доступа к общим ресурсам, таким как переменные, файлы и объекты баз данных.

В зависимости от задачи удвоение количества потоков (рабочих) не уменьшает вдвое количество секунд, которое будет затрачено на выполнение задачи. Фактически это может даже увеличить длительность выполнения задачи, как показано на рис. 13.2.

Никогда не полагайтесь на то, что увеличение количества потоков повысит производительность! Выполните тесты производительности сначала базового кода без реализации нескольких потоков, а затем — кода с несколькими потоками. Выполняйте тесты производительности в промежуточной среде, максимально приближенной к рабочей.

Мониторинг производительности и использования ресурсов


Прежде чем мы сможем улучшить производительность любого кода, мы должны иметь возможность проводить мониторинг его скорости и эффективности работы, чтобы получить базовые данные, на основании которых можем измерять улучшения.

Оценка эффективности типов


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

  • функциональность — для принятия решения проверяется, предоставляет ли данный тип необходимую вам функциональность;
  • объем памяти — для принятия решения проверяется, сколько байтов памяти потребляет данный тип;
  • производительность — для принятия решения проверяется, насколько быстро работает данный тип;
  • потребности в будущем — этот фактор зависит от возможных требований и возможности поддержки.


Будут сценарии, например, при сохранении чисел, когда несколько типов имеют одинаковую функциональность, поэтому, прежде чем выбирать, следует сопоставить расход памяти и производительность.

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

Если же необходимо сохранить только несколько чисел, но выполнить с ними большое количество операций, то лучше выбрать тип, который быстрее всего работает на конкретном ЦПУ.

Ранее упоминалась функция sizeof(), предназначенная для отображения количества байтов, занимаемых в памяти одним экземпляром конкретного типа. При сохранении большого количества значений в более сложных структурах данных, таких как массивы и списки, измерение использования памяти требует способа получше.

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

В следующем подразделе вы научитесь писать код для мониторинга действительных требований к памяти и производительности при использовании различных типов.

В настоящее время оптимальным выбором может стать переменная short, но, вероятно, будет лучше задействовать переменную int, хотя она занимает в два раза больше места в памяти, ведь возможно, что в дальнейшем потребуется хранить более широкий диапазон значений.

Следует принять во внимание еще один показатель — обслуживание. Данная мера показывает, сколько усилий потребуется приложить другому разработчику, чтобы понять и отредактировать ваш код. Если вы прибегаете к неочевидному выбору типа, не объясняя данное действие с помощью комментария, то это может запутать разработчика, открывшего ваш код, чтобы исправить ошибку или добавить какую-либо функциональность.

Мониторинг производительности и использования памяти


В пространстве имен System.Diagnostics реализовано большое количество полезных типов для мониторинга вашего кода. В первую очередь следует рассмотреть тип Stopwatch.

1. Создайте в папке Code папку Chapter13 с двумя подпапками MonitoringLib и MonitoringApp.

2. В программе Visual Studio Code сохраните рабочую область как Chapter13.code-workspace.

3. Добавьте в рабочую область папку MonitoringLib, откройте для нее новую панель TERMINAL (Терминал) и создайте новый проект библиотеки классов, как показано в следующей команде:

4. Добавьте в рабочую область папку MonitoringApp, откройте для нее новую панель TERMINAL (Терминал) и создайте новый проект консольного приложения, как показано в следующей команде:

5. В проекте MonitoringLib переименуйте файл Class1.cs на Recorder.cs.

6. В проекте MonitoringApp найдите и откройте файл MonitoringApp.csproj и добавьте ссылку на библиотеку MonitoringLib, как показано ниже (выделено полужирным шрифтом):

7. На панели TERMINAL (Терминал) скомпилируйте проекты, как показано в следующей команде:

С полным содержанием статьи можно ознакомиться на сайте "Хабрахабр":

https://habr.com/ru/company/piter/blog/552366/


Комментарии: 0

Пока нет комментариев


Оставить комментарий






CAPTCHAОбновить изображение

Наберите текст, изображённый на картинке

Все поля обязательны к заполнению.

Перед публикацией комментарии проходят модерацию.