Pull to refresh
52
-4
Евгений Пешков @epeshk

User

Send message

Блокировка UI-потока гораздо заметнее блокировки фонового потока, поэтому Task.Run(() => ...) может быть меньшим злом.

Если запускаемая функция блокирует поток Thread Pool и это ухудшает производительность — её можно запустить не на Thread Pool, а в отдельном потоке, создав его вручную, или следующим образом (в нынешней реализации .NET этот способ тоже создаёт новый поток):

Task.Factory.StartNew(
  () => { ... },
  TaskCreationOptions.LongRunning|TaskCreationOptions.HideScheduler);

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

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

Такой способ будет работать, но дополнительный Task будет создаваться даже если в вызывающем коде нет контекста.
Можно доработать и перекладывать в Thread Pool только если контекст есть, получится эквивалент способа 3 (с await EscapeContext())

Корень проблемы .ConfigureAwait(...) на мой взгляд в том, что она сталкивает разработчиков библиотек и UI-кода:

  • разработчики библиотек не хотят засорять код .ConfigureAwait(false)

  • разработчики UI — .ConfigureAwait(true), await Task.Run(() => ...)

Наиболее автоматизированное решение сейчас — генерировать .ConfigureAwait(false) через Fody. Но Fody — сторонняя приблуда, ещё и усложняющая сборку проекта. Конечно хочется нативного решения, на уровне dotnet sdk или рантайма, и идей, как это сделать описано уже много.

Атрибут для сборки/параметр *.csproj
https://github.com/dotnet/csharplang/issues/2542

Переопредение оператора await на уровне проекта
https://github.com/dotnet/csharplang/issues/2649

Короткий синтаксис для `.ConfigureAwait(false)
https://github.com/dotnet/csharplang/discussions/645

Новый вид Task/Task<T>, свободный от контекста (даже есть реализация, но кажется, что overkill)
https://github.com/ufcpp/ContextFreeTask

Если добавить в язык условный await(false) или await!! грязи меньше не станет, поэтому остановимся на первом proposal. Его можно реализовать, например, в виде configureawait context, по аналогии с nullable context

С ним в *.csproj можно было бы писать:

<ConfigureAwait>false</ConfigureAwait>

А в файле с кодом *.cs:

#configureawait true
public static async Task ContextDependentMethod() { ... }
#configureawait restore

Только увы, proposal висит с 2015 года, и никакого результата. Cейчас .ConfigureAwait(false) реализован в виде структуры-обёртки над Task, т.е. на уровне стандартной библиотеки, реализация же proposal потребует знания о ConfigureAwait на стороне компилятора (Roslyn) или рантайма. Возможно, сложность заключается в этом. Или просто всем без разницы и время на это не выделили.

Можно ли var text = await Task.Run(() => GetTextAsync()); заменить на var text = await GetTextAsync().ConfigureAwait(false);
Тот же вопрос, почему используется Task.Run, а не ConfigureAwait(false)

.ConfigureAwait(false) имеет смысл только в методах, которым не нужно возвращаться на UI поток. Если использовать его внутри метода, которому важен контекст, то произойдёт исключение при попытке обновить UI (Text.Text = text;), если выполнение перейдёт на Thread Pool.

Метод Task.Run в этих примерах разделяет код, которому контекст важен, и код, который может работать на Thread Pool без возврата в исходный контекст. Весь код, запущенный через Task.Run ничего не узнает про контекст синхронизации, в то же время Task, возвращённый Task.Run может ожидаться в нужном контексте — хоть синхронно, хоть асинхронно.

Можно и так, и так.

Проблема в том, что нужно вспомнить в нужный момент об этой особенности функции .Split() и дописать либо параметр, либо .Where(...).

Также при использовании Console.ReadLine().Split() для формата ввода "в столбик" придётся полностью переписать код. А с поэлементным можно сделать универсальный метод, которому не важен ни тип разделителей, ни их количество:

int[] ReadIntArray()
{
  var array = new int[ReadInt()];
  for (int i = 0; i < array.Length; ++i)
    array[i] = ReadInt();
  return array;
}

Только, во-первых, надо использовать не DoWork, а сделать переменную и туда положить DoWork, иначе будет аллокация, о чём честно предупреждает Rider

В будущих версиях языка (начиная с C# 11) это будет не нужно
https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-11#improved-method-group-conversion-to-delegate

Я почему-то вначале подумал, что билеты на конференцию продаются прямо в приложении СберМегаМаркет, и на них можно потратить бонусы

Вот так постепенно с уязвимостями интела, требованиями Windows 11 к TPM и замедлением райзенов в ней же и затягиваются гайки добровольно-принудительного обновления железа. Конечно не отрицаю, что уязвимость может быть реальной, но могли и настройку сделать вместо игр с подбором версии драйвера.

P.S. Чего стоит одно название утилиты, проверяющей требования для Windows 11 — "PC Health Check". Как будто PC не health, если не работает на Win 11

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

Это решение, конечно, учитывая, что так можно добавить и чёрный список слов для фильтрации рекламы от самих каналов, но:

  • Чужой сборке нельзя доверять в наше непростое время

  • При обновлениях клиента понадобится пересобирать его самостоятельно (а в случае с чужим форком — изучать все новые патчи)

  • Необходимо проделать на всех платформах, особый геморрой на iOS

  • У меня ещё свежи воспоминания о войне ICQ с альтернативными клиентами. Если такое произойдёт с телеграмом — это конец. Но это очень маловероятно, вряд ли телеграм опустится до баннеров

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

Но пересобрать ещё и с фильтрацией сообщений — годная тема

Это на какой монете получается выжать 2-3к? Это нереалистично. Полгода окупаемость будет если крипта и дальше вверх пойдёт, по нынешним ценам больше года. Ну а так действительно здравая мысль для тех, кто хочет отбить затраты, со своими рисками, конечно

Ray Tracing сам по себе бьёт по производительности, большинство игр и без него выглядят достойно, учитывая, что игры которые выйдут скоро разрабатываются давно — вряд ли лучи будут минимальным требованием. Если есть возможность взять 1070ti/1080/1080ti или из новых 1660super и разница в цене с 30 серией ощутимая — почему бы и нет, если играть только в FullHD. Не самые новые игры, Ведьмак 3 например, пойдут и в 2к. Но 3060(ti) держится наравне с топами 10 поколения.

Ещё есть вариант купить ноут с ноутбучной 3060, но там свои проблемы — перегревы, урезанная мощность видеокарт, невозможность апгрейда

Ещё вариант на computeruniverse посмотреть, с доставкой и пошлиной может выйти дешевле, чем в местных магазинах

Чёрный список слов, сообщения с которыми не отображаются, как в твиттере. Но такое не добавят — это убьёт рекламу в каналах. Похоже всё же придётся это костылить для себя самостоятельно, но с iOS клиентом это будет полный гемор (но от чтения спама я сойду с ума быстрее)

Похоже попытка прорекламировать личный блог провалилась. Ведь сейчас полная версия статьи доступна лишь в веб архиве
http://web.archive.org/web/20130315164343/http://www.claris-verbis.ru/TN_VA_IPS

Хорошими делами прославиться нельзя.

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

Я конкретно о категории Process, которая собирает данные медленно. Соответствие между инстансами в ней и PID как-то применимо в других категориях? Выглядит так, что в других категориях — свои имена инстансов, а в самой категории Process нет метрик, без которых нельзя обойтись или извлечь другим способом

Атомарность есть на уровнях NtQuerySystemInformation и Pdh, если в один query добавить сразу несколько каунтеров, включая ID Process.


.net.process — это тот, что System.Diagnostics.Process? Дотнетные обёртки что для процесса, что для перфкаунтеров сами по себе тяжеловесные. В версии 4.7.2 и Core частично исправили ситуацию, но все равно.


Hard-way ETW, конечно, не предлагаю, но там есть и эвенты с уже готовыми метриками, перформанс их конечно надо исследовать. Hard-way с ручным подсчётом если и использовать, то, например, для метрик по времени работы GC, которые не вытащить другими способами.


А какие уникальные метрики нужны из категории Process?

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

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


Если хочется прочитать что-то из категории Process, то это, имхо, лучше всего сделать добавив в PdhQuery сразу нужный каунтер и ID Process. Или пойти в обход каунтеров и вызывать напрямую NtQuerySystemInformation(5) (5 — это SystemProcessInformation). Так или иначе вся категория Process сведётся к этому вызову. На практике же хватает периодического обновления мапа между инстансами и process id.


Но т.к. NtQuerySystemInformation(5)работает за O(processes+threads), то при утечке потоков или их некорректном завершении из-за кривых драйверов, например, имеет огромные шансы добить систему окончательно, имхо лучше вообще категории Process и Thread избегать по возможности. Например использовать более легкие функции GetProcessMemoryInfo, GetProcessTime/GetSystemTime для мониторинга метрик по памяти/cpu одного процесса. IO метрики по диску надо придумать, откуда ещё можно вытащить, если они нужны. В IPHlpApi можно взять метрики по сетевой активности.


Если начинать использовать ETW — то логично это делать не только для отслеживания запуска/завершения процессов, а извлекать куда более интересные метрики из эвентов. Сходу не скажу, но скорее всего через ETW можно вытащить большинство метрик, что есть в перф каунтерах (как минимум стоит в PerfView протыкать IIS и MemInfo), но тут опять надо смотреть, из насколько медленных источников эти метрики попадают в ETW, не из того же ли NtQuerySystemInformation в случае метрик по памяти.


А для мониторинга бизнес-логики по типу запросов, имхо, нет ничего надёжнее ручной отправки из приложения

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

Как будто зловред и так не может проникнуть в сеть через корпоративный VPN или просто получить доступ к рабочим файлам, не будучи подключенным к офисной сети

Information

Rating
Does not participate
Works in
Registered
Activity