Production tracing with Event Tracing for Windows (ETW)

Sign in to queue


An overview of ETW and the frameworks built around it, including WPP, manifests, Event Log, and the new TraceLogging framework.



Session Type:






The Discussion

  • User profile image
  • User profile image

    One thing I didn't have time to discuss in the presentation was how to optimize the use of EventSource.Write.

    The first thing EventSource.Write does is check to see whether there are any listeners for your event. If there are no listeners, it returns immediately. However, this is not optimal. The CPU had to prepare all of the parameters and make the call to EventSource.Write.

    If you are using EventSource.Write in a performance-sensitive region of code and want to ensure that it has minimal performance impact, you can avoid performing unnecessary work (avoid preparing the parameters for EventSource.Write) by using the IsEnabled() method as follows:

    if (MyLogger.IsEnabled())
            new EventSourceOptions { Level = EventLevel.Information },
                StringVal = stringData,
                CounterVal = counter

    This avoids the overhead of creating a string "EventName", creating a new EventSourceOptions object, creating a new object with the event data, and calling the Write method. These steps are only taken if somebody is listening to events from the MyLogger provider. This can be a significant improvement, especially if collecting the data is expensive.

    To optimize further, you can use IsEnabled(level, keyword). The value of level and keyword should match the values provided in the EventSourceOptions parameter.

    The event used in the example used an anonymous type to provide the values for the event. Anonymous types make it very easy to provide the values for the event, but since anonymous types are classes, each event that uses the anonymous type will generate some garbage. If this garbage is a concern for your application, you can create a struct that contains your event's values. The struct must have an EventData attribute, and must have public gettable properties for each value to be included in your event. This is less convenient than using an anonymous type, but it can improve performance and reduce garbage for performance-critical code. (The implementation of EventSource.Write tries very hard to avoid generating garbage on each invocation, and will only generate garbage if you pass a complex value such as an array.)

    Note that the above optimizations are unnecessary when using the C/C++ TraceLoggingProvider.h APIs because the TraceLoggingWrite macro always generates a corresponding IF block to prevent parameter evaluation if nobody is listening to the event.

Add Your 2 Cents