2010-03-09 4 views
16

Я написал приложение C#, которое работает постоянно в цикле, и несколько потоков записывают в файл log4net.Производительность Log4Net

Проблема в том, что чем дольше приложение работает, тем больше времени требуется для завершения цикла. Я запустил профилировщик ANTS Performance и заметил, что большая часть этого времени процессора тратится на журнал с log4.net.

В более подробных журналах больше используется ЦП, и через 30 минут он использует 100% CPU. Если отключить регистрацию, время, затраченное на цикл, остается постоянным с течением времени. Я посмотрел на Windows Performance Monitor, а физический диск - в большинстве случаев IDLE.

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

Вот пример моего файла конфигурации Log4net.xml:

<log4net> 
    <root> 
    <!-- Levels: OFF, DEBUG, INFO, WARN, ERROR, FATAL--> 
    <level value="INFO" /> 
    <appender-ref ref="RollingLogFileAppender" /> 
    </root> 

    <!--Logs to a file--> 
    <appender name="RollingLogFileAppender" type="log4net.Appender.RollingFileAppender"> 
    <file value="c:\\logs\\log-file.txt" /> 
    <appendToFile value="true" /> 
    <lockingModel type="log4net.Appender.FileAppender+ExclusiveLock" /> 
    <rollingStyle value="Composite" /> 
    <datePattern value="yyyyMMdd" /> 
    <maxSizeRollBackups value="20" /> 
    <maximumFileSize value="1MB" /> 
    <layout type="log4net.Layout.PatternLayout"> 
     <conversionPattern value="%date [%thread] %-5level %logger %L %M Schdl:[%property{scheduleContext}] Job:[%property{jobContext}] - %message%newline" /> 
    </layout> 
    </appender> 
</log4net> 

Я использую тот же регистратор от каждого объекта, который регистрируется.

log4net.ILog logger; 
    log4net.Config.BasicConfigurator.Configure(); 
    logger = log4net.LogManager.GetLogger(typeof(myProject)); 

Зачем использовать все больше и больше процессора, чем дольше он работает?

Любые рекомендации относительно того, как улучшить это, будут оценены.

+0

попробуйте использовать приложение ADOnet вместо этого? – ram

+0

ADOnet вызывал ту же проблему –

ответ

29

Вы настраиваете log4net в каждом объекте, который регистрируется? Это похоже на ваш код. Конфигурирование должно выполняться один раз в процессе, например. при запуске, а затем ваши объекты должны получить только регистратор.

Для каждого класса, который должен войти я, как правило, следующий шаблон:

class SomeClass 
{ 
    private static readonly ILog log = LogManager.GetLogger(typeof(SomeClass)); 
    ... 
} 

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

+0

Правильно, и каждый объект, который регистрирует журнал, может обращаться к регистратору: 'private static readonly ILog log = LogManager.GetLogger (typeof (MyProject));' –

+0

Вы правы, я запускал Configure() в каждый объект, который регистрируется. Я добавил статический член к каждому объекту журнала. Все идет нормально. После этого я буду выполнять больше тестов и обновлять их. –

+0

Спасибо @ Jamie, вот как я это делаю, если я не использую инъекцию зависимостей. –

-3

(я никогда не использовал log4net раньше, так принять то, что я рекомендую с осторожностью)

Вы можете написать асинхронной прокси Log4Net компонент и регистрации на выделенном потоке. Вы больше не будете блокировать свои основные потоки с попытками записать в файл журнала.

Это бесполезно, если в log4net уже есть асинхронный прокси.

+1

Возможно, лучший ответ мог бы быть предоставлен, если вы использовали log4Net :) – HansLindgren

4

Что вы делаете с этими свойствами контекста? Schdl:[%property{scheduleContext}] Job:[%property{jobContext}] Если вы назначаете нечто большее, чем просто значение здесь (или объект с простым методом ToString()), он может привести к снижению производительности. Обратитесь к руководству log4net под номером Active Property Values за то, что я говорю.

Peter Lillevold имеет хорошее предложение о настройке log4net только один раз. Вы также можете поместить следующую строку в свой сборник.CS-файл:

[assembly: log4net.Config.XmlConfigurator()] 

Следующая строка легко вырезать и вставить в любой класс, который делает каротаж:

private static readonly log4net.ILog _log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); 

Вы также можете попытаться повернуть на log4net внутреннюю регистрацию, чтобы увидеть, что происходит:

<appSettings> 
    <add key="log4net.Internal.Debug" value="true"/> 
</appSettings> 
+0

Im, используя свойства контекста, чтобы указать идентификаторы задания и расписания, оба являются Int32. Мне легче фильтровать журнал. Если эти числа порождают проблему с производительностью, я могу добавить эти переменные в сообщение журнала. –

+0

Я использую такие свойства из довольно занятых сайтов ASP.NET (многопоточное протоколирование в один файл FileAppender) без проблем. Простые значения не должны быть проблемой. – intoOrbit

Смежные вопросы