Comments 19
Ребята, я вас расстрою — оно не станет быстрее работать. Оно станет ещё медленнее.
Скорее — зависит. Если код тупо сидит и ждёт IO операцию, которая потом станет асинхронной, то асинхронность даст нам свободный поток, который может заняться другой полезной операцией, что ускорит общую обработку.
Конечно мы ждем улучшений когда привносим async, но конечный результат нужно тестировать, чтобы ответить на вопрос об «ускорении». Первый же, и самый очевидный результат, который можно предсказать без всякого тестирования, это то, что TPL привносит свой overhead, и не стоит его игнорировать.
Есть ещё одна плохая новость — приложение может работать значительно хуже после простого переписывания на async, без осознания особенностей конкурентной модели. Об этих особенностях я расскажу очень подробно в следующей статье.

Откровения от Додо Пиццы. Оказывается, асинк не спасает, когда в лог пишем последовательно!
В случае с NLog — у него синхронный интерфейс, поэтому thread, выполняющий логирование будет ждать завершения метода, например Logger.Info, и проблема будет общей как для блокирующего кода, так и async/await. Конфигурация асинхронного логгера будет означать, что метод не будет ожидать записи в файл, а просто поставит сообщение в очередь. Это решает проблему и для блокирующего кода, и async/await. Пропускная способность логгера с такой конфигурацией возрастает в десятки раз.

Не нравится мне ваша картинка с конфигом NLog.


Во-первых, при таком комбинировании способов записи асинхронная запись может заблокировать блокирующую — и проблема вернётся, пусть и в меньшем объёме.


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


В-третьих, раз уж вы упёрлись в скорость работы с логом — нужно сами логи тоже ускорять. Как минимум, keepFileOpen="true" прописать...

Во-вторых, строчки в логе при вашем способе могут идти вразнобой

А оно критично? Я думал, сейчас почти все пишется с именем сервиса и таймстампом, и кладется куда-нибудь типа elasticsearch для построения нормальных запросов, а не поиска в логе глазами.
Эдак можно сразу отправлять логи куда-нибудь по сети, не заморачиваясь хранением их на диске. Если логи хранятся на диске в текстовом формате — значит, чтение их человеком предусмотрено в качестве одного из вариантов.
Посмотрите свой конфиг ещё раз! Есть записи, которые копятся в очереди, и периодически записываются вместе. А есть записи, которые пишутся напрямую в файл построчно.

Первые записи будут блокировать вторые, как раз из-за сериализации таргетом «file». Первые и вторые записи будут идти вперемешку.
это тестовый конфиг, для бенчмарка. конечно вы правы — не нужно одновременно в оба логгера писать. либо в синхронный, либо в асинхронный
Асинхронный таргет NLog не означает одновременной попытки записывать что-либо в файл, да это и невозможно, файл здесь — последовательное устройство. То, что в NLog назывется асинхронной записью, на самом деле просто очередь, которая сбрасывается в файл через временные интервалы. Поэтому порядок сохраняется. Сами логи не нужно ускорять, и keepFileOpen ничего не прибавляет, потому что логи сбрасываются раз в несколько секунд. Скорость асинхронного лога становится в десятки раз больше, потому что на скорость в основном влияет не скорость записи на диск, а latency доступа к диску, то есть все упирается в количество обращений к диску.
Вы можете значительно упростить структуру конфигурации.
Просто добавьте атрибут async в элемент targets, NLog сам добавит асинхронные обертки.
<targets async="true"> 
  ... your targets go here ...
</targets>

Документация тут.
Если написать ядро вашей системы на C/C++ и грамотно спроектировать основную БД, где будут храниться только необходимые данные для текущей работы? А все остальные сервисы, не требующие «realtime», будут эти данные извлекать по мере возможности и самостоятельно хранить и обрабатывать.

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

Ну не верю я, что на любом современном процессоре с производительностью порядка 30ГФлопс/ядро нельзя рассчитать заказы пиццы!
На весь период используется транзакция в базе данных и некий ключ, общий для всех запросов.

Мы работаем, используя транзакцию для консистенции, у двух запросов происходит Contention на ключе общего объекта

Самое обидное, что наименее полезная операция в транзакции, которая залочила ключ, происходит в самом начале.

А можете пояснить, что за такой «общий ключ для всех запросов»? Это тоже самое, что и «ключ общего объекта»? И как его или их лочит транзакция? А то как-то непонятно.
один и тот же объект меню ресторана, хранящийся в той же базе данных, что и заказы клиентов

Все равно непонятно. Ок. Попробую спросить по-другому. Этот ключ, который объект меню ресторана, физически — это запись в БД? И под "лочит" понимается update lock в БД?

Only those users with full accounts are able to leave comments. Log in, please.