Почему замки?
Насколько я помню, в Enterprise Library используется класс .NET Tracelistener, у которого есть свойство IsThreadSafe. Если слушатель является потокобезопасным, синхронизация не выполняется.
Для файла в качестве устройства вывода нет причин синхронизировать доступ из нескольких потоков, если только StreamWriter , который содержит буфер записи, может быть поврежден из-за несинхронизированных записей. По этой причине вам нужно получить синхронизированный StreamWriter для записи в файл из разных потоков.
Но, во всяком случае, это больше академический интерес. Если вы разрешаете писать только одному потоку за раз, вы все равно можете генерировать несколько сотен МБ выходных данных, что приводит к падению даже самого быстрого жесткого диска. Вы связаны с IO, когда пишете в файл. Самая медленная вещь во всей цепочке - это жесткий диск, а не ваша синхронизированная запись в файл.
Но иногда приятно иметь вывод нескольких процессов в одном файле. Например, Log4Net не может сделать это.
... Как получить несколько процессов для входа
в тот же файл?
FileAppender удерживает блокировку записи
файл журнала во время регистрации. это
предотвращает запись других процессов
в файл, поэтому это не
можно иметь несколько процессов
войти непосредственно в тот же файл журнала,
даже если они на одной машине. ...
Производительность форматирования
Даже если вы считаете, что блокировка снижает производительность, часто пропускаются и другие затраты. Настраиваемый формат вывода очень хорош, но по крайней мере форматирование в Enterprise Library до 4.0 было очень медленным . Я сделал это в 13 раз быстрее, что привело к увеличению пропускной способности чистых файлов в 2 раза.
Одновременная запись в файл
С небольшой магией Win32 возможно для одновременной записи надежных данных из разных процессов в один и тот же файл.
Но вернемся к вашему вопросу, если синхронизация необходима: она может потребоваться в зависимости от устройства вывода.
Scalabilty
Если вас беспокоит масштабируемость, вам нужен буфер для каждого потока, который объединяется в определенный момент времени, чтобы обеспечить быстрый сбор данных. Затем вы можете реализовать глобальный кольцевой буфер, который получает из всех потоков отформатированные данные, где самые старые данные перезаписываются. Когда происходит что-то интересное, вы можете сбросить весь кольцевой буфер на диск. Этот дизайн в ~ 10-20 раз быстрее любого файлового приложения. Windows Event Tracing использует трюк с кольцевым буфером, который невероятно быстр.
Поскольку вы спрашивали о блокировке, я думаю, что speed - ваша главная задача. Если это предположение верно, вы должны взглянуть на каркас трассировки , подобный тому, который использует инструмент ApiChange . Он имеет несколько инновационных подходов, таких как автоматическое отслеживание исключений, когда ваш метод оставлен с исключением, или внедрение ошибок для модульного тестирования пути ошибки без необходимости изменения кода продукта.
Чтобы быть масштабируемым, вы должны различать ведение журнала и трассировку, как я объяснил здесь: Ведение журнала не отслеживается. .
Lock Free
Если вы хотите создать масштабируемую инфраструктуру трассировки, вам нужно передать все свои данные для одного вызова трассировки в качестве неизменяемых данных, отформатировать данные в строку и передать их на ваше устройство вывода. Это может быть так просто, как (C # псевдокод)
- Trace.Info ("blahh {0}", data);
- traceString = Format (formatString, args, CurrentTime);
- Write (traceString);
Когда данные не сохраняются в классе или члены класса не изменяются после его инициализации, вам никогда не понадобится блокировка. Вы должны быть осторожны, чтобы поделиться, например, буфер форматирования между потоками. Чтобы быть масштабируемым, вам необходимо установить приоритеты проектирования для безопасности потоков в следующем порядке.
- Изоляция
Это, безусловно, лучшее решение. Если проблему можно разделить так, чтобы несколько потоков могли работать независимо, вам никогда не нужно думать о блокировке или общих данных.
- Неизменность
Вторым лучшим решением является обмен данными, но как только несколько потоков могут «видеть» их, они никогда не должны изменяться. Это может быть достигнуто, например, с объектами, которые имеют только геттеры и все данные передаются через ctor.
- Замок
Если вы используете блокировку без блокировки или какая-то стратегия блокировки не имеет большого значения. Вы находитесь в мире боли, где вы должны обращать внимание на кэши процессора, ложное совместное использование , и если вы отважны, вы даже можете попробовать какой-нибудь метод без блокировки только для того, чтобы узнать, что в лучшем случае он работает в два раза быстрее, чем нормальный замок. В некоторых случаях код без блокировки может быть медленнее.
Если вы хотите больше узнать о деталях потоков, я рекомендую блог Джо Даффи .
Трассировка стратегии
Для написания поддерживаемого программного обеспечения вы должны иметь возможность следить за вашим приложением и потоком данных. Только тогда вы сможете диагностировать проблемы, которые происходят только на вашем сайте клиента. Это окупается, чтобы «загромождать» ваш код следами, которые дают вам достаточно информации для быстрой диагностики проблемы. Вы можете отслеживать слишком много или слишком мало или не соответствующие данные. Одна хорошая линия трассировки, которая действительно коррелирует, например, Ваша строка запроса XPath с файлом, с которым она работает, намного лучше, чем разбросанные фрагменты информации в вашем файле журнала.
С уважением,
Алоис Краус