День 1589. #ЗаметкиНаПолях
Планирование Фоновых Заданий в Quartz.NET
Если вы создаёте масштабируемое приложение, обычно требуется перенести часть работы в фоновое задание. Несколько примеров:
- отправка email уведомлений,
- создание отчётов,
- обновление кэша,
- обработка изображений.
Quartz.NET — полнофункциональная система планирования заданий с открытым кодом, которую можно использовать от самых маленьких приложений до крупных корпоративных систем.
В Quartz.NET необходимо понимать три концепции:
1. Job — фоновое задание.
2. Trigger — триггер, управляющий запуском задания.
3. Scheduler — планировщик, отвечающий за координацию заданий и триггеров.
Во-первых, добавим пакет Quartz.Extensions.Hosting. Этот вариант установки прекрасно интегрируется с .NET с помощью экземпляра IHostedService.
Теперь надо внедрить и запустить сервис:
Чтобы создать фоновое задание, необходимо реализовать IJob. В нём один метод — Execute, где размещается код фонового задания. Здесь отметим несколько вещей:
- можно использовать DI для внедрения сервисов,
- атрибут DisallowConcurrentExecution предотвращает одновременный запуск задания несколько раз.
1) Однозначно идентифицируем фоновое задание с помощью JobKey.
2) AddJob регистрирует ProcessMessages в DI, а также в Quartz.
3) Настраиваем триггер для задания, вызывая AddTrigger:
- связываем задание с триггером с помощью ForJob,
- настраиваем расписание: в этом примере запускаем задание каждые десять секунд и повторяем бесконечно, пока работает сервис.
Quartz также поддерживает настройку триггеров с помощью выражений cron.
По умолчанию Quartz настраивает все задания, используя RAMJobStore, который является наиболее производительным, поскольку хранит все данные в оперативной памяти. Однако это также означает, что хранилище непостоянное, и вы можете потерять информацию о планировании, когда приложение остановится или выйдет из строя. Иногда может быть полезно иметь постоянное хранилище, для этого есть встроенный AdoJobStore, который работает с базами данных SQL. Нужно создать набор таблиц базы данных для использования Quartz.NET. Подробности описаны в документации.
Источник: https://www.milanjovanovic.tech/blog/scheduling-background-jobs-with-quartz-net
Планирование Фоновых Заданий в Quartz.NET
Если вы создаёте масштабируемое приложение, обычно требуется перенести часть работы в фоновое задание. Несколько примеров:
- отправка email уведомлений,
- создание отчётов,
- обновление кэша,
- обработка изображений.
Quartz.NET — полнофункциональная система планирования заданий с открытым кодом, которую можно использовать от самых маленьких приложений до крупных корпоративных систем.
В Quartz.NET необходимо понимать три концепции:
1. Job — фоновое задание.
2. Trigger — триггер, управляющий запуском задания.
3. Scheduler — планировщик, отвечающий за координацию заданий и триггеров.
Во-первых, добавим пакет Quartz.Extensions.Hosting. Этот вариант установки прекрасно интегрируется с .NET с помощью экземпляра IHostedService.
Теперь надо внедрить и запустить сервис:
services.AddQuartz(cfg =>Quartz.NET будет создавать задания, извлекая их из DI-контейнера. Это также означает, что вы можете использовать scope-сервисы, а не только singleton или transient. Установка WaitForJobsToComplete в true гарантирует, что Quartz.NET будет ожидать корректного завершения заданий перед выходом.
{
cfg.UseMicrosoftDependencyInjectionJobFactory();
});
services.AddQuartzHostedService(opt =>
{
opt.WaitForJobsToComplete = true;
});
Чтобы создать фоновое задание, необходимо реализовать IJob. В нём один метод — Execute, где размещается код фонового задания. Здесь отметим несколько вещей:
- можно использовать DI для внедрения сервисов,
- атрибут DisallowConcurrentExecution предотвращает одновременный запуск задания несколько раз.
[DisallowConcurrentExecution]Теперь зарегистрируем задание в DI-контейнере с триггером (планировщик Quartz создаст сам):
public class ProcessMessages : IJob
{
// внедряем нужные сервисы
public async Task Execute(
IJobExecutionContext context) { … }
}
services.AddQuartz(cfg =>Здесь:
{
var key = new JobKey(nameof(ProcessMessages));
cfg
.AddJob<ProcessMessages>(key)
.AddTrigger(t => t.ForJob(key)
.WithSimpleSchedule(s =>
s.WithIntervalInSeconds(10)
.RepeatForever()
)
);
cfg.UseMicrosoftDependencyInjectionJobFactory();
});
1) Однозначно идентифицируем фоновое задание с помощью JobKey.
2) AddJob регистрирует ProcessMessages в DI, а также в Quartz.
3) Настраиваем триггер для задания, вызывая AddTrigger:
- связываем задание с триггером с помощью ForJob,
- настраиваем расписание: в этом примере запускаем задание каждые десять секунд и повторяем бесконечно, пока работает сервис.
Quartz также поддерживает настройку триггеров с помощью выражений cron.
По умолчанию Quartz настраивает все задания, используя RAMJobStore, который является наиболее производительным, поскольку хранит все данные в оперативной памяти. Однако это также означает, что хранилище непостоянное, и вы можете потерять информацию о планировании, когда приложение остановится или выйдет из строя. Иногда может быть полезно иметь постоянное хранилище, для этого есть встроенный AdoJobStore, который работает с базами данных SQL. Нужно создать набор таблиц базы данных для использования Quartz.NET. Подробности описаны в документации.
Источник: https://www.milanjovanovic.tech/blog/scheduling-background-jobs-with-quartz-net
👍23
День 1590. #ЧтоНовенького
Действия для Устаревших Репозиториев GitHub
По мере расширения организации и развития проектов репозитории могут легко устаревать и становиться неактивными. Важно идентифицировать эти репозитории и предпринимать соответствующие действия, чтобы исходный код был организован и обновлён. Архивирование проектов, которые больше не находятся в активной разработке, сообщит остальным разработчикам, что полагаться на поддержку этого проекта больше не стоит.
GitHub представляет Stale Repos Action, инструмент, который поможет выявлять и сообщать о репозиториях, в которых не было активности. Таким образом вы можете обнаружить неактивные репозитории в своей организации, что позволит вам принять решение об их архивации, возрождении или переориентации усилий.
Чтобы начать использовать Stale Repos Action, выполните следующие действия:
1. Создайте новый репозиторий или используйте существующий для размещения рабочего процесса GitHub Action. Это будет репозиторий, в который вы получите отчёт.
2. Скопируйте пример рабочего процесса, приведённый ниже, в свой репозиторий, сохранив его в каталоге .github/workflows/ с расширением .yml, Например,
3. Настройте необходимые значения среды, в примере рабочего процесса, приведённом ниже. Значения GH_TOKEN и ORGANIZATION следует заменить вашей информацией из секретов репозитория. См. подробнее, как их создать.
Примечание. Убедитесь, что ваш токен GitHub имеет доступ для чтения ко всем репозиториям в организации. GitHub использует токен личного доступа (классический) с выбранной областью read:org.
Пример:
См. также: Подробнее о GitHub Actions.
Источник: https://github.blog/2023-06-05-announcing-the-stale-repos-action/
Действия для Устаревших Репозиториев GitHub
По мере расширения организации и развития проектов репозитории могут легко устаревать и становиться неактивными. Важно идентифицировать эти репозитории и предпринимать соответствующие действия, чтобы исходный код был организован и обновлён. Архивирование проектов, которые больше не находятся в активной разработке, сообщит остальным разработчикам, что полагаться на поддержку этого проекта больше не стоит.
GitHub представляет Stale Repos Action, инструмент, который поможет выявлять и сообщать о репозиториях, в которых не было активности. Таким образом вы можете обнаружить неактивные репозитории в своей организации, что позволит вам принять решение об их архивации, возрождении или переориентации усилий.
Чтобы начать использовать Stale Repos Action, выполните следующие действия:
1. Создайте новый репозиторий или используйте существующий для размещения рабочего процесса GitHub Action. Это будет репозиторий, в который вы получите отчёт.
2. Скопируйте пример рабочего процесса, приведённый ниже, в свой репозиторий, сохранив его в каталоге .github/workflows/ с расширением .yml, Например,
.github/workflows/stale_repos.yml
. Обратите внимание, что в коде ниже по умолчанию используется один год. Используйте нужное вам целое количество дней с момента последнего коммита в ветку по умолчанию.3. Настройте необходимые значения среды, в примере рабочего процесса, приведённом ниже. Значения GH_TOKEN и ORGANIZATION следует заменить вашей информацией из секретов репозитория. См. подробнее, как их создать.
Примечание. Убедитесь, что ваш токен GitHub имеет доступ для чтения ко всем репозиториям в организации. GitHub использует токен личного доступа (классический) с выбранной областью read:org.
Пример:
name: stale repo identifierТеперь действие будет запускаться автоматически в соответствии с заданным вами расписанием, проверяя наличие неактивных репозиториев и создавая отчет о проблеме в текущем репозитории. В отчёте будет таблица неактивных репозиториев со ссылками на них и количеством дней неактивности для каждого репозитория.
on:
workflow_dispatch:
schedule:
- cron: '3 2 1 * *'
jobs:
build:
name: stale repo identifier
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Run stale_repos tool
uses: docker://ghcr.io/github/stale_repos:v1
env:
GH_TOKEN: ${{ secrets.GH_TOKEN }}
ORGANIZATION: ${{ secrets.ORGANIZATION }}
INACTIVE_DAYS: 365
- name: Create issue
uses: peter-evans/create-issue-from-file@v4
with:
title: Stale repository report
content-filepath: ./stale_repos.md
assignees: <ВАШ_ЛОГИН_GITHUB>
См. также: Подробнее о GitHub Actions.
Источник: https://github.blog/2023-06-05-announcing-the-stale-repos-action/
👍8
День 1591. #ЗаметкиНаПолях
Повышаем Производительность с Помощью Разделения Запросов в EF Core
Некоторые сложные многотабличные запросы могут выполняться слишком долго в зависимости от количества данных в таблицах.
Допустим, у нас есть таблица заказов Orders. Заказ может иметь одну или несколько позиций LineItems. Кроме того, для позиций заказов есть таблица, содержащая допустимые измерения — LineItemDimensions. Вот запрос, который нам нужен:
В EF Core 5.0 появилась новая функция разделения запросов. Она позволяет указать, что данный LINQ-запрос должен быть разделён на несколько SQL-запросов. Всё, что нужно сделать, это вызвать метод AsSplitQuery:
Вы можете включить разделение запросов на уровне контекста, вызвав метод UseQuerySplittingBehavior:
Особенности
- Не существует гарантии согласованности для нескольких SQL-запросов. Вы можете столкнуться с проблемой, если одновременно с запросом данных выполняется параллельное обновление. Чтобы смягчить это, можно обернуть запросы в транзакцию, но это также может привести к проблемам с производительностью.
- Каждый запрос требует отдельного обращения к БД по сети. Это может снизить производительность, если задержка для базы высока.
Источник: https://www.milanjovanovic.tech/blog/entity-framework-query-splitting
Повышаем Производительность с Помощью Разделения Запросов в EF Core
Некоторые сложные многотабличные запросы могут выполняться слишком долго в зависимости от количества данных в таблицах.
Допустим, у нас есть таблица заказов Orders. Заказ может иметь одну или несколько позиций LineItems. Кроме того, для позиций заказов есть таблица, содержащая допустимые измерения — LineItemDimensions. Вот запрос, который нам нужен:
dbContextEF Core преобразует это в следующий SQL-запрос:
.Orders
.Include(o => o.LineItems)
.ThenInclude(li => li.Dimensions)
.First(o => o.Id == orderId);
SELECT o.*, li.*, d.*В большинстве случаев этот запрос будет выполняться нормально. Однако здесь мы сталкиваемся с проблемой декартова взрыва - ситуацией, когда на выбор N заказов с M позициями и K измерениями база данных возвращает N*M*K строк.
FROM Orders o
LEFT JOIN LineItems li ON li.OrderId = o.Id
LEFT JOIN LineItemDimensions d ON d.LineItemId = li.Id
WHERE o.Id = @orderId
ORDER BY o.Id, li.Id, d.Id;
В EF Core 5.0 появилась новая функция разделения запросов. Она позволяет указать, что данный LINQ-запрос должен быть разделён на несколько SQL-запросов. Всё, что нужно сделать, это вызвать метод AsSplitQuery:
dbContextВ этом случае EF Core сгенерирует следующие SQL-запросы:
.Orders
.Include(o => o.LineItems)
.ThenInclude(li => li.Dimensions)
.AsSplitQuery()
.First(o => o.Id == orderId);
SELECT o.*Обратите внимание, что для каждого оператора Include у нас есть отдельный запрос. Преимущество здесь в том, что мы не выбираем лишние данные, как это было в предыдущем случае.
FROM Orders o
WHERE o.Id = @orderId;
SELECT li.*
FROM LineItems li
JOIN Orders o ON li.OrderId = o.Id
WHERE o.Id = @orderId;
SELECT d.*
FROM LineItemDimensions d
JOIN LineItems li ON d.LineItemId = li.Id
JOIN Orders o ON li.OrderId = o.Id
WHERE o.Id = @orderId;
Вы можете включить разделение запросов на уровне контекста, вызвав метод UseQuerySplittingBehavior:
services.AddDbContext<ApplicationDbContext>(opt =>Это приведет к тому, что все запросы, создаваемые EF Core, будут разделёнными запросами. Чтобы вернуться к единому SQL-запросу в этом случае, в LINQ-запрос нужно будет добавить AsSingleQuery().
opt.UseSqlServer(
"CONNECTION_STRING",
o => o.UseQuerySplittingBehavior(
QuerySplittingBehavior.SplitQuery)));
Особенности
- Не существует гарантии согласованности для нескольких SQL-запросов. Вы можете столкнуться с проблемой, если одновременно с запросом данных выполняется параллельное обновление. Чтобы смягчить это, можно обернуть запросы в транзакцию, но это также может привести к проблемам с производительностью.
- Каждый запрос требует отдельного обращения к БД по сети. Это может снизить производительность, если задержка для базы высока.
Источник: https://www.milanjovanovic.tech/blog/entity-framework-query-splitting
👍21👎1
День 1592. #Карьера
Маркетинговые Приёмы для Создания Резюме
Резюме — первый контакт с потенциальным работодателем. Отправка одного и того же резюме на каждую вакансию не будет самым быстрым и продуктивным методом.
Думайте как маркетолог
У многих инженеров аллергия на маркетинг. Но маркетинг – это способность донести идею таким образом, чтобы она была проста для понимания и убедительна для человека. Т.е. поставить себя на место другого человека и рассказать о своих услугах так, чтобы они соответствовали его интересам и проблемам. Нужно попытаться понять, кто наши потенциальные покупатели: что им нравится, что они делают. Отталкиваясь от этого, создать презентацию, описав основные функции и преимущества, которые понравятся конкретному человеку. Не заставлять его искать ваши выгодные стороны, а проделать эту работу за него. Для опубликованных вакансий это сделать довольно просто: они точно говорят вам, что им нужно.
Начните с базы
Резюме составляется из результатов вашей повседневной работы, поэтому важно собирать эти исходные материалы. Сохраняйте обзоры продуктивности, оценки, положительные комментарии – всё, что говорит о вашей эффективности. Поскольку мы лучше запоминаем более свежие события, обновляйте резюме примерно раз в полгода. Возможно, сейчас вы не ищете работу, но это окупится.
Первый фильтр резюме - система отслеживания кандидатов (ATS): ПО, которое отсеивает резюме без нужных ключевых слов. Поэтому важно, чтобы ваше резюме могло быть легко прочитано ATS. Чистое форматирование, отсутствие диаграмм, рисунков, отсутствие важной информации в верхних и нижних колонтитулах.
Создайте базовое резюме с основной информацией о вас:
- Технические навыки. Даже навыки с низким уровнем владения могут подчеркнуть ваше стремление выучить новые языки или технологии за пределами текущей должности.
- Опыт и социальные навыки. Что вы делали, как вы это сделали, каков был результат. Попробуйте использовать точные цифры: увеличение производительности системы, дохода компании и т.п.
- Сторонние проекты или сертификаты, ссылки на репозитории, чтобы потенциальные работодатели могли увидеть проделанную вами работу.
Хотя и не стоит рассылать базовое резюме, оно может стать основой вашего профиля LinkedIn. Большинство рекрутеров просматривают профили LinkedIn как часть процесса найма.
Целевые резюме
В целевом резюме надо сообщить менеджеру по найму, почему вы подходите для конкретной роли. Сгруппируйте вакансии по типам и создайте отдельные резюме для каждого типа. Резюме на вакансию фуллстек-разработчика в стартап и на инженера по облачным сервисам в крупную корпорацию должны отличаться, даже если у вас есть все подходящие навыки. Если требуется конкретный навык, убедитесь, что он указан.
Остальное зависит от конкретной вакансии. В любое резюме вы можете добавить «tl;dr» — саммари вашей карьеры, ориентированное на должность, на которую вы претендуете. Это послужит тизером, чтобы резюме дочитали до конца. Не обязательно красиво расписывать, нужно донести свою историю как можно чётче и эффективнее, т.е. использовать простой язык и простое построение предложений.
Хотя сопроводительные письма не так важны для технических должностей, они могут добавить немного дополнительного контекста, например, если в письме описан ваш вклад в работу компании на предыдущей должности.
Итого
Когда вы ищете работу, вашим потенциальным клиентом является менеджер по найму. Резюме часто является первой возможностью произвести впечатление, поэтому чем больше мыслей вы сможете в него вложить, тем лучше. Создав несколько резюме, адаптированных для различных должностей, отраслей и размеров компаний, вы получите больше шансов пройти отбор.
Источник: https://stackoverflow.blog/2023/05/24/how-to-use-marketing-techniques-to-build-a-better-resume/
Маркетинговые Приёмы для Создания Резюме
Резюме — первый контакт с потенциальным работодателем. Отправка одного и того же резюме на каждую вакансию не будет самым быстрым и продуктивным методом.
Думайте как маркетолог
У многих инженеров аллергия на маркетинг. Но маркетинг – это способность донести идею таким образом, чтобы она была проста для понимания и убедительна для человека. Т.е. поставить себя на место другого человека и рассказать о своих услугах так, чтобы они соответствовали его интересам и проблемам. Нужно попытаться понять, кто наши потенциальные покупатели: что им нравится, что они делают. Отталкиваясь от этого, создать презентацию, описав основные функции и преимущества, которые понравятся конкретному человеку. Не заставлять его искать ваши выгодные стороны, а проделать эту работу за него. Для опубликованных вакансий это сделать довольно просто: они точно говорят вам, что им нужно.
Начните с базы
Резюме составляется из результатов вашей повседневной работы, поэтому важно собирать эти исходные материалы. Сохраняйте обзоры продуктивности, оценки, положительные комментарии – всё, что говорит о вашей эффективности. Поскольку мы лучше запоминаем более свежие события, обновляйте резюме примерно раз в полгода. Возможно, сейчас вы не ищете работу, но это окупится.
Первый фильтр резюме - система отслеживания кандидатов (ATS): ПО, которое отсеивает резюме без нужных ключевых слов. Поэтому важно, чтобы ваше резюме могло быть легко прочитано ATS. Чистое форматирование, отсутствие диаграмм, рисунков, отсутствие важной информации в верхних и нижних колонтитулах.
Создайте базовое резюме с основной информацией о вас:
- Технические навыки. Даже навыки с низким уровнем владения могут подчеркнуть ваше стремление выучить новые языки или технологии за пределами текущей должности.
- Опыт и социальные навыки. Что вы делали, как вы это сделали, каков был результат. Попробуйте использовать точные цифры: увеличение производительности системы, дохода компании и т.п.
- Сторонние проекты или сертификаты, ссылки на репозитории, чтобы потенциальные работодатели могли увидеть проделанную вами работу.
Хотя и не стоит рассылать базовое резюме, оно может стать основой вашего профиля LinkedIn. Большинство рекрутеров просматривают профили LinkedIn как часть процесса найма.
Целевые резюме
В целевом резюме надо сообщить менеджеру по найму, почему вы подходите для конкретной роли. Сгруппируйте вакансии по типам и создайте отдельные резюме для каждого типа. Резюме на вакансию фуллстек-разработчика в стартап и на инженера по облачным сервисам в крупную корпорацию должны отличаться, даже если у вас есть все подходящие навыки. Если требуется конкретный навык, убедитесь, что он указан.
Остальное зависит от конкретной вакансии. В любое резюме вы можете добавить «tl;dr» — саммари вашей карьеры, ориентированное на должность, на которую вы претендуете. Это послужит тизером, чтобы резюме дочитали до конца. Не обязательно красиво расписывать, нужно донести свою историю как можно чётче и эффективнее, т.е. использовать простой язык и простое построение предложений.
Хотя сопроводительные письма не так важны для технических должностей, они могут добавить немного дополнительного контекста, например, если в письме описан ваш вклад в работу компании на предыдущей должности.
Итого
Когда вы ищете работу, вашим потенциальным клиентом является менеджер по найму. Резюме часто является первой возможностью произвести впечатление, поэтому чем больше мыслей вы сможете в него вложить, тем лучше. Создав несколько резюме, адаптированных для различных должностей, отраслей и размеров компаний, вы получите больше шансов пройти отбор.
Источник: https://stackoverflow.blog/2023/05/24/how-to-use-marketing-techniques-to-build-a-better-resume/
👍14
День 1593. #TipsAndTricks #PerformanceTips
Советы по Оптимизации Производительности
I. Управление Памятью и Сборка Мусора
Управление памятью и сборка мусора являются важными аспектами настройки производительности в C#, поэтому эти рекомендации помогут вам оптимизировать код для достижения максимальной эффективности.
1. Используйте интерфейс IDisposable
IDisposable помогает правильно управлять неуправляемыми ресурсами и обеспечивает эффективное использование памяти вашим приложением.
Плохо:
Хорошо:
Хотя, с IDisposable не всегда бывает так просто. Подробнее об этом можно почитать в серии постов Мои любимые ошибки с IDisposable:
- 1
- 2
- 3
2. Избегайте преждевременной оптимизации
Преждевременная оптимизация может привести к обратным результатам, усложняя чтение, поддержку и расширение кода.
Слишком большое внимание микрооптимизациям может привести к сложному, загромождённому коду, который жертвует простотой поддержки ради незначительного повышения производительности. Преждевременные оптимизации могут усложнить поддержку кода, при этом не оказав существенного влияния на общую производительность или даже снизив производительность. Далеко не всё, что интуитивно кажется должно ускорить выполнение кода, в реальности его ускоряет.
Важно сначала сосредоточиться на написании чистого, эффективного кода и оптимизировать его только при необходимости после тщательного профилирования приложения. Такой подход приведет к созданию более удобных в сопровождении и более производительных приложений.
См. подробнее про оптимизацию кода.
Источник: https://dev.to/bytehide/50-c-advanced-optimization-performance-tips-18l2
Советы по Оптимизации Производительности
I. Управление Памятью и Сборка Мусора
Управление памятью и сборка мусора являются важными аспектами настройки производительности в C#, поэтому эти рекомендации помогут вам оптимизировать код для достижения максимальной эффективности.
1. Используйте интерфейс IDisposable
IDisposable помогает правильно управлять неуправляемыми ресурсами и обеспечивает эффективное использование памяти вашим приложением.
Плохо:
public class ResourceHolder
{
private Stream _stream;
public ResourceHolder(string filePath)
{
_stream = File.OpenRead(filePath);
}
//…
}
ResourceHolder не реализует интерфейс IDisposable, поэтому неуправляемые ресурсы могут не освобождаться, что приводит к утечке памяти. Хорошо:
public class ResourceHolder : IDisposable
{
private Stream _stream;
public ResourceHolder(string filePath)
{
_stream = File.OpenRead(filePath);
}
public void Dispose()
{
_stream?.Dispose();
}
}
Реализуя интерфейс IDisposable, вы гарантируете, что неуправляемые ресурсы будут освобождены, когда они больше не нужны, что предотвратит утечку памяти и уменьшит нагрузку на сборщик мусора.Хотя, с IDisposable не всегда бывает так просто. Подробнее об этом можно почитать в серии постов Мои любимые ошибки с IDisposable:
- 1
- 2
- 3
2. Избегайте преждевременной оптимизации
Преждевременная оптимизация может привести к обратным результатам, усложняя чтение, поддержку и расширение кода.
Слишком большое внимание микрооптимизациям может привести к сложному, загромождённому коду, который жертвует простотой поддержки ради незначительного повышения производительности. Преждевременные оптимизации могут усложнить поддержку кода, при этом не оказав существенного влияния на общую производительность или даже снизив производительность. Далеко не всё, что интуитивно кажется должно ускорить выполнение кода, в реальности его ускоряет.
Важно сначала сосредоточиться на написании чистого, эффективного кода и оптимизировать его только при необходимости после тщательного профилирования приложения. Такой подход приведет к созданию более удобных в сопровождении и более производительных приложений.
См. подробнее про оптимизацию кода.
Источник: https://dev.to/bytehide/50-c-advanced-optimization-performance-tips-18l2
👍15
День 1594. #TipsAndTricks #PerformanceTips
Советы по Оптимизации Производительности
II. Асинхронное программирование и async/await
Асинхронное программирование — мощный метод повышения производительности в операциях, связанных с вводом-выводом, позволяющий повысить скорость отклика и эффективность приложения.
1. Ограничьте количество одновременных операций
Управление параллелизмом имеет решающее значение для оптимизации производительности. Ограничивая количество одновременных операций в приложении, вы помогаете снизить общую нагрузку на систему.
Плохо:
Хорошо:
2. Используйте UseConfigureAwait(false), где возможно
Плохо:
Хорошо:
Источник: https://dev.to/bytehide/50-c-advanced-optimization-performance-tips-18l2
Советы по Оптимизации Производительности
II. Асинхронное программирование и async/await
Асинхронное программирование — мощный метод повышения производительности в операциях, связанных с вводом-выводом, позволяющий повысить скорость отклика и эффективность приложения.
1. Ограничьте количество одновременных операций
Управление параллелизмом имеет решающее значение для оптимизации производительности. Ограничивая количество одновременных операций в приложении, вы помогаете снизить общую нагрузку на систему.
Плохо:
public async Task ProcessManyItems(List<string> items)Здесь задачи создаются одновременно для каждого элемента без надлежащего ограничения, что может вызвать значительную нагрузку на систему.
{
var tasks = items.Select(
async item => await ProcessItem(item));
await Task.WhenAll(tasks);
}
Хорошо:
public async Task ProcessManyItems(Без ограничения параллелизма множество задач будут выполняться одновременно, что может привести к большой нагрузке и снижению общей производительности. Вместо этого используйте SemaphoreSlim для управления количеством одновременных операций. Это отличный пример того, как повысить производительность приложения без ущерба для удобства чтения или сопровождения.
List<string> items,
int maxConcurrency = 10)
{
using (var semaphore = new
SemaphoreSlim(maxConcurrency))
{
var tasks = items.Select(async item =>
{
// Ограничиваем конкурентность семафором
await semaphore.WaitAsync();
try
{
await ProcessItem(item);
}
finally
{
semaphore.Release();
}
});
await Task.WhenAll(tasks);
}
}
2. Используйте UseConfigureAwait(false), где возможно
Плохо:
public async Task<string> LoadDataAsync()ConfigureAwait(false) — ценный приём, который может помочь предотвратить взаимоблокировки в асинхронном коде и повысить эффективность, не заставляя продолжения выполняться в исходном контексте синхронизации.
{
var data = await ReadDataAsync();
return ProcessData(data);
}
Хорошо:
public async Task<string> LoadDataAsync()Используйте ConfigureAwait(false) всегда в библиотечном коде и приложениях, не связанных с пользовательским интерфейсом.
{
var data = await ReadDataAsync()
.ConfigureAwait(false);
return ProcessData(data);
}
Источник: https://dev.to/bytehide/50-c-advanced-optimization-performance-tips-18l2
👍14👎6
День 1595. #TipsAndTricks #PerformanceTips
Советы по Оптимизации Производительности
III. Параллельные вычисления и библиотека параллельных задач (TPL)
Параллельные вычисления могут помочь использовать мощность многоядерных процессоров и ускорить операции, связанные с ЦП.
1. Используйте параллельные циклы с Parallel.For() и Parallel.ForEach()
Плохо:
Хорошо:
2. Используйте класс Partitioner для эффективного распределения рабочей нагрузки.
Плохо:
Хорошо:
Partitioner создает оптимальные рабочие блоки, чтобы свести к минимуму накладные расходы на синхронизацию задач, что приводит к повышению производительности и распределению рабочей нагрузки для ваших приложений.
Источник: https://dev.to/bytehide/50-c-advanced-optimization-performance-tips-18l2
Советы по Оптимизации Производительности
III. Параллельные вычисления и библиотека параллельных задач (TPL)
Параллельные вычисления могут помочь использовать мощность многоядерных процессоров и ускорить операции, связанные с ЦП.
1. Используйте параллельные циклы с Parallel.For() и Parallel.ForEach()
Плохо:
private void ProcessData(List<int> data)Здесь для обработки данных используется стандартный цикл for, что приводит к последовательному выполнению операций. Это не позволяет использовать весь потенциал современных многоядерных процессоров.
{
for (int i = 0; i < data.Count; i++)
{
PerformExpensiveOperation(data[i]);
}
}
Хорошо:
private void ProcessData(List<int> data)Параллельные циклы могут значительно ускорить обработку больших коллекций за счет распределения нагрузки между несколькими ядрами ЦП. Переключайтесь с обычных циклов for и foreach на их параллельные аналоги всякий раз, когда это возможно и безопасно.
{
Parallel.ForEach(
data, item =>
PerformExpensiveOperation(item));
}
2. Используйте класс Partitioner для эффективного распределения рабочей нагрузки.
Плохо:
private void ProcessData(IEnumerable<int> data)Здесь не уделяется особого внимания оптимизации разделения рабочей нагрузки между параллельными задачами. Это может привести к потенциальным накладным расходам и неравномерному распределению нагрузки.
{
Parallel.ForEach(data, item =>
PerformExpensiveOperation(item));
}
Хорошо:
private void ProcessData(IEnumerable<int> data)Используя класс Partitioner, вы можете эффективно распределять рабочие нагрузки по частям, уменьшая потенциальные накладные расходы и улучшая балансировку нагрузки между параллельными задачами.
{
var partitioner = Partitioner.Create(data);
Parallel.ForEach(partitioner, item =>
PerformExpensiveOperation(item));
}
Partitioner создает оптимальные рабочие блоки, чтобы свести к минимуму накладные расходы на синхронизацию задач, что приводит к повышению производительности и распределению рабочей нагрузки для ваших приложений.
Источник: https://dev.to/bytehide/50-c-advanced-optimization-performance-tips-18l2
👍21
День 1596. #TipsAndTricks #PerformanceTips
Советы по Оптимизации Производительности
IV. Важность кэширования данных
Кэширование может значительно повысить производительность приложений за счёт сокращения времени, затрачиваемого на выборку и обработку данных.
1. Реализовать кэширование данных с помощью кэша в памяти
Использование кэширования в памяти может значительно сократить время, требующее выборки данных из базы данных, и ускорить приложение.
Плохо:
Хорошо:
2. Реализуйте кэширование с помощью распределённых систем кэширования
Распределённые системы кэширования, такие как Redis, могут ещё больше повысить производительность вашего приложения за счёт кэширования данных способом, который масштабируется на нескольких серверах и обеспечивает высокую доступность. Например, используем распределённый кэш для извлечения списка популярных продуктов:
Источник: https://dev.to/bytehide/50-c-advanced-optimization-performance-tips-18l2
Советы по Оптимизации Производительности
IV. Важность кэширования данных
Кэширование может значительно повысить производительность приложений за счёт сокращения времени, затрачиваемого на выборку и обработку данных.
1. Реализовать кэширование данных с помощью кэша в памяти
Использование кэширования в памяти может значительно сократить время, требующее выборки данных из базы данных, и ускорить приложение.
Плохо:
public Product GetProductById(int id)Здесь данные о продукте извлекаются из базы каждый раз, когда вызывается метод. Это может привести к значительному снижению производительности, особенно если база данных расположена удалённо или находится под большой нагрузкой.
{
// Извлечение данных из БД каждый раз
var pr = _dbContext.Products
.FirstOrDefault(p => p.Id == id);
return pr;
}
Хорошо:
private static MemoryCache _cache =Использование кэширования в памяти для хранения данных сокращает затраты на выборку базы. Используйте MemoryCache для кэширования часто запрашиваемых данных и повышения производительности.
new MemoryCache(new MemoryCacheOptions());
public Product GetProductById(int id)
{
// Извлечение из кэша, если возможно
if (!_cache.TryGetValue(id, out Product pr))
{
pr = _dbContext.Products
.FirstOrDefault(p => p.Id == id);
_cache.Set(id, pr, TimeSpan.FromMinutes(30));
}
return pr;
}
2. Реализуйте кэширование с помощью распределённых систем кэширования
Распределённые системы кэширования, такие как Redis, могут ещё больше повысить производительность вашего приложения за счёт кэширования данных способом, который масштабируется на нескольких серверах и обеспечивает высокую доступность. Например, используем распределённый кэш для извлечения списка популярных продуктов:
private static IDistributedCache _dCache;Здесь мы используем распределённое кэширование с помощью Redis для хранения данных о популярных продуктах, что сокращает частоту выборки из базы данных. Используйте распределённые системы кэширования для кэширования на нескольких серверах и улучшения масштабируемости приложений.
public List<Product> GetProducts()
{
var key = "popularProducts";
var cached = _dCache.GetString(key);
if (cached == null)
{
var pr = _dbContext.Products
.Where(p => p.IsPopular).ToList();
_dCache.SetString(key,
JsonConvert.SerializeObject(pr),
new DistributedCacheEntryOptions
{
AbsoluteExpirationRelativeToNow =
TimeSpan.FromMinutes(30)
});
return pr;
}
else
{
return JsonConvert
.DeserializeObject<List<Product>>(cached);
}
}
Источник: https://dev.to/bytehide/50-c-advanced-optimization-performance-tips-18l2
👍13
День 1597. #TipsAndTricks #PerformanceTips
Советы по Оптимизации Производительности
V. Параллелизм и безопасность потоков
Обеспечение потокобезопасности может предотвратить нежелательные ошибки и проблемы с производительностью.
1. По возможности используйте структуры данных без блокировок
Выбор структур данных, таких как ConcurrentBag, ConcurrentQueue или ConcurrentDictionary, может помочь вам обеспечить безопасность потоков в многопоточных сценариях без ущерба для производительности.
Плохо:
Хорошо:
2. Используйте эффективные конструкции синхронизации
Использование SemaphoreSlim, ReaderWriterLockSlim или Monitor, может помочь вам защитить общие ресурсы и обеспечить безопасность потоков, сводя к минимуму конфликты и влияние на производительность.
Плохо: см. выше.
Хорошо:
3. Используйте Interlocked для атомарных операций
Вы можете выполнять простые атомарные операции, не полагаясь на блокировки, уменьшая конкуренцию и повышая производительность.
Плохо:
Хорошо:
Источник: https://dev.to/bytehide/50-c-advanced-optimization-performance-tips-18l2
Советы по Оптимизации Производительности
V. Параллелизм и безопасность потоков
Обеспечение потокобезопасности может предотвратить нежелательные ошибки и проблемы с производительностью.
1. По возможности используйте структуры данных без блокировок
Выбор структур данных, таких как ConcurrentBag, ConcurrentQueue или ConcurrentDictionary, может помочь вам обеспечить безопасность потоков в многопоточных сценариях без ущерба для производительности.
Плохо:
private object _sync = new object();
private List<int> _list = new List<int>();
public void Add(int item)
{
lock (_sync)
{
_list.Add(item);
}
}
Здесь используется блокировка для синхронизации доступа к списку, что может привести к конфликтам и снижению производительности.Хорошо:
private ConcurrentBag<int> _bag =
new ConcurrentBag<int>();
public void Add(int item)
{
_bag.Add(item);
}
Используя структуры данных без блокировок, вы можете свести к минимуму конфликты, повысить производительность и обеспечить потокобезопасность в многопоточных сценариях.2. Используйте эффективные конструкции синхронизации
Использование SemaphoreSlim, ReaderWriterLockSlim или Monitor, может помочь вам защитить общие ресурсы и обеспечить безопасность потоков, сводя к минимуму конфликты и влияние на производительность.
Плохо: см. выше.
Хорошо:
private SemaphoreSlim _semaphore
= new SemaphoreSlim(1, 1);
private List<int> _list = new List<int>();
public async Task AddAsync(int item)
{
await _semaphore.WaitAsync();
try
{
_list.Add(item);
}
finally
{
_semaphore.Release();
}
}
Эффективные конструкции синхронизации позволяют защитить общие ресурсы и обеспечить безопасность потоков, сводя к минимуму конфликты и влияние на производительность.3. Используйте Interlocked для атомарных операций
Вы можете выполнять простые атомарные операции, не полагаясь на блокировки, уменьшая конкуренцию и повышая производительность.
Плохо:
private int _counter;
private object _sync = new object();
public void Increment()
{
lock (_syncRoot)
{
_counter++;
}
}
Здесь ключевое слово lock используется для обеспечения потокобезопасности для увеличения счетчика. Однако это может привести к конфликтам и снижению производительности.Хорошо:
private int _counter;
public void Increment ()
{
Interlocked.Increment(ref _counter);
}
Класс Interlocked позволяет выполнять простые атомарные операции без использования блокировок, что повышает производительность и снижает количество конфликтов. Используйте его, когда это возможно, для таких операций, как инкремент, декремент или добавление.Источник: https://dev.to/bytehide/50-c-advanced-optimization-performance-tips-18l2
👍12
День 1598. #Курсы
Сегодня предлагаю вам подборку плейлистов «для новичков», размещённых на канале dotnet. Это серии коротких видео, рассказывающие об основах определённого языка, технологии или инструмента. Думаю, некоторые будут полезны не только совсем новичкам в программировании, но и тем, кто захочет начать знакомиться с какой-то определённой темой.
Языки
C#
F#
Технологии
.NET
ASP.NET
Web API
Entity Framework Core
Xamarin
.NET MAUI
Blazor
ML.NET
Прочее
.NET в Azure
Docker и .NET
NuGet
Основы dotnet-monitor
Миграция с ASP.NET на ASP.NET Core
Инструменты Visual Studio
Начало Работы с GitHub
Автоматизированное Тестирование
Расширения Visual Studio
Сегодня предлагаю вам подборку плейлистов «для новичков», размещённых на канале dotnet. Это серии коротких видео, рассказывающие об основах определённого языка, технологии или инструмента. Думаю, некоторые будут полезны не только совсем новичкам в программировании, но и тем, кто захочет начать знакомиться с какой-то определённой темой.
Языки
C#
F#
Технологии
.NET
ASP.NET
Web API
Entity Framework Core
Xamarin
.NET MAUI
Blazor
ML.NET
Прочее
.NET в Azure
Docker и .NET
NuGet
Основы dotnet-monitor
Миграция с ASP.NET на ASP.NET Core
Инструменты Visual Studio
Начало Работы с GitHub
Автоматизированное Тестирование
Расширения Visual Studio
👍19
День 1599. #ЧтоНовенького
Улучшенная Обработка Исключений в ASP.NET Core 8. Начало
ASP.NET Core 8 скоро выйдет и принесёт крутые улучшения: больше не нужно писать своё промежуточное ПО для обработки исключений!
В ASP.NET Core 8 вы можете создать класс, реализующий интерфейс IExceptionHandler:
- при True выполнение конвейера завершится, и другое промежуточное ПО в конвейере не будет вызываться.
- при False, конвейер продолжит выполнение.
Источник: https://anthonygiretti.com/2023/06/14/asp-net-core-8-improved-exception-handling-with-iexceptionhandler/
Улучшенная Обработка Исключений в ASP.NET Core 8. Начало
ASP.NET Core 8 скоро выйдет и принесёт крутые улучшения: больше не нужно писать своё промежуточное ПО для обработки исключений!
В ASP.NET Core 8 вы можете создать класс, реализующий интерфейс IExceptionHandler:
public interface IExceptionHandlerВажная вещь: нужно вернуть True или False:
{
ValueTask<bool> TryHandleAsync(
HttpContext httpContext,
Exception exception,
CancellationToken cancellationToken);
}
- при True выполнение конвейера завершится, и другое промежуточное ПО в конвейере не будет вызываться.
- при False, конвейер продолжит выполнение.
public class DefaultExHandler :Вы можете записать в ответ что угодно. Здесь это экземпляр ProblemDetails, потому что это стандарт RFC для обработки ошибок, возвращаемых в ответах HTTP API. Код состояния HTTP по умолчанию — 500, но его можно настроить:
IExceptionHandler
{
private ILogger<DefaultExHandler> _logger;
public DefaultExHandler(
ILogger<DefaultExHandler> logger)
{
_logger = logger;
}
public async ValueTask<bool> TryHandleAsync(
HttpContext ctx,
Exception ex,
CancellationToken ct)
{
_logger.LogError(ex, "Error occurred");
await httpContext.Response
.WriteAsJsonAsync(
new ProblemDetails
{
Status = (int)HttpStatusCode.InternalServerError,
Type = ex.GetType().Name,
Title = "Error occurred",
Detail = ex.Message,
Instance = $"{httpContext.Request.iss.onethod} {httpContext.Request.Path}"
});
return true;
}
}
httpContext.Response.StatusCode =Регистрация обработчика ошибок:
(int)HttpStatusCode.RequestTimeout;
var builder = WebApplication.CreateBuilder(args);Окончание следует…
builder.Services
.AddExceptionHandler<DefaultExHandler>();
var app = builder.Build();
app.UseExceptionHandler(opt => { });
…
app.Run();
Источник: https://anthonygiretti.com/2023/06/14/asp-net-core-8-improved-exception-handling-with-iexceptionhandler/
👍12
День 1600. #ЧтоНовенького
Улучшенная Обработка Исключений в ASP.NET Core 8. Окончание
Начало
Цепочка обработчиков исключений
Вы можете связать обработчики исключений в цепочку. При возврате False, конвейер продолжит выполнение и вызовет следующий обработчик исключений. Если все обработчики исключений возвратят False, конвейер выполнит все ПО промежуточного слоя, оставшиеся в конвейере. Вы также можете комбинировать обработчики исключений и промежуточное ПО.
Чтобы связать обработчики исключений, вы ДОЛЖНЫ определить обработчик исключений по умолчанию, который будет запускаться (и размещаться в самом конце) для обработки любого исключения, которое не было обработано предыдущими обработчиками. Порядок имеет значение! Ниже показан обработчик, который обрабатывает (только) TimeOutException и прерывает выполнение конвейера, если исключение фактически является TimeOutException. В противном случае выполнение конвейера продолжится и достигнет обработчика исключений по умолчанию:
Источник: https://anthonygiretti.com/2023/06/14/asp-net-core-8-improved-exception-handling-with-iexceptionhandler/
Улучшенная Обработка Исключений в ASP.NET Core 8. Окончание
Начало
Цепочка обработчиков исключений
Вы можете связать обработчики исключений в цепочку. При возврате False, конвейер продолжит выполнение и вызовет следующий обработчик исключений. Если все обработчики исключений возвратят False, конвейер выполнит все ПО промежуточного слоя, оставшиеся в конвейере. Вы также можете комбинировать обработчики исключений и промежуточное ПО.
Чтобы связать обработчики исключений, вы ДОЛЖНЫ определить обработчик исключений по умолчанию, который будет запускаться (и размещаться в самом конце) для обработки любого исключения, которое не было обработано предыдущими обработчиками. Порядок имеет значение! Ниже показан обработчик, который обрабатывает (только) TimeOutException и прерывает выполнение конвейера, если исключение фактически является TimeOutException. В противном случае выполнение конвейера продолжится и достигнет обработчика исключений по умолчанию:
public class TimeOutExHandler :Использование:
IExceptionHandler
{
private ILogger<DefaultExHandler> _logger;
public TimeOutExceptionHandler(
ILogger<DefaultExHandler> logger)
{
_logger = logger;
}
public async ValueTask<bool> TryHandleAsync(
HttpContext ctx,
Exception ex,
CancellationToken ct)
{
_logger.LogError(ex, "A timeout occurred");
if (ex is TimeoutException)
{
httpContext.Response.StatusCode =
(int)HttpStatusCode.RequestTimeout;
await httpContext.Response
.WriteAsJsonAsync(
new ProblemDetails
{ … });
return true;
}
return false;
}
}
var builder = WebApplication.CreateBuilder(args);Если при выполнении конечной точки возникнет TimeOutException, оно будет обработано TimeOutExHandler. Любой другой вид исключений достигнет обработчика TimeOutExHandler, но не будет им обработан (т.к. TimeOutExHandler вернёт false), а будет обработан DefaultExHandler.
builder.Services
.AddExceptionHandler<TimeOutExHandler>();
builder.Services
.AddExceptionHandler<DefaultExHandler>();
var app = builder.Build();
app.UseExceptionHandler(opt => { });
…
app.Run();
Источник: https://anthonygiretti.com/2023/06/14/asp-net-core-8-improved-exception-handling-with-iexceptionhandler/
👍9
День 1601. #ЗаметкиНаПолях
Полезные Расширения для IEnumerable. Начало
Мы уже рассматривали расширения для Task<T>, сегодня рассмотрим расширения для
IEnumerable.
Примечание: Будьте осторожны, если ваш тип IQueryable, потому что расширение может материализовать запрос. Вместо IEnumerable вы можете использовать IReadOnlyCollection, чтобы удостовериться, что вы имеете дело с материализованной коллекцией.
1. IsNullOrEmpty
Метод аналогичен методу для строк:
Популярная операция над коллекциями: одна коллекция содержит все элементы, соответствующие предикату, другая – все не соответствующие:
LINQ предоставляет метод Average для среднего арифметического, но нет метода для медианного значения:
Источник: https://steven-giesel.com/blogPost/1b8eaaef-01a3-4799-9a96-f0d37197d175
Полезные Расширения для IEnumerable. Начало
Мы уже рассматривали расширения для Task<T>, сегодня рассмотрим расширения для
IEnumerable.
Примечание: Будьте осторожны, если ваш тип IQueryable, потому что расширение может материализовать запрос. Вместо IEnumerable вы можете использовать IReadOnlyCollection, чтобы удостовериться, что вы имеете дело с материализованной коллекцией.
1. IsNullOrEmpty
Метод аналогичен методу для строк:
public static bool IsNullOrEmpty<T>(Использование:
this IEnumerable<T>? source)
=> source is null || !source.Any();
Enumerable.Empty<int>().IsNullOrEmpty();2. Разделение
// true
new[] { 1, 2 }.IsNullOrEmpty();
// false
((IEnumerable<int>)null).IsNullOrEmpty();
// true
Популярная операция над коллекциями: одна коллекция содержит все элементы, соответствующие предикату, другая – все не соответствующие:
public static (IEnumerable<T> True, IEnumerable<T> False)Использование:
Partition<T>(
this IEnumerable<T> source,
Func<T, bool> predicate)
{
ArgumentNullException.ThrowIfNull(source);
ArgumentNullException.ThrowIfNull(predicate);
var trueItems = new List<T>();
var falseItems = new List<T>();
foreach (var item in source)
{
if (predicate(item))
trueItems.Add(item);
else
falseItems.Add(item);
}
return (trueItems, falseItems);
}
var numbers = Enumerable.Range(0, 5);3. Медиана
var (even, odd) =
numbers.Partition(n => n % 2 == 0);
LINQ предоставляет метод Average для среднего арифметического, но нет метода для медианного значения:
public static double Median<T>(Использование:
this IEnumerable<T> source)
where T : IConvertible
{
ArgumentNullException.ThrowIfNull(source);
var sorted = source
.Select(x => x.ToDouble(
CultureInfo.InvariantCulture))
.OrderBy(x => x).ToList();
var count = sorted.Count;
if (count == 0)
throw new InvalidOperationException(
"Исходная коллекция пуста.");
if (count % 2 == 0)
return (sorted[count / 2 - 1] + sorted[count / 2]) / 2;
return sorted[count / 2];
}
var median = new[] { 1, 1, 1, 1, 5, 6, 7, 8, 9 }Окончание следует…
.Median(); // 5
var average = new[] { 1, 1, 1, 1, 5, 6, 7, 8, 9 }
.Average(); // 4.333333333333333
Источник: https://steven-giesel.com/blogPost/1b8eaaef-01a3-4799-9a96-f0d37197d175
👍14
День 1602. #ЗаметкиНаПолях
Полезные Расширения для IEnumerable. Окончание
Начало
4. Мода
Мода – число, которое чаще всего встречается в наборе:
5. Среднеквадратичное отклонение
Это мера того, насколько разбросаны числа:
Этот метод перемешивает элементы в последовательности, используя алгоритм перемешивания Фишера-Йейтса:
Полезные Расширения для IEnumerable. Окончание
Начало
4. Мода
Мода – число, которое чаще всего встречается в наборе:
public static IEnumerable<T>Использование:
Mode<T>(this IEnumerable<T> source)
{
ArgumentNullException.ThrowIfNull(source);
var groups = source.GroupBy(x => x);
var maxCount = groups.Max(g => g.Count());
return groups
.Where(g => g.Count() == maxCount)
.Select(g => g.Key);
}
var mode = new[] { 1, 1, 1, 1, 5, 6, 7, 8, 9 }Если два или более чисел встречаются одинаковое количество раз, мы получим несколько значений в результате.
.Mode(); // 1
5. Среднеквадратичное отклонение
Это мера того, насколько разбросаны числа:
public static doubleИспользование:
StandardDeviation<T>(
this IEnumerable<T> source)
where T : IConvertible
{
ArgumentNullException.ThrowIfNull(source);
var values = source
.Select(x => x.ToDouble(
CultureInfo.InvariantCulture))
.ToList();
var count = values.Count;
if (count == 0)
throw new InvalidOperationException(
"Исходная коллекция пуста.");
var avg = values.Average();
var sum = values.Sum(d => Math.Pow(d - avg, 2));
return Math.Sqrt(sum / count);
}
var stdDev = new[] { 1, 1, 1, 1, 5, 6, 7, 8, 9 }6. Перемешивание
.StandardDeviation(); // 3.1622776601683795
Этот метод перемешивает элементы в последовательности, используя алгоритм перемешивания Фишера-Йейтса:
public static IEnumerable<T>Использование:
Shuffle<T>(this IEnumerable<T> source)
{
ArgumentNullException.ThrowIfNull(source);
var arr = source.ToArray();
var random = Random.Shared;
for (var i = arr.Length - 1; i > 0; i--)
{
var idx = random.Next(i + 1);
(arr[i], arr[idx]) = (arr[idx], arr[i]);
}
return arr;
}
var numbers = Enumerable.Range(0, 5);Источник: https://steven-giesel.com/blogPost/1b8eaaef-01a3-4799-9a96-f0d37197d175
var random = numbers.Shuffle();
// 4, 0, 1, 3, 2
👍8👎1
День 1603. #ЧтоНовенького
Подсказки IntelliSense в Visual Studio Теперь Могут Управлять Завершениями Кода из GitHub Copilot
В последней версии GitHub Copilot изменение вашего выбора в списке IntelliSense в Visual Studio даёт GitHub Copilot дополнительный контекст, так что вы можете легко получить одно- и многострочные автодополнения кода в зависимости от вашего выбора.
В этом видео кратко показан процесс.
В последнем выпуске (версия 1.84+) предложения Copilot видны не только в списке IntelliSense, когда IntelliSense открыт, но ваш выбор IntelliSense также управляет предложениями Copilot. Это поможет вам исследовать и получить именно то автодополнение кода, которое вы ищете. Это особенно полезно в сочетании с помеченными звёздочками завершениями, которые встроенный в Visual Studio IntelliCode AI располагает вверху списка предложений. До этого пользователям Copilot в Visual Studio приходилось выбирать между принятием завершения Copilot или открытием списка IntelliSense, после чего предложения Copilot больше не отображались.
Нажмите
Разработчикам, возможно, придётся вручную обновить Copilot до версии 1.84. В Visual Studio выберите Extensions > Extension Manager > Updates (Расширения > Диспетчер расширений > Обновления), чтобы получить последнюю версию GitHub Copilot.
Чтобы начать работу с GitHub Copilot, убедитесь, что вы используете Visual Studio 2022 версии 17.4.4 или более позднюю. Затем ознакомьтесь с руководством в этом видео.
Copilot бесплатен для утверждённых GitHub студентов и коллаборантов популярных проектов с открытым исходным кодом. Подробности о Copilot для физических лиц и Copilot для бизнеса можно найти на веб-сайте GitHub.
Источник: https://devblogs.microsoft.com/visualstudio/github-copilot-visual-studio-intellisense/
Подсказки IntelliSense в Visual Studio Теперь Могут Управлять Завершениями Кода из GitHub Copilot
В последней версии GitHub Copilot изменение вашего выбора в списке IntelliSense в Visual Studio даёт GitHub Copilot дополнительный контекст, так что вы можете легко получить одно- и многострочные автодополнения кода в зависимости от вашего выбора.
В этом видео кратко показан процесс.
В последнем выпуске (версия 1.84+) предложения Copilot видны не только в списке IntelliSense, когда IntelliSense открыт, но ваш выбор IntelliSense также управляет предложениями Copilot. Это поможет вам исследовать и получить именно то автодополнение кода, которое вы ищете. Это особенно полезно в сочетании с помеченными звёздочками завершениями, которые встроенный в Visual Studio IntelliCode AI располагает вверху списка предложений. До этого пользователям Copilot в Visual Studio приходилось выбирать между принятием завершения Copilot или открытием списка IntelliSense, после чего предложения Copilot больше не отображались.
Нажмите
Tab
, чтобы принять элемент IntelliSense, затем снова Tab
, чтобы принять предложение Copilot. Чтобы скрыть список IntelliSense или принять предложение Copilot (посмотреть предложение с подсветкой синтаксиса), нажмите левую клавишу Ctrl
.Разработчикам, возможно, придётся вручную обновить Copilot до версии 1.84. В Visual Studio выберите Extensions > Extension Manager > Updates (Расширения > Диспетчер расширений > Обновления), чтобы получить последнюю версию GitHub Copilot.
Чтобы начать работу с GitHub Copilot, убедитесь, что вы используете Visual Studio 2022 версии 17.4.4 или более позднюю. Затем ознакомьтесь с руководством в этом видео.
Copilot бесплатен для утверждённых GitHub студентов и коллаборантов популярных проектов с открытым исходным кодом. Подробности о Copilot для физических лиц и Copilot для бизнеса можно найти на веб-сайте GitHub.
Источник: https://devblogs.microsoft.com/visualstudio/github-copilot-visual-studio-intellisense/
👍6
День 1604. #TipsAndTricks #PerformanceTips
Советы по Оптимизации Производительности
VI. Оптимизация обработки исключений
Обработка исключений — важнейший аспект программирования, но неправильное использование может привести к снижению производительности. Посмотрим, как эффективно и ответственно обрабатывать исключения.
1. Избегайте использования исключений для управления потоком
Обработка исключений как части нормального потока исполнения программы может значительно повлиять на производительность, создавая ненужную работу для оптимизатора и приводя к потенциальным проблемам производительности во время выполнения.
Плохо:
Хорошо:
2. Используйте фильтры исключений, чтобы свести к минимуму блоки захвата
Фильтры исключений помогают писать эффективный код обработки исключений, который делает блоки захвата более краткими и простыми в обслуживании.
Плохо:
Хорошо:
Источник: https://dev.to/bytehide/50-c-advanced-optimization-performance-tips-18l2
Советы по Оптимизации Производительности
VI. Оптимизация обработки исключений
Обработка исключений — важнейший аспект программирования, но неправильное использование может привести к снижению производительности. Посмотрим, как эффективно и ответственно обрабатывать исключения.
1. Избегайте использования исключений для управления потоком
Обработка исключений как части нормального потока исполнения программы может значительно повлиять на производительность, создавая ненужную работу для оптимизатора и приводя к потенциальным проблемам производительности во время выполнения.
Плохо:
tryЗдесь попытка парсинга недопустимой входной строки вызовет исключение. Генерация исключения здесь не идеальна для производительности и вынуждает обрабатывать FormatException как часть потока исполнения программы.
{
int.Parse(input);
}
catch (FormatException)
{
// обработка неправильного ввода
}
Хорошо:
if (int.TryParse(input, out int result))Здесь используется метод TryParse, чтобы не полагаться на исключение для потока исполнения. Такой подход обеспечивает лучшую производительность и более чистый код.
{
// Используем значение
}
else
{
// обработка неправильного ввода
}
2. Используйте фильтры исключений, чтобы свести к минимуму блоки захвата
Фильтры исключений помогают писать эффективный код обработки исключений, который делает блоки захвата более краткими и простыми в обслуживании.
Плохо:
tryЗдесь несколько исключений перехватываются в одном блоке catch с вложенными операторами if, используемыми для определения типа их обработки. Это может привести к более запутанному и сложному в сопровождении коду.
{
// …
}
catch (Exception ex)
{
if (ex is InvalidOperationException
|| ex is ArgumentNullException)
{
// обработка этих видов исключений
}
else
{
throw;
}
}
Хорошо:
tryХороший пример демонстрирует использование фильтров исключений. Это позволяет перехватывать исключения только при выполнении определённого условия, что упрощает блоки перехвата и устраняет необходимость в нескольких блоках перехвата или повторной генерации необработанных исключений. См. подробнее о фильтрах исключений
{
// …
}
catch (Exception ex) when (
ex is InvalidOperationException ||
ex is ArgumentNullException)
{
// обработка этих видов исключений
}
Источник: https://dev.to/bytehide/50-c-advanced-optimization-performance-tips-18l2
👍8
День 1605. #Карьера
9 Ментальных Моделей Сеньора, Которыми Должен Овладеть Каждый
Сеньор — это не звание, а способ мышления. Большинство руководств и курсов сосредоточены на том, чтобы научить вас новейшим фреймворкам, а не научить вас мыслить. Вот 9 ментальных моделей, которые помогут вам мыслить, как сеньор.
1. Принцип Парето: 20% усилий дадут 80% результатов. 20% вашей работы дадут вам 80% навыков. 20% ПО, над которым вы будете работать, обеспечат вам 80% признания. И т.д. Определите и сосредоточьте свои усилия на 20%, которые окупаются.
2. Закон Паркинсона: вы потратите всё время, которое выделите себе, независимо от того, сколько времени реально требуется. Выделив 100 часов на побочный проект, вы потратите 100 часов. Даже если его можно было сделать за 10. Нужны твёрдые сроки, иначе вы никогда не закончите.
3. Решения "с односторонней и двусторонней дверью": первые необратимы, так что не торопитесь, вторые можно легко отменить, поэтому избегайте оверинжиниринга. SQL и NoSQL база — решение первого типа. А выбор между for, foreach и LINQ можно легко изменить. Выбор фреймворка для изучения обратим – всегда можно переключиться на другой. А выбор между остаться разработчиком или стать техническим менеджером, обычно сложно откатить назад, т.к. непросто сохранить технические навыки на управленческой должности.
4. Закон Конвея: структура ПО будет имитировать структуру команд и организации, которые его создают. Команды разработчиков строятся вокруг технических навыков членов: frontend- и backend-инженеры, администраторы БД и специалисты по DevOps. ПО, которое они создают, будет отражать структуру их коммуникации. Обратите внимание на то, как команды общаются и организуются. Структура и качество ПО, которое они производят, будут такими же.
5. Круг Компетенции: знать, что вы знаете, а что нет, и придерживаться того, что вы знаете, пока круг не расширится. Лишь немногие разработчики понимают круг своей компетенции и работают над его улучшением. Большинство отвлекаются на новые фреймворки, перескакивают с одного дела на другое и превращают набор своих навыков в бессвязную кучу. Определите свой круг компетенции, оставайтесь в нём и неустанно работайте над его расширением!
6. Рассуждение от основ: чтобы глубоко понять что-то, надо разбить это на основополагающие элементы и рассуждать на этом уровне. В эпоху новых фреймворков и библиотек, разработчики, которым удаётся понять принципы, лежащие в их основе, могут с лёгкостью ориентироваться во всём этом хаосе.
7. Мышление второго порядка: всегда думайте о последствиях. Вы довольны своей работой, но компания сталкивается с финансовыми проблемами. Можно сменить работу, но надо пройти собеседование. Значит сначала нужно преодолеть свои страхи, а уже потом улучшать навыки. Вы можете думать, что всё будет хорошо, и ничего не делать. Но мышление второго порядка заставит вас понять, что это самый рискованный вариант. Хорошие исполнители всегда учитывают последствия своего поведения и действуют соответственно.
8. Обратное мышление: решение задачи является обратным задаче. Чтобы найти решение проблемы, подумайте о том, как проблему создать. Что делать, чтобы получить повышение? Подумаем, что нужно, чтобы оставаться на том же уровне: не улучшать навыки, делать минимум, лишь бы не уволили, не просить больше, не ходить на собеседования и т.п. Теперь переверните всё вышеописанное, и у вас есть решение проблемы!
9. Делать вещи правильно или делать правильные вещи: если вы делаете неправильные вещи, вы никогда не достигнете своих целей. Вы можете услышать о популярности Kubernetes и потратить сотни часов на его изучение и сертификацию по облачным сервисам. Но, если ваша работа с этим не связана, эти навыки не практикуются, а реальные ваши навыки (о которых могут спросить на собеседовании) деградируют. Это не проблема нехватки времени или дисциплины. Вы правильно делали неправильные вещи.
Источник: https://dev.to/dragosnedelcu/9-senior-developer-mental-models-every-programmer-should-master-1jlk
9 Ментальных Моделей Сеньора, Которыми Должен Овладеть Каждый
Сеньор — это не звание, а способ мышления. Большинство руководств и курсов сосредоточены на том, чтобы научить вас новейшим фреймворкам, а не научить вас мыслить. Вот 9 ментальных моделей, которые помогут вам мыслить, как сеньор.
1. Принцип Парето: 20% усилий дадут 80% результатов. 20% вашей работы дадут вам 80% навыков. 20% ПО, над которым вы будете работать, обеспечат вам 80% признания. И т.д. Определите и сосредоточьте свои усилия на 20%, которые окупаются.
2. Закон Паркинсона: вы потратите всё время, которое выделите себе, независимо от того, сколько времени реально требуется. Выделив 100 часов на побочный проект, вы потратите 100 часов. Даже если его можно было сделать за 10. Нужны твёрдые сроки, иначе вы никогда не закончите.
3. Решения "с односторонней и двусторонней дверью": первые необратимы, так что не торопитесь, вторые можно легко отменить, поэтому избегайте оверинжиниринга. SQL и NoSQL база — решение первого типа. А выбор между for, foreach и LINQ можно легко изменить. Выбор фреймворка для изучения обратим – всегда можно переключиться на другой. А выбор между остаться разработчиком или стать техническим менеджером, обычно сложно откатить назад, т.к. непросто сохранить технические навыки на управленческой должности.
4. Закон Конвея: структура ПО будет имитировать структуру команд и организации, которые его создают. Команды разработчиков строятся вокруг технических навыков членов: frontend- и backend-инженеры, администраторы БД и специалисты по DevOps. ПО, которое они создают, будет отражать структуру их коммуникации. Обратите внимание на то, как команды общаются и организуются. Структура и качество ПО, которое они производят, будут такими же.
5. Круг Компетенции: знать, что вы знаете, а что нет, и придерживаться того, что вы знаете, пока круг не расширится. Лишь немногие разработчики понимают круг своей компетенции и работают над его улучшением. Большинство отвлекаются на новые фреймворки, перескакивают с одного дела на другое и превращают набор своих навыков в бессвязную кучу. Определите свой круг компетенции, оставайтесь в нём и неустанно работайте над его расширением!
6. Рассуждение от основ: чтобы глубоко понять что-то, надо разбить это на основополагающие элементы и рассуждать на этом уровне. В эпоху новых фреймворков и библиотек, разработчики, которым удаётся понять принципы, лежащие в их основе, могут с лёгкостью ориентироваться во всём этом хаосе.
7. Мышление второго порядка: всегда думайте о последствиях. Вы довольны своей работой, но компания сталкивается с финансовыми проблемами. Можно сменить работу, но надо пройти собеседование. Значит сначала нужно преодолеть свои страхи, а уже потом улучшать навыки. Вы можете думать, что всё будет хорошо, и ничего не делать. Но мышление второго порядка заставит вас понять, что это самый рискованный вариант. Хорошие исполнители всегда учитывают последствия своего поведения и действуют соответственно.
8. Обратное мышление: решение задачи является обратным задаче. Чтобы найти решение проблемы, подумайте о том, как проблему создать. Что делать, чтобы получить повышение? Подумаем, что нужно, чтобы оставаться на том же уровне: не улучшать навыки, делать минимум, лишь бы не уволили, не просить больше, не ходить на собеседования и т.п. Теперь переверните всё вышеописанное, и у вас есть решение проблемы!
9. Делать вещи правильно или делать правильные вещи: если вы делаете неправильные вещи, вы никогда не достигнете своих целей. Вы можете услышать о популярности Kubernetes и потратить сотни часов на его изучение и сертификацию по облачным сервисам. Но, если ваша работа с этим не связана, эти навыки не практикуются, а реальные ваши навыки (о которых могут спросить на собеседовании) деградируют. Это не проблема нехватки времени или дисциплины. Вы правильно делали неправильные вещи.
Источник: https://dev.to/dragosnedelcu/9-senior-developer-mental-models-every-programmer-should-master-1jlk
👍22
День 1606. #BestPractices
Правильно Используем HttpClient. Начало
Самый простой способ делать HTTP-запросы в .NET — использовать HttpClient. Это отличная абстракция, особенно при передаче данных в JSON. К сожалению, легко неправильно использовать HttpClient.
Самый простой способ — создать новый экземпляр, задать необходимые свойства и использовать его для отправки запросов. Однако каждый экземпляр использует собственный пул соединений в целях изоляции. Если сервер находится под высокой нагрузкой, а приложение постоянно создаёт новые подключения, это может привести к исчерпанию доступных портов. Это вызовет исключение во время выполнения при попытке отправить запрос.
Вместо самостоятельного управления временем жизни HttpClient вы можете использовать IHttpClientFactory для создания экземпляра. Просто вызовите метод CreateClient и используйте возвращённый экземпляр HttpClient для отправки запросов.
Дорогостоящей частью HttpClient является фактический обработчик сообщений — HttpMessageHandler. Каждый HttpMessageHandler имеет внутренний пул HTTP-соединений, который можно использовать повторно. IHttpClientFactory будет кэшировать HttpMessageHandler и повторно использовать его при создании нового экземпляра HttpClient. Важным примечанием здесь является то, что экземпляры HttpClient, созданные IHttpClientFactory, должны быть недолговечными.
Использование IHttpClientFactory решит большинство проблем, связанных с созданием HttpClient вручную. Но нам по-прежнему необходимо настраивать параметры запроса по умолчанию каждый раз, когда мы получаем новый экземпляр из CreateClient().
Можно настроить именованный клиент. AddHttpClient принимает имя и делегат, который можно использовать для настройки параметров по умолчанию экземпляра HttpClient:
Источник: https://www.milanjovanovic.tech/blog/the-right-way-to-use-httpclient-in-dotnet
Правильно Используем HttpClient. Начало
Самый простой способ делать HTTP-запросы в .NET — использовать HttpClient. Это отличная абстракция, особенно при передаче данных в JSON. К сожалению, легко неправильно использовать HttpClient.
Самый простой способ — создать новый экземпляр, задать необходимые свойства и использовать его для отправки запросов. Однако каждый экземпляр использует собственный пул соединений в целях изоляции. Если сервер находится под высокой нагрузкой, а приложение постоянно создаёт новые подключения, это может привести к исчерпанию доступных портов. Это вызовет исключение во время выполнения при попытке отправить запрос.
Вместо самостоятельного управления временем жизни HttpClient вы можете использовать IHttpClientFactory для создания экземпляра. Просто вызовите метод CreateClient и используйте возвращённый экземпляр HttpClient для отправки запросов.
Дорогостоящей частью HttpClient является фактический обработчик сообщений — HttpMessageHandler. Каждый HttpMessageHandler имеет внутренний пул HTTP-соединений, который можно использовать повторно. IHttpClientFactory будет кэшировать HttpMessageHandler и повторно использовать его при создании нового экземпляра HttpClient. Важным примечанием здесь является то, что экземпляры HttpClient, созданные IHttpClientFactory, должны быть недолговечными.
// в Program регистрируем фабрику:Сокращаем дублирование с помощью именованных клиентов
services.AddHttpClient();
// в сервисе внедряем её
public class MyService
{
private IHttpClientFactory _factory;
public MyService(
IHttpClientFactory factory)
{
_factory = factory;
}
public async Task<string> GetAsync()
{
var client =
_factory.CreateClient();
client.BaseAddress =
new Uri("https://my.api.com");
…
}
}
Использование IHttpClientFactory решит большинство проблем, связанных с созданием HttpClient вручную. Но нам по-прежнему необходимо настраивать параметры запроса по умолчанию каждый раз, когда мы получаем новый экземпляр из CreateClient().
Можно настроить именованный клиент. AddHttpClient принимает имя и делегат, который можно использовать для настройки параметров по умолчанию экземпляра HttpClient:
services.AddHttpClient(Отличие в том, что теперь нужно указывать имя при получении экземпляра через CreateClient:
"client1",
(c) =>
{
c.BaseAddress =
new Uri("https://my.api.com");
}
);
var client = _factory.CreateClient("client1");Окончание следует…
Источник: https://www.milanjovanovic.tech/blog/the-right-way-to-use-httpclient-in-dotnet
👍21
День 1607. #BestPractices
Правильно Используем HttpClient. Окончание
Начало
Замена именованных клиентов типизированными
Недостатком использования именованных клиентов является необходимость разрешать HttpClient, каждый раз передавая имя. Добиться того же поведения можно через типизированный клиент, вызвав AddClient<TClient>(), где TClient – сервис, в который будет внедряться HttpClient.
Замечание: «Под капотом» всё равно используется именованный клиент, имя которого совпадает с именем типа. Также это зарегистрирует MyService с временем жизни transient.
Поскольку типизированный клиент является transient-сервисом, внедрение его в singleton-сервис приведёт к его кэшированию на время существования singleton-сервиса, что помешает типизированному клиенту реагировать на изменения DNS. Если вы хотите использовать типизированный клиент в singleton-сервисе, рекомендуется использовать SocketsHttpHandler в качестве основного обработчика и настроить свойство PooledConnectionLifetime. Также, т.к. теперь SocketsHttpHandler будет управлять пулом подключений, для него можно установить бесконечное время жизни:
Согласно рекомендациям Microsoft:
- Используйте статический или singleton-экземпляр HttpClient с настроенным PooledConnectionLifetime, так как это решает проблемы как исчерпания портов, так и отслеживания изменений DNS.
- Используйте IHttpClientFactory, если вы хотите переместить конфигурацию в одно место или использовать несколько разных клиентов, настроенных для разных вариантов использования. Но помните, что клиенты должны быть недолговечными, и после создания клиента фабрика больше не может управлять им.
- Используйте типизированный клиент, если вам нужна возможность настройки IHttpClientFactory.
Источник: https://www.milanjovanovic.tech/blog/the-right-way-to-use-httpclient-in-dotnet
Правильно Используем HttpClient. Окончание
Начало
Замена именованных клиентов типизированными
Недостатком использования именованных клиентов является необходимость разрешать HttpClient, каждый раз передавая имя. Добиться того же поведения можно через типизированный клиент, вызвав AddClient<TClient>(), где TClient – сервис, в который будет внедряться HttpClient.
Замечание: «Под капотом» всё равно используется именованный клиент, имя которого совпадает с именем типа. Также это зарегистрирует MyService с временем жизни transient.
services.AddHttpClient<MyService>(В MyService внедряем HttpClient, а не фабрику:
(c) =>
{
c.BaseAddress =
new Uri("https://my.api.com");
}
);
public class MyServiceИзбегайте типизированных клиентов в синглтонах
{
private HttpClient client;
public MyService(HttpClient client)
{
_client = client;
}
public async Task<string> GetAsync()
{
return await
client.GetFromJsonAsync(…);
}
}
Поскольку типизированный клиент является transient-сервисом, внедрение его в singleton-сервис приведёт к его кэшированию на время существования singleton-сервиса, что помешает типизированному клиенту реагировать на изменения DNS. Если вы хотите использовать типизированный клиент в singleton-сервисе, рекомендуется использовать SocketsHttpHandler в качестве основного обработчика и настроить свойство PooledConnectionLifetime. Также, т.к. теперь SocketsHttpHandler будет управлять пулом подключений, для него можно установить бесконечное время жизни:
services.AddHttpClient<MyService>(Какой вариант использовать?
(c) => { … }
)
.ConfigurePrimaryHttpMessageHandler(() =>
{
return new SocketsHttpHandler()
{
PooledConnectionLifetime
= TimeSpan.FromMinutes(15)
};
})
.SetHandlerLifetime(Timeout.InfiniteTimeSpan);
Согласно рекомендациям Microsoft:
- Используйте статический или singleton-экземпляр HttpClient с настроенным PooledConnectionLifetime, так как это решает проблемы как исчерпания портов, так и отслеживания изменений DNS.
- Используйте IHttpClientFactory, если вы хотите переместить конфигурацию в одно место или использовать несколько разных клиентов, настроенных для разных вариантов использования. Но помните, что клиенты должны быть недолговечными, и после создания клиента фабрика больше не может управлять им.
- Используйте типизированный клиент, если вам нужна возможность настройки IHttpClientFactory.
Источник: https://www.milanjovanovic.tech/blog/the-right-way-to-use-httpclient-in-dotnet
👍9
День 1608. #ЧтоНовенького
Новинки ASP.NET Core в .NET 8 Превью 5
Последний выпуск .NET 8 Preview 5 содержит важные дополнения в ASP.NET Core, которые кратко сегодня рассмотрим.
1. Продуктивность. Улучшения отладки в ASP.NET Core касаются введения атрибутов настройки отладки (DebuggerDisplay), упрощающих извлечение важной информации, связанной с такими типами, как HttpContext, HttpRequest, HttpResponse и ClaimsPrincipal, в отладчике Visual Studio.
2. «Незаметные повторные подключения» в SignalR. Эта новая функция направлена на минимизацию времени простоя клиентов, сталкивающихся с временными сбоями в работе сети. Временная буферизация данных как на стороне сервера, так и на стороне клиента и подтверждение сообщений обеспечивают более плавное взаимодействие с пользователем. В настоящее время эта поддержка ограничена клиентами .NET, использующими WebSockets, а конфигурация пока недоступна. Разработчики могут свободно использовать эту функцию и настраивать параметры options.UseAks в HubConnectionBuilder. Ожидается, что в будущих версиях будет представлена конфигурация на стороне сервера, настраиваемые параметры буферизации, ограничения времени ожидания и расширенная поддержка других видов клиентов.
3. Blazor
- Компонент Blazor Router теперь интегрируется с маршрутизацией конечных точек для обработки маршрутизации как на стороне сервера, так и на стороне клиента. Эта интеграция обеспечивает согласованную маршрутизацию к компонентам независимо от того, используется ли рендеринг на стороне сервера или на стороне клиента. Новый шаблон Blazor Web App включает образцы страниц, такие как Index.razor и ShowData.razor, которые используют маршрутизацию конечных точек и потоковую визуализацию для отображения данных прогноза погоды, а улучшенная поддержка навигации ожидается в будущих предварительных версиях .NET 8.
- Blazor Server предоставляет возможность включения интерактивности для отдельных компонентов. С помощью нового атрибута [RenderModeServer] разработчики могут активировать интерактивность для определённых компонентов, используя метод расширения AddServerComponents. Это усовершенствование обеспечивает большую гибкость и контроль при создании интерактивных приложений в режиме рендеринга Blazor Server.
4. Обобщённые атрибуты, добавленые в C#11, теперь предоставляют более ясные альтернативы атрибутам, которые ранее полагались на параметр типа System.Type. Обобщённые варианты теперь доступны для следующих атрибутов: ProducesResponseType<T>, Produces<T>, MiddlewareFilter<T>, ModelBinder<T>, ModelMetadataType<T>, ServiceFilter<T> и TypeFilter<T>.
5. Аутентификация и авторизация. Шаблоны проектов ASP.NET Core React и Angular удалили зависимость от Duende IdentityServer. Вместо этого теперь используется пользовательский интерфейс ASP.NET Core Identity по умолчанию и аутентификация по файлам cookie. Кроме того, представлен новый анализатор Roslyn, чтобы облегчить принятие более «краткого» синтаксиса с использованием API AddAuthorizationBuilder, где это применимо.
6. В области Native AOT добавлены улучшения для минимальных API, создаваемых во время компиляции. Они включают поддержку параметров, дополненных атрибутом AsParameters, и автоматический вывод метаданных для типов запросов и ответов.
Разработчики могут оставлять отзывы и следить за ходом работы над ASP.NET Core в .NET 8, посетив официальный репозиторий проекта на GitHub.
Источник: https://www.infoq.com/news/2023/06/aspnet-core-8-preview-5/
Новинки ASP.NET Core в .NET 8 Превью 5
Последний выпуск .NET 8 Preview 5 содержит важные дополнения в ASP.NET Core, которые кратко сегодня рассмотрим.
1. Продуктивность. Улучшения отладки в ASP.NET Core касаются введения атрибутов настройки отладки (DebuggerDisplay), упрощающих извлечение важной информации, связанной с такими типами, как HttpContext, HttpRequest, HttpResponse и ClaimsPrincipal, в отладчике Visual Studio.
2. «Незаметные повторные подключения» в SignalR. Эта новая функция направлена на минимизацию времени простоя клиентов, сталкивающихся с временными сбоями в работе сети. Временная буферизация данных как на стороне сервера, так и на стороне клиента и подтверждение сообщений обеспечивают более плавное взаимодействие с пользователем. В настоящее время эта поддержка ограничена клиентами .NET, использующими WebSockets, а конфигурация пока недоступна. Разработчики могут свободно использовать эту функцию и настраивать параметры options.UseAks в HubConnectionBuilder. Ожидается, что в будущих версиях будет представлена конфигурация на стороне сервера, настраиваемые параметры буферизации, ограничения времени ожидания и расширенная поддержка других видов клиентов.
3. Blazor
- Компонент Blazor Router теперь интегрируется с маршрутизацией конечных точек для обработки маршрутизации как на стороне сервера, так и на стороне клиента. Эта интеграция обеспечивает согласованную маршрутизацию к компонентам независимо от того, используется ли рендеринг на стороне сервера или на стороне клиента. Новый шаблон Blazor Web App включает образцы страниц, такие как Index.razor и ShowData.razor, которые используют маршрутизацию конечных точек и потоковую визуализацию для отображения данных прогноза погоды, а улучшенная поддержка навигации ожидается в будущих предварительных версиях .NET 8.
- Blazor Server предоставляет возможность включения интерактивности для отдельных компонентов. С помощью нового атрибута [RenderModeServer] разработчики могут активировать интерактивность для определённых компонентов, используя метод расширения AddServerComponents. Это усовершенствование обеспечивает большую гибкость и контроль при создании интерактивных приложений в режиме рендеринга Blazor Server.
4. Обобщённые атрибуты, добавленые в C#11, теперь предоставляют более ясные альтернативы атрибутам, которые ранее полагались на параметр типа System.Type. Обобщённые варианты теперь доступны для следующих атрибутов: ProducesResponseType<T>, Produces<T>, MiddlewareFilter<T>, ModelBinder<T>, ModelMetadataType<T>, ServiceFilter<T> и TypeFilter<T>.
5. Аутентификация и авторизация. Шаблоны проектов ASP.NET Core React и Angular удалили зависимость от Duende IdentityServer. Вместо этого теперь используется пользовательский интерфейс ASP.NET Core Identity по умолчанию и аутентификация по файлам cookie. Кроме того, представлен новый анализатор Roslyn, чтобы облегчить принятие более «краткого» синтаксиса с использованием API AddAuthorizationBuilder, где это применимо.
6. В области Native AOT добавлены улучшения для минимальных API, создаваемых во время компиляции. Они включают поддержку параметров, дополненных атрибутом AsParameters, и автоматический вывод метаданных для типов запросов и ответов.
Разработчики могут оставлять отзывы и следить за ходом работы над ASP.NET Core в .NET 8, посетив официальный репозиторий проекта на GitHub.
Источник: https://www.infoq.com/news/2023/06/aspnet-core-8-preview-5/
👍4👎1
День 1609. #TipsAndTricks #PerformanceTips
Советы по Оптимизации Производительности
VII. Обнуляемость и обнуляемые ссылочные типы
Обработка ссылочных типов, допускающих значение null, является важной частью программирования на C#, особенно для предотвращения исключений NullReferenceException. Рассмотрим несколько советов по безопасной работе с типами, допускающими значение null, без ущерба для производительности.
1. Используйте операторы объединения с null (??, ??=)
Операторы объединения с null помогают писать краткий и производительный код при работе с типами, допускающими значение NULL, гарантируя, что значения null заменяются значением по умолчанию.
Плохо:
Хорошо:
2. Используйте обнуляемые ссылочные типы, чтобы избежать исключений NullReferenceException во время выполнения
Обнуляемые ссылочные типы, появившиеся в C# 8.0, помогают перехватывать потенциальные исключения NullReferenceException во время компиляции, а не во время выполнения.
Плохо:
Хорошо:
Источник: https://dev.to/bytehide/50-c-advanced-optimization-performance-tips-18l2
Советы по Оптимизации Производительности
VII. Обнуляемость и обнуляемые ссылочные типы
Обработка ссылочных типов, допускающих значение null, является важной частью программирования на C#, особенно для предотвращения исключений NullReferenceException. Рассмотрим несколько советов по безопасной работе с типами, допускающими значение null, без ущерба для производительности.
1. Используйте операторы объединения с null (??, ??=)
Операторы объединения с null помогают писать краткий и производительный код при работе с типами, допускающими значение NULL, гарантируя, что значения null заменяются значением по умолчанию.
Плохо:
string input = GetNullableString();Неудачный пример демонстрирует многословный и менее производительный код при работе с нулевыми значениями.
if (input == null)
{
input = "default";
}
Хорошо:
var input = GetNullableString() ?? "default";Здесь используется оператор объединения с нулевым значением, который обеспечивает более лаконичный и эффективный способ обработки нулевых значений в C#. Это обеспечивает лучшую производительность и более понятный код.
2. Используйте обнуляемые ссылочные типы, чтобы избежать исключений NullReferenceException во время выполнения
Обнуляемые ссылочные типы, появившиеся в C# 8.0, помогают перехватывать потенциальные исключения NullReferenceException во время компиляции, а не во время выполнения.
Плохо:
string name = GetName();Здесь у нас потенциально во время выполнения может возникнуть исключение NullReferenceException, что может привести к неожиданным сбоям.
int length = name.Length;
Хорошо:
string? name = GetName();Используя обнуляемые ссылочные типы, и условный доступ с нулевым значением через оператор ?., вы можете избежать потенциальных исключений NullReferenceException в своём коде. Это помогает создавать более безопасный и производительный код, который легче понять как во время разработки, так и во время отладки.
int length = name?.Length ?? 0;
Источник: https://dev.to/bytehide/50-c-advanced-optimization-performance-tips-18l2
👍13