log4net BufferingForwardingAppender performance-Problem
EDIT 2 : ich habe das problem gelöst (siehe Antwort unten) Bitte beachten Sie, dass das problem potenziell betroffen sind alle appenders verziert mit BufferingForwardingAppender sowie allen appenders Erben von BufferingAppenderSkeleton (beziehungsweise : AdoNetAppender, RemotingAppender, SmtpAppender und SmtpPickupDirAppender) *
War ich dabei einige sehr basic-Bänke von log4net und ich versuchte, Sie zu schmücken, RollingFileAppender mit einem BufferingForwardingAppender.
Erlebe ich schreckliche Leistung werde durch die BufferingForwardingAppender statt direkt durch den RollingFileAppender und ich weiß wirklich nicht, was der Grund ist.
Hier ist meine Konfiguration:
<appender name="RollingLogFileAppender" type="log4net.Appender.RollingFileAppender">
<file value="c:\" />
<appendToFile value="false" />
<rollingStyle value="Composite" />
<datePattern value="'.'MMdd-HH'.log'" />
<maxSizeRollBackups value="168" />
<staticLogFileName value="false" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-5level %logger - %message%newline" />
</layout>
</appender>
<appender name="BufferingForwardingAppender" type="log4net.Appender.BufferingForwardingAppender">
<bufferSize value="512" />
<appender-ref ref="RollingLogFileAppender" />
</appender>
<root>
<level value="DEBUG" />
<appender-ref ref="BufferingForwardingAppender" />
</root>
Und hier ist der benchmark (sehr einfacher code):
var stopWatch = new Stopwatch();
stopWatch.Start();
for (int i = 0; i < 100000; i++)
{
Log.Debug("Hello");
}
stopWatch.Stop();
Console.WriteLine("Done in {0} ms", stopWatch.ElapsedMilliseconds);
Geht direkt durch RollingFileAppender die Ausgabe ist:
Getan 511 ms
Während werde durch die BufferingForwardingAppender Dekoration der RollingFileAppender :
Getan 14261 ms
Ist ca 30 mal langsamer.
Ich dachte, ich würde gewinnen einige Geschwindigkeit durch die Pufferung eine bestimmte Menge von log, bevor das schreiben auf die Datei, aber für einige Grund wird es die Dinge viel schlimmer.
Scheint mir, wie die Konfiguration ist OK, also das ist wirklich seltsam.
Hat jemand eine Ahnung?
Dank!
EDIT 1 :
Das Verhalten ist genau das gleiche durch umwickeln/verzieren einen FileAppender oder sogar ConsoleAppender (es gibt noch ein Beispiel von basic BufferingForwardingAppender Verpackung/Dekoration ConsoleAppender in log4net offiziellen config Proben .. und nichts spezifisches erwähnt, Umgang mit Leistung).
Nachdem einige Untersuchung/Profilierung, ich kann sehen, dass die Mehrheit der Zeit verdorben ist, innerhalb der BufferingForwardingAppender genauer gesagt in einem Aufruf WindowsIdentity.GetCurrent() ... aufgerufen wird, JEDES mal, wenn wir anrufen um zu Log.Debug()
.. im vorherigen Beispiel (100K mal in die sample-Quelle oben).
Aufrufe dieser Methode sind dafür bekannt, sehr teuer und sollten vermieden oder minimiert werden, ich weiß wirklich nicht, warum es wird genannt für jedes Ereignis protokollieren.
Bin ich wirklich komplett misconfiguring etwas /nicht zu sehen, etwas deutlicher, oder ist dass ein bug, der irgendwie und irgendwo, das ist, was ich versuche jetzt...
Die teilweise call-stack ist :
- AppenderSkeleton.DoAppend
- BufferingAppenderSkeleton.Append
- LoggingEvent.FixVolatileData
- LoggingEvent.get_UserName()
Einen Anruf zu get_LocationInformation()
ist auch in FixVolatileData, dass ein high-perf-Kosten (Erfassung der stack-trace jedes mal).
Ich versuche jetzt zu verstehen, warum das so extrem teuer FixVolatileData nennen (zumindest für das Update gebeten werden) geschieht, für jedes Ereignis protokollieren in diesem Zusammenhang in der Erwägung, dass geht direkt durch die gewickelten appender (direkt über ConsoleAppender/FileAppender ..) nicht der Durchführung dieser Art von operation.
Kommenden update Folgen, es sei denn, jemand hat eine Antwort auf alle diese 😉
Dank!
Du musst angemeldet sein, um einen Kommentar abzugeben.
Fand ich heraus, das Problem.
Den
BufferingForwardingAppender
erbt vonBufferingAppenderSkeleton
(wie andere appenders die Nutzung der logging-Ereignisse Puffern wieAdoNetAppender
,RemotingAppender
,SmtpAppender
..).Den
BufferingAppenderSkeleton
ist tatsächlich die Pufferung Protokollierung von Ereignissen, bevor Sie tatsächlich liefern Sie dem Ziel Appen, sobald eine bestimmte Bedingung erfüllt ist (Puffer voll zum Beispiel).Gemäß der Dokumentation des
LoggingEvent
Klasse (mit einem logging-event, und das mit allen Werten (message, threadid ...) vor der Veranstaltung) :Diese "flüchtigen" Eigenschaften sind, vertreten durch die
FixFlags
enumeration mit Kennzeichen wie die Nachricht, ThreadName, Benutzername, Identität ... so alle flüchtigen Eigenschaften.Es enthält auch das flag "None" (fix keine "Eigenschaften"), "All" (alles fix Eigenschaften) und "Partial" (fix nur eine bestimmte vorgeben dset von Eigenschaften).
Whem die
BufferingAppenderSkeleton
ist instanziert, STANDARDMÄßIG, setzt es die Fixierung auf "Alle" bedeutet, dass alle "flüchtigen" Eigenschaften, die behoben werden sollte.In diesem Zusammenhang, für jedes LoggingEvent angehängt, in der BufferingAppenderSkeleton, ALLE "flüchtigen" Eigenschaften werden festgelegt, bevor das Ereignis wird automatisch in den Puffer. Dies umfasst die Eigenschaften der Identität (Benutzername) und LocationInformation (stack-trace), auch wenn diese Eigenschaften nicht enthalten sind in der layout - (aber ich denke, es macht eine Art von Sinn, wenn das layout geändert wird, um auch diese Eigenschaften zu einem späteren Zeitpunkt, während ein Puffer, wurden bereits gefüllt mit LoggingEvents).
Aber in meinem Fall wirklich beeinträchtigt die Leistung. Ich bin nicht mit der Identität und der LocationInformation in meinem layout, und planen Sie nicht zu (vor allem für performance-Probleme)
Jetzt für die Lösung ...
Gibt es zwei Eigenschaften, die in
BufferingAppenderSkeleton
kann verwendet werden, um dieFixFlags
flag-Wert derBufferingAppenderSkeleton
(wieder standardmäßig ist es auf "ALLE", das ist nicht sehr nett !).Diese beiden Eigenschaften sind
Fix
(FixFlags-Typ) undOnlyFixPartialEventData
(Typ bool).Für eine Feinabstimmung der flag-Wert oder zu deaktivieren, alle fix, die
Fix
Eigenschaft verwendet werden soll.Für eine bestimmte partielle vordefinierte Kombination von flags (einschließlich der nicht-Identität oder LocationInfo), die
OnlyFixPartialEventData
kann stattdessen verwendet werden, mit der Einstellung "true".Wenn ich die Wiederverwendung der Konfiguration-Beispiel oben (in meiner Frage), die einzige änderung an der Konfiguration zu entfesseln, die Leistung wird unten angegeben:
Verwendung dieser modifizierten Konfiguration, die benchmark-code-Ausführung vorgestellt in meiner Frage oben, ist ein Sturz von ca 14000ms zu 230ms (60X schneller) !
Und wenn ich
<OnlyFixPartialEventData value="true"/>
anstatt deaktivieren alle fix ist es unter ca 350ms.Traurig, diese Flagge ist nicht sehr gut dokumentiert sind (außer in der SDK-Dokumentation, a little bit) .. also ich hatte zu Graben, in log4net Quellen zu finden das Problem.
Dies ist besonders problematisch, vor allem in der "reference" - Konfiguration Proben, wird dieses flag angezeigt wird nirgends (http://logging.apache.org/log4net/release/config-examples.html).
Also die Proben, die für BufferingForwardingAppender, und AdoNetAppender (und andere appenders Erben von BufferingAppenderSkeleton) geben SCHRECKLICH Leistung für Benutzer, selbst wenn das layout Sie verwenden, ist ziemlich minimal.
RollingFileAppender
: 511 ms vs 230 ms oder 350 ms (abhängig von der config) fürBufferingForwardingAppender
? Sicherlich eine Verbesserung, aber nicht so beeindruckend wie ich gedacht hätte...Ist es möglich, dass es ist, weil Sie nicht die Angabe eines layout-Muster, in der
BufferingForwardingAppender
aber Sie sind in derRollingLogFileAppender
daher dieBufferingForwardingAppender
ist auch alles, was in die Ausgabe einschließlich der username (%username)Unten ist ein interessanter blog-Artikel, die eine Liste der Optionen in der Muster-layouts und wie es aussieht hat er mehrere von Ihnen gekennzeichnet als langsam.
http://www.beefycode.com/post/Log4Net-Tutorial-pt-4-Layouts-and-Patterns.aspx