EDIT 2 : me han resuelto el problema (véase la respuesta a continuación) por Favor, tenga en cuenta que el problema afecta potencialmente a todos los appenders decoradas con BufferingForwardingAppender así como todos los appenders heredar de BufferingAppenderSkeleton (respectivamente : AdoNetAppender, RemotingAppender, SmtpAppender y SmtpPickupDirAppender) *

Yo estaba haciendo algunas muy básicas banquillos de log4net y traté de decorar un RollingFileAppender con un BufferingForwardingAppender.

Tengo experiencia terrible rendimiento a través de la BufferingForwardingAppender en lugar de directamente a través de la RollingFileAppender y yo realmente no obtener la razón.

Aquí está mi configuración:

<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>

Y aquí es el punto de referencia (código muy simple):

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);

Va directamente a través de RollingFileAppender la salida es:

Hecho en 511 ms

Mientras que ir a través de la BufferingForwardingAppender la decoración de la RollingFileAppender :

Hecho en 14261 ms

Que es aproximadamente 30 veces más lento.

Yo pensaba que iba a ganar algo de velocidad por el almacenamiento en búfer de una cierta cantidad de registro antes de escribirlos en el archivo, sin embargo, por alguna razón, se pone las cosas mucho peor.

Me parece que la configuración está bien, así que esto es realmente extraño.

Alguien tiene una idea?

Gracias!

EDIT 1 :

El comportamiento es estrictamente la misma por la envoltura/de decorar una FileAppender o incluso ConsoleAppender (todavía hay un ejemplo básico de BufferingForwardingAppender de envoltura/de decorar ConsoleAppender en log4net oficial config muestras .. y nada específico mencionado tratar con el rendimiento).

Después de algunas investigaciones/perfiles, puedo ver que la mayoría de las veces se echa a perder en el interior de la BufferingForwardingAppender más específicamente en una llamada a WindowsIdentity.GetCurrent() … se llama CADA vez que se hace una llamada a Log.Debug() .. en el ejemplo anterior (de 100 mil veces en el código fuente de ejemplo de arriba).

Las llamadas a este método son conocidos por ser muy costoso y debe ser evitado o minimizado, yo realmente no obtener por qué se llama para cada evento de registro.
Realmente estoy completamente desconfiguración de algo /no ver algo evidente, o que es un bug de alguna manera, en algún lugar, esto es lo que estoy tratando de averiguar ahora…

El parcial de la pila de llamadas es :

  • AppenderSkeleton.DoAppend
  • BufferingAppenderSkeleton.Anexar
  • LoggingEvent.FixVolatileData
  • LoggingEvent.get_UserName()

Una llamada a get_LocationInformation() también se hace en FixVolatileData, incurrir en un alto perf costo (captura de la traza de la pila cada vez).

Ahora estoy tratando de entender por qué esta extremadamente costoso FixVolatileData llamada (al menos para la revisión pidió a) que pasa por cada evento de registro en este contexto, considerando que va directamente a través de la envuelta appender (directamente a través de ConsoleAppender/FileAppender ..) no realizar este tipo de operación.

Próxima actualización a seguir, a menos que alguien tiene una respuesta a todo esto 😉

Gracias!

InformationsquelleAutor darkey | 2012-07-03

2 Comentarios

  1. 39

    Me enteré de la cuestión.

    La BufferingForwardingAppender es la herencia de BufferingAppenderSkeleton (como otros appenders haciendo uso de los eventos de registro de almacenamiento en búfer, tales como AdoNetAppender, RemotingAppender, SmtpAppender ..).

    La BufferingAppenderSkeleton es en realidad el búfer de registro de los eventos antes de la entrega de ellos a la meta appender una vez que se cumple una condición determinada (buffer lleno, por ejemplo).

    De acuerdo a la documentación de la LoggingEvent clase (que representa a un evento de registro, y que contiene todos los valores (mensaje, threadid …) del evento) :

    Algunos eventos de registro de propiedades se consideran «volátil», que es el
    los valores son correctos en el momento en que el evento se entrega a los appenders,
    pero no va a ser constante en cualquier momento después. Si un evento es
    ser almacenados y procesados en un tiempo posterior, estos valores volátiles
    debe ser fijo bycalling FixVolatileData. Hay un rendimiento
    pena de incurrir llamando FixVolatileData pero es esencial para
    mantener la consistencia de los datos

    Estos «volátil» propiedades están representados por el FixFlags enumeración que contiene indicadores tales como Mensajes, ThreadName, nombre de Usuario, la Identidad … así que todas las propiedades volátiles.
    También contiene la bandera «None» (fix sin propiedades), «Todos» (revisión de todas las propiedades) y «Parcial» (fix sólo un cierto predefinir dset de propiedades).

    Cuando el BufferingAppenderSkeleton es instanciated, por DEFECTO se establece la fijación de «Todo» lo que significa que todos los «volátiles» propiedades deben ser corregidos.

    En ese contexto, para cada LoggingEvent anexa en el BufferingAppenderSkeleton, TODOS los «volátiles» propiedades será corregido antes de que el evento se inserta en el búfer. Esto incluye las propiedades de la Identidad (nombre de usuario) y LocationInformation (seguimiento de la pila), incluso si estas propiedades no están incluidos en el diseño (pero creo que se hace algún tipo de sentido si el diseño se cambió para incluir estas propiedades en un momento posterior, mientras que un buffer ya se ha llenado con LoggingEvents).

    Sin embargo en mi caso esto me DUELE mucho el rendimiento. No estoy incluyendo la Identidad y LocationInformation en mi diseño, y no en plan a (principalmente para problemas de rendimiento)

    Ahora para la solución de …

    Hay dos propiedades en BufferingAppenderSkeleton que puede ser utilizado para el control de la FixFlags valor del indicador de la BufferingAppenderSkeleton (una vez más, por defecto está establecido a «TODOS», que no es muy agradable !).
    Estas dos propiedades son Fix (FixFlags tipo) y OnlyFixPartialEventData (tipo bool).

    Para una sintonía fina de la bandera de valor o para deshabilitar todos los fix, el Fix de la propiedad debe ser utilizado.
    Para un determinado parcial combinación predefinida de banderas (no incluida la Identidad o LocationInfo), el OnlyFixPartialEventData puede utilizarse en su lugar se establece en «true».

    Si puedo reutilizar la configuración del ejemplo anterior (en mi pregunta), el único cambio hecho a la configuración para dar rienda suelta a rendimiento se indica a continuación:

    <appender name="BufferingForwardingAppender" type="log4net.Appender.BufferingForwardingAppender">
      <bufferSize value="512" />
      <appender-ref ref="RollingLogFileAppender" />
      <Fix value="0"/> <!-- Set Fix flag to NONE -->
    </appender>

    El uso de esta modificación de la configuración, el punto de referencia de la ejecución de código presentado en mi pregunta anterior, está cayendo desde aprox 14000ms a 230ms (60 VECES más rápido) !
    Y si yo uso <OnlyFixPartialEventData value="true"/> en lugar de deshabilitar todos los fix que está tomando aprox 350ms.

    Lamentablemente, este indicador no está muy bien documentada (excepto en la documentación del SDK, un poco) .. así que tuve que cavar profundamente en log4net fuentes para encontrar el problema.

    Esto es particularmente problemático, especialmente en la «referencia» de la configuración de las muestras, este indicador aparece por ningún lado (http://logging.apache.org/log4net/release/config-examples.html).
    Así, los ejemplos de BufferingForwardingAppender, y AdoNetAppender (y otros appenders heredar de BufferingAppenderSkeleton) va a dar un mal rendimiento para los usuarios, incluso si la presentación que se está utilizando es bastante mínima.

    • Hola, Somos de registro de hilo, de excepción y de un campo personalizado de identificación. Estamos utilizando log4net.Appender.AdoNetAppender. Tratamos de especificar <Fix=»0″/> y el resultado fue detenido el registro de valores de Hilo y de la Excepción. También la costumbre de identificación de campo se inició el registro de forma incorrecta. A pesar de que el rendimiento mejora de casi 10 veces. Puedes dar alguna pista ?
    • Para AdoNetAppender usted necesita para asegurarse de que esas cosas son fijos. Sume los valores de las cosas que usted necesita fijo en esta documentación de referencia: logging.apache.org/log4net/release/sdk/…
    • Gracias por la solución! Así que el final números serían RollingFileAppender: 511 ms vs 230 ms o 350 ms (dependiendo de la configuración) para BufferingForwardingAppender? Sin duda una mejora, pero no es tan impresionante como yo pensaba…
  2. 0

    Es posible que sea porque no son la especificación de un modelo de diseño en el BufferingForwardingAppender pero está en el RollingLogFileAppender por lo tanto, la BufferingForwardingAppender es como todo en la salida, incluyendo el nombre de usuario (%nombre de usuario)

    A continuación un interesante artículo en el blog que tiene una lista de las opciones en los diseños de patrón y parece que tiene varios de ellos marcados como lento.

    http://www.beefycode.com/post/Log4Net-Tutorial-pt-4-Layouts-and-Patterns.aspx

    • Hola y gracias por tu respuesta ! Pensé que ya e tratado de especificar el mismo diseño que tenía en mi RollingFileAppender dentro de la BufferingForwardingAppender. Por desgracia, no resuelve el problema. He encontrado la forma de solucionarlo, tuve que tomar un vistazo de cerca a log4net código fuente. De hecho, hay una propiedad en la BufferingForwardingAppender (o más bien la BufferingAppenderSkeleton) que debe ser configurado con un valor específico. Sin embargo esta propiedad no es absolutamente documentado (excepto en la documentación del SDK, pero no está claro). Responde a mi pregunta de pronto con todos los detalles

Dejar respuesta

Please enter your comment!
Please enter your name here