Во многих службах, над которыми я работаю, ведется много регистрации. Сервисы - это сервисы WCF (в основном), которые используют класс .NET EventLogger.
Я нахожусь в процессе улучшения производительности этих сервисов, и я подумал, что асинхронное ведение журнала повысит производительность.
Я не знаю, что происходит, когда несколько потоков просят войти в систему, и если это создает узкое место, но даже если это не так, я все еще думаю, что это не должно мешать действительному процессу, который выполняется.
Я думаю, что я должен вызвать тот же метод журнала, который я сейчас вызываю, но сделать это с использованием нового потока, продолжая при этом сам процесс.
Несколько вопросов об этом:
Это нормально?
Есть ли минусы?
Должно ли это быть сделано по-другому?
Может быть, это так быстро, что это даже не стоит усилий?
Ответы:
Отдельная тема для операции ввода-вывода звучит разумно.
Например, было бы не хорошо регистрировать, какие кнопки пользователь нажал в том же потоке пользовательского интерфейса. Такой пользовательский интерфейс будет зависать наугад и иметь медленную воспринимаемую производительность .
Решение состоит в том, чтобы отделить событие от его обработки.
Здесь много информации о проблемах производителей и потребителей и очереди событий из мира разработки игр
Часто есть такой код
Этот подход приведет к конфликту потоков. Все обрабатывающие потоки будут бороться, чтобы иметь возможность получить блокировку и запись в один и тот же файл одновременно.
Некоторые могут попытаться снять замки.
Невозможно предсказать результат, если 2 потока будут вводить метод одновременно.
Так что со временем разработчики вообще отключат ведение журнала ...
Можно ли это исправить?
Да.
Допустим, у нас есть интерфейс:
Вместо того, чтобы ждать блокировки и выполнять блокировку файловой операции при каждом
ILogger
вызове, мы добавим новое сообщение LogMessage в очередь сообщений Penging и вернемся к более важным вещам:Мы сделали с этим простым Asynchronous Logger .
Следующим шагом является обработка входящих сообщений.
Для простоты, давайте запустим новый поток и будем ждать до тех пор, пока приложение не закроется, или Asynchronous Logger добавит новое сообщение в очередь ожидания .
Я прохожу цепочку заказных слушателей. Возможно, вы захотите просто отправить каркас регистрации вызовов (
log4net
и т. Д.)Вот остаток кода:
Точка входа:
источник
Ключевыми факторами, которые необходимо учитывать, являются ваша потребность в надежности файлов журналов и потребность в производительности. Обратитесь к минусам. Я думаю, что это отличная стратегия для ситуаций с высокими показателями.
Это нормально - да
Существуют ли какие-либо недостатки - да, - в зависимости от критичности вашего ведения журнала и вашей реализации может произойти любое из следующих действий - журналы записываются не по порядку, действия потока журнала не завершаются до завершения действий события. (Представьте себе сценарий, в котором вы регистрируете «начало соединения с БД», а затем сбиваете сервер, событие журнала может никогда не записаться, даже если событие произошло (!))
Если это будет сделано по-другому - вы можете посмотреть на модель Disruptor, так как она почти идеальна для этого сценария
Может быть, это так быстро, что это даже не стоит усилий - не согласен. Если у вас логика «приложения», и единственное, что вы делаете, - это записывает логи активности - тогда вы будете на несколько порядков меньше задерживать за счет разгрузки журналов. Однако, если вы полагаетесь на 5-секундный вызов БД SQL для возврата перед регистрацией 1-2 операторов, преимущества будут неоднозначными.
источник
Я думаю, что регистрация - вообще синхронная операция по своей природе. Вы хотите регистрировать вещи, если они происходят, или если они не зависят от вашей логики, поэтому, чтобы что-то регистрировать, эта вещь должна быть оценена в первую очередь.
Сказав это, вы можете улучшить производительность своего приложения, кэшируя логи, а затем создавая поток и сохраняя их в файлы, когда у вас есть связанная с процессором операция.
Вам нужно грамотно идентифицировать свои контрольные точки, чтобы вы не потеряли важную информацию для регистрации в течение этого периода кэширования.
Если вы хотите повысить производительность своих потоков, вам необходимо сбалансировать операции ввода-вывода и загрузки процессора.
Если вы создадите 10 потоков, которые все выполняют IO, то вы не получите повышения производительности.
источник
Ведение журнала асинхронно - единственный путь, если вам нужны низкие задержки в потоках журналирования. То, как это делается для максимальной производительности, заключается в использовании схемы прерывателя для обмена потоками без блокировок и без мусора. Теперь, если вы хотите разрешить нескольким потокам одновременно регистрировать один и тот же файл, вы должны либо синхронизировать вызовы журнала и заплатить цену за конфликт блокировки, либо использовать мультиплексор без блокировки. Например, CoralQueue предоставляет простую очередь мультиплексирования, как описано ниже:
Вы можете взглянуть на CoralLog, который использует эти стратегии для асинхронной регистрации.
Отказ от ответственности: я являюсь одним из разработчиков CoralQueue и CoralLog.
источник