//------------------------------------------------------------------------------ // File: Measure.h // // Desc: DirectShow base classes. // // Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved. //------------------------------------------------------------------------------ /* The idea is to pepper the source code with interesting measurements and have the last few thousand of these recorded in a circular buffer that can be post-processed to give interesting numbers. WHAT THE LOG LOOKS LIKE: Time (sec) Type Delta Incident_Name 0.055,41 NOTE -. Incident Nine - Another note 0.055,42 NOTE 0.000,01 Incident Nine - Another note 0.055,44 NOTE 0.000,02 Incident Nine - Another note 0.055,45 STOP -. Incident Eight - Also random 0.055,47 START -. Incident Seven - Random 0.055,49 NOTE 0.000,05 Incident Nine - Another note ------- ---------------- 0.125,60 STOP 0.000,03 Msr_Stop 0.125,62 START -. Msr_Start 0.125,63 START -. Incident Two - Start/Stop 0.125,65 STOP 0.000,03 Msr_Start 0.125,66 START -. Msr_Stop 0.125,68 STOP 0.000,05 Incident Two - Start/Stop 0.125,70 STOP 0.000,04 Msr_Stop 0.125,72 START -. Msr_Start 0.125,73 START -. Incident Two - Start/Stop 0.125,75 STOP 0.000,03 Msr_Start 0.125,77 START -. Msr_Stop 0.125,78 STOP 0.000,05 Incident Two - Start/Stop 0.125,80 STOP 0.000,03 Msr_Stop 0.125,81 NOTE -. Incident Three - single Note 0.125,83 START -. Incident Four - Start, no stop 0.125,85 START -. Incident Five - Single Start/Stop 0.125,87 STOP 0.000,02 Incident Five - Single Start/Stop Number Average StdDev Smallest Largest Incident_Name 10 0.000,58 0.000,10 0.000,55 0.000,85 Incident One - Note 50 0.000,05 0.000,00 0.000,05 0.000,05 Incident Two - Start/Stop 1 -. -. -. -. Incident Three - single Note 0 -. -. -. -. Incident Four - Start, no stop 1 0.000,02 -. 0.000,02 0.000,02 Incident Five - Single Start/Stop 0 -. -. -. -. Incident Six - zero occurrences 100 0.000,25 0.000,12 0.000,02 0.000,62 Incident Seven - Random 100 0.000,79 0.000,48 0.000,02 0.001,92 Incident Eight - Also random 5895 0.000,01 0.000,01 0.000,01 0.000,56 Incident Nine - Another note 10 0.000,03 0.000,00 0.000,03 0.000,04 Msr_Note 50 0.000,03 0.000,00 0.000,03 0.000,04 Msr_Start 50 0.000,04 0.000,03 0.000,03 0.000,31 Msr_Stop WHAT IT MEANS: The log shows what happened and when. Each line shows the time at which something happened (see WHAT YOU CODE below) what it was that happened and (if approporate) the time since the corresponding previous event (that's the delta column). The statistics show how many times each event occurred, what the average delta time was, also the standard deviation, largest and smalles delta. WHAT YOU CODE: Before anything else executes: - register your ids int id1 = Msr_Register("Incident One - Note"); int id2 = Msr_Register("Incident Two - Start/Stop"); int id3 = Msr_Register("Incident Three - single Note"); etc. At interesting moments: // To measure a repetitive event - e.g. end of bitblt to screen Msr_Note(Id9); // e.g. "video frame hiting the screen NOW!" or // To measure an elapsed time e.g. time taken to decode an MPEG B-frame Msr_Start(Id2); // e.g. "Starting to decode MPEG B-frame" . . . MsrStop(Id2); // "Finished MPEG decode" At the end: HANDLE hFile; hFile = CreateFile("Perf.log", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL); Msr_Dump(hFile); // This writes the log out to the file CloseHandle(hFile); or Msr_Dump(NULL); // This writes it to DbgLog((LOG_TRACE,0, ... )); // but if you are writing it out to the debugger // then the times are probably all garbage because // the debugger can make things run awfully slow. A given id should be used either for start / stop or Note calls. If Notes are mixed in with Starts and Stops their statistics will be gibberish. If you code the calls in upper case i.e. MSR_START(idMunge); then you get macros which will turn into nothing unless PERF is defined. You can reset the statistical counts for a given id by calling Reset(Id). They are reset by default at the start. It logs Reset as a special incident, so you can see it in the log. The log is a circular buffer in storage (to try to minimise disk I/O). It overwrites the oldest entries once full. The statistics include ALL incidents since the last Reset, whether still visible in the log or not. */ #ifndef __MEASURE__ #define __MEASURE__ #ifdef PERF #define MSR_INIT() Msr_Init() #define MSR_TERMINATE() Msr_Terminate() #define MSR_REGISTER(a) Msr_Register(a) #define MSR_RESET(a) Msr_Reset(a) #define MSR_CONTROL(a) Msr_Control(a) #define MSR_START(a) Msr_Start(a) #define MSR_STOP(a) Msr_Stop(a) #define MSR_NOTE(a) Msr_Note(a) #define MSR_INTEGER(a,b) Msr_Integer(a,b) #define MSR_DUMP(a) Msr_Dump(a) #define MSR_DUMPSTATS(a) Msr_DumpStats(a) #else #define MSR_INIT() ((void)0) #define MSR_TERMINATE() ((void)0) #define MSR_REGISTER(a) 0 #define MSR_RESET(a) ((void)0) #define MSR_CONTROL(a) ((void)0) #define MSR_START(a) ((void)0) #define MSR_STOP(a) ((void)0) #define MSR_NOTE(a) ((void)0) #define MSR_INTEGER(a,b) ((void)0) #define MSR_DUMP(a) ((void)0) #define MSR_DUMPSTATS(a) ((void)0) #endif #ifdef __cplusplus extern "C" { #endif // This must be called first - (called by the DllEntry) void WINAPI Msr_Init(void); // Call this last to clean up (or just let it fall off the end - who cares?) void WINAPI Msr_Terminate(void); // Call this to get an Id for an "incident" that you can pass to Start, Stop or Note // everything that's logged is called an "incident". int WINAPI Msr_Register(LPTSTR Incident); // Reset the statistical counts for an incident void WINAPI Msr_Reset(int Id); // Reset all the counts for all incidents #define MSR_RESET_ALL 0 #define MSR_PAUSE 1 #define MSR_RUN 2 void WINAPI Msr_Control(int iAction); // log the start of an operation void WINAPI Msr_Start(int Id); // log the end of an operation void WINAPI Msr_Stop(int Id); // log a one-off or repetitive operation void WINAPI Msr_Note(int Id); // log an integer (on which we can see statistics later) void WINAPI Msr_Integer(int Id, int n); // print out all the vaialable log (it may have wrapped) and then the statistics. // When the log wraps you lose log but the statistics are still complete. // hFIle==NULL => use DbgLog // otherwise hFile must have come from CreateFile or OpenFile. void WINAPI Msr_Dump(HANDLE hFile); // just dump the statistics - never mind the log void WINAPI Msr_DumpStats(HANDLE hFile); // Type definitions in case you want to declare a pointer to the dump functions // (makes it a trifle easier to do dynamic linking // i.e. LoadModule, GetProcAddress and call that) // Typedefs so can declare MSR_DUMPPROC *MsrDumpStats; or whatever typedef void WINAPI MSR_DUMPPROC(HANDLE hFile); typedef void WINAPI MSR_CONTROLPROC(int iAction); #ifdef __cplusplus } #endif #endif // __MEASURE__