michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: /* Visual event tracer, creates a log of events on each thread for visualization */ michael@0: michael@0: /** michael@0: * The event tracer code is by default disabled in both build and run time. michael@0: * michael@0: * To enable this code at build time, add --enable-visual-profiling to your michael@0: * configure options. michael@0: * michael@0: * To enable this code at run time, export MOZ_TRACE_FILE env var with a michael@0: * path to the file to write the log to. This is all you need to * produce michael@0: * the log of all events instrumentation in the mozilla code. Check michael@0: * MOZ_EVENT_TRACER_* macros below to add your own. michael@0: * michael@0: * To let the event tracer log only some events to save disk space, export michael@0: * MOZ_PROFILING_EVENTS with comma separated list of event names you want michael@0: * to record in the log. michael@0: */ michael@0: michael@0: #ifndef VisualEventTracer_h___ michael@0: #define VisualEventTracer_h___ michael@0: michael@0: #include michael@0: #include "mozilla/Attributes.h" michael@0: #include "mozilla/GuardObjects.h" michael@0: michael@0: #ifdef MOZ_VISUAL_EVENT_TRACER michael@0: #include "nsIVisualEventTracer.h" michael@0: michael@0: // Bind an object instance, usually |this|, to a name, usually URL or michael@0: // host name, the instance deals with for its lifetime. The name string michael@0: // is duplicated. michael@0: // IMPORTANT: it is up to the caller to pass the correct static_cast michael@0: // of the |instance| pointer to all these macros ; otherwise the linking michael@0: // of events and objects will not work! michael@0: // The name will show in details of the events on the timeline and also michael@0: // will allow events filtering by host names, URLs etc. michael@0: #define MOZ_EVENT_TRACER_NAME_OBJECT(instance, name) \ michael@0: mozilla::eventtracer::Mark(mozilla::eventtracer::eName, instance, name) michael@0: michael@0: // The same as MOZ_EVENT_TRACER_NAME_OBJECT, just simplifies building michael@0: // names when it consists of two parts michael@0: #define MOZ_EVENT_TRACER_COMPOUND_NAME(instance, name, name2) \ michael@0: mozilla::eventtracer::Mark(mozilla::eventtracer::eName, instance, name, name2) michael@0: michael@0: michael@0: // Call the followings with the same |instance| reference as you have michael@0: // previously called MOZ_EVENT_TRACER_NAME_OBJECT. michael@0: // Let |name| be the name of the event happening, like "resolving", michael@0: // "connecting", "loading" etc. michael@0: michael@0: // This will crate a single-point-in-time event marked with an arrow michael@0: // on the timeline, this is a way to indicate an event without a duration. michael@0: #define MOZ_EVENT_TRACER_MARK(instance, name) \ michael@0: mozilla::eventtracer::Mark(mozilla::eventtracer::eShot, instance, name) michael@0: michael@0: // Following macros are used to log events with duration. michael@0: // There always has to be complete WAIT,EXEC,DONE or EXEC,DONE michael@0: // uninterrupted and non-interferring tuple(s) for an event to be correctly michael@0: // shown on the timeline. Each can be called on any thread, the event tape is michael@0: // finally displayed on the thread where it has been EXECuted. michael@0: michael@0: // Example of 3 phases usage for "HTTP request channel": michael@0: // WAIT: we've just created the channel and called AsyncOpen on it michael@0: // EXEC: we've just got first call to OnDataAvailable, so we are actually michael@0: // receiving the content after some time like connection establising, michael@0: // opening a cache entry, sending the GET request... michael@0: // DONE: we've just got OnStopRequest call that indicates the content michael@0: // has been completely delivered and the request is now finished michael@0: michael@0: // Indicate an event pending start, on the timeline this will michael@0: // start the event's interval tape with a pale color, the time will michael@0: // show in details. Usually used when an event is being posted or michael@0: // we wait for a lock acquisition. michael@0: // WAITING is not mandatory, some events don't have a pending phase. michael@0: #define MOZ_EVENT_TRACER_WAIT(instance, name) \ michael@0: mozilla::eventtracer::Mark(mozilla::eventtracer::eWait, instance, name) michael@0: michael@0: // Indicate start of an event actual execution, on the timeline this will michael@0: // change the event's tape to a deeper color, the time will show in details. michael@0: #define MOZ_EVENT_TRACER_EXEC(instance, name) \ michael@0: mozilla::eventtracer::Mark(mozilla::eventtracer::eExec, instance, name) michael@0: michael@0: // Indicate the end of an event execution (the event has been done), michael@0: // on the timeline this will end the event's tape and show the time in michael@0: // event details. michael@0: // NOTE: when the event duration is extremely short, like 1ms, it will convert michael@0: // to an event w/o a duration - the same as MOZ_EVENT_TRACER_MARK would be used. michael@0: #define MOZ_EVENT_TRACER_DONE(instance, name) \ michael@0: mozilla::eventtracer::Mark(mozilla::eventtracer::eDone, instance, name) michael@0: michael@0: // The same meaning as the above macros, just for concurent events. michael@0: // Concurent event means it can happen for the same instance on more michael@0: // then just a single thread, e.g. a service method call, a global lock michael@0: // acquisition, enter and release. michael@0: #define MOZ_EVENT_TRACER_WAIT_THREADSAFE(instance, name) \ michael@0: mozilla::eventtracer::Mark(mozilla::eventtracer::eWait | mozilla::eventtracer::eThreadConcurrent, instance, name) michael@0: #define MOZ_EVENT_TRACER_EXEC_THREADSAFE(instance, name) \ michael@0: mozilla::eventtracer::Mark(mozilla::eventtracer::eExec | mozilla::eventtracer::eThreadConcurrent, instance, name) michael@0: #define MOZ_EVENT_TRACER_DONE_THREASAFE(instance, name) \ michael@0: mozilla::eventtracer::Mark(mozilla::eventtracer::eDone | mozilla::eventtracer::eThreadConcurrent, instance, name) michael@0: michael@0: #else michael@0: michael@0: // MOZ_VISUAL_EVENT_TRACER disabled michael@0: michael@0: #define MOZ_EVENT_TRACER_NAME_OBJECT(instance, name) (void)0 michael@0: #define MOZ_EVENT_TRACER_COMPOUND_NAME(instance, name, name2) (void)0 michael@0: #define MOZ_EVENT_TRACER_MARK(instance, name) (void)0 michael@0: #define MOZ_EVENT_TRACER_WAIT(instance, name) (void)0 michael@0: #define MOZ_EVENT_TRACER_EXEC(instance, name) (void)0 michael@0: #define MOZ_EVENT_TRACER_DONE(instance, name) (void)0 michael@0: #define MOZ_EVENT_TRACER_WAIT_THREADSAFE(instance, name) (void)0 michael@0: #define MOZ_EVENT_TRACER_EXEC_THREADSAFE(instance, name) (void)0 michael@0: #define MOZ_EVENT_TRACER_DONE_THREASAFE(instance, name) (void)0 michael@0: michael@0: #endif michael@0: michael@0: michael@0: namespace mozilla { michael@0: namespace eventtracer { michael@0: michael@0: // Initialize the event tracer engine, called automatically on XPCOM startup. michael@0: void Init(); michael@0: michael@0: // Shuts the event tracer engine down and closes the log file, called michael@0: // automatically during XPCOM shutdown. michael@0: void Shutdown(); michael@0: michael@0: enum MarkType { michael@0: eNone, // No operation, ignored michael@0: eName, // This is used to bind an object instance with a name michael@0: michael@0: eShot, // An event with no duration michael@0: eWait, // Start of waiting for execution (lock acquire, post...) michael@0: eExec, // Start of the execution it self michael@0: eDone, // End of the execution michael@0: eLast, // Sentinel michael@0: michael@0: // Flags michael@0: michael@0: // The same object can execute the same event on several threads concurently michael@0: eThreadConcurrent = 0x10000 michael@0: }; michael@0: michael@0: // Records an event on the calling thread. michael@0: // @param aType michael@0: // One of MarkType fields, can be bitwise or'ed with the flags. michael@0: // @param aItem michael@0: // Reference to the object we want to bind a name to or the event is michael@0: // happening on. Can be actually anything, but valid poitners should michael@0: // be used. michael@0: // @param aText michael@0: // Text of the name (for eName) or event's name for others. The string michael@0: // is duplicated. michael@0: // @param aText2 michael@0: // Optional second part of the instnace name, or event name. michael@0: // Event filtering does apply only to the first part (aText). michael@0: void Mark(uint32_t aType, void * aItem, michael@0: const char * aText, const char * aText2 = 0); michael@0: michael@0: michael@0: // Helper guard object. Use to mark an event in the constructor and a different michael@0: // event in the destructor. michael@0: // michael@0: // Example: michael@0: // int class::func() michael@0: // { michael@0: // AutoEventTracer tracer(this, eventtracer::eExec, eventtracer::eDone, "func"); michael@0: // michael@0: // do_something_taking_a_long_time(); michael@0: // } michael@0: class MOZ_STACK_CLASS AutoEventTracer michael@0: { michael@0: public: michael@0: AutoEventTracer(void * aInstance, michael@0: uint32_t aTypeOn, // MarkType marked in constructor michael@0: uint32_t aTypeOff, // MarkType marked in destructor michael@0: const char * aName, michael@0: const char * aName2 = 0 michael@0: MOZ_GUARD_OBJECT_NOTIFIER_PARAM) michael@0: : mInstance(aInstance) michael@0: , mName(aName) michael@0: , mName2(aName2) michael@0: , mTypeOn(aTypeOn) michael@0: , mTypeOff(aTypeOff) michael@0: { michael@0: MOZ_GUARD_OBJECT_NOTIFIER_INIT; michael@0: michael@0: ::mozilla::eventtracer::Mark(mTypeOn, mInstance, mName, mName2); michael@0: } michael@0: michael@0: ~AutoEventTracer() michael@0: { michael@0: ::mozilla::eventtracer::Mark(mTypeOff, mInstance, mName, mName2); michael@0: } michael@0: michael@0: private: michael@0: void * mInstance; michael@0: const char * mName; michael@0: const char * mName2; michael@0: uint32_t mTypeOn; michael@0: uint32_t mTypeOff; michael@0: michael@0: MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER michael@0: }; michael@0: michael@0: #ifdef MOZ_VISUAL_EVENT_TRACER michael@0: michael@0: // The scriptable class that drives the event tracer michael@0: michael@0: class VisualEventTracer : public nsIVisualEventTracer michael@0: { michael@0: NS_DECL_ISUPPORTS michael@0: NS_DECL_NSIVISUALEVENTTRACER michael@0: }; michael@0: michael@0: #define NS_VISUALEVENTTRACER_CID \ michael@0: { 0xb9e5e102, 0xc2f4, 0x497a, \ michael@0: { 0xa6, 0xe4, 0x54, 0xde, 0xf3, 0x71, 0xf3, 0x9d } } michael@0: #define NS_VISUALEVENTTRACER_CONTRACTID "@mozilla.org/base/visual-event-tracer;1" michael@0: #define NS_VISUALEVENTTRACER_CLASSNAME "Visual Event Tracer" michael@0: michael@0: #endif michael@0: michael@0: } // eventtracer michael@0: } // mozilla michael@0: michael@0: #endif /* VisualEventTracer_h___ */