5 * Created by damian on 25/5/08.
6 * Copyright 2008 frey damian@frey.co.nz. All rights reserved.
16 A thread-safe profiler. On call to Display(), displays result by thread.
18 To use, #include "FProfiler.h", and globally #define PROFILE. Then, use
19 the following macros to profile parts of code:
21 * PROFILE_SECTION_PUSH( label ) and PROFILE_SECTION_POP()
23 Profile code between these calls, storing results in a tree.
26 .. unprofiled preprocessing
27 PROFILE_SECTION_PUSH( "partial section" );
28 .. code to be profiled
29 PROFILE_SECTION_POP();
30 .. unprofiled postprocessing
34 PROFILE_SECTION_PUSH( "two-step process" );
36 PROFILE_SECTION_PUSH( "step 1" );
38 PROFILE_SECTION_POP();
39 PROFILE_SECTION_PUSH( "step 2" );
41 PROFILE_SECTION_POP();
42 PROFILE_SECTION_POP();
45 - two-step process <total time for steps 1 + 2 + preprocessing> ...
46 - - step 1 <time for step 1> ...
47 - - step 2 <time for step 2> ...
49 NOTE: all labels at a given level in the tree must be unique.
51 * PROFILE_THIS_FUNCTION()
53 Wraps the current function in a pair of
54 PROFILE_SECTION_PUSH( function_name ) and PROFILE_SECTION_POP calls.
56 * PROFILE_THIS_BLOCK( label )
58 Wraps the current block (the code between the current level { and })
59 in a pair of PROFILE_SECTION_PUSH( label ) and PROFILE_SECTION_POP
66 PROFILE_THIS_BLOCK( "test passed" );
67 // code to run on test condition
71 To display profile results, call FProfiler::Display();
80 #define PROFILE_SECTION_PUSH( label ) FProfiler::SectionPush( label );
81 #define PROFILE_SECTION_POP() FProfiler::SectionPop();
82 #define PROFILE_THIS_FUNCTION() volatile FFunctionProfiler __function_profiler_object__( __FUNCTION__ );
83 #define PROFILE_THIS_BLOCK( label ) volatile FFunctionProfiler __section_profiler_object__##__LINE__( label );
84 #warning Profiling with FProfiler enabled
86 #define PROFILE_SECTION_PUSH( label ) ;
87 #define PROFILE_SECTION_POP() ;
88 #define PROFILE_THIS_FUNCTION() ;
89 #define PROFILE_THIS_BLOCK( label );
90 //#warning Profiling with FProfiler disabled
94 #include "FSemaphore.h"
102 class FProfileSection
;
104 class FProfileContext
107 FThreadContext thread_context
;
108 FProfileSection
* toplevel
;
109 FProfileSection
* current
;
111 FProfileContext() { toplevel
= NULL
; }
119 /// clear the database and restart profiling
123 static void SectionPush( const std::string
& name
= "unlabelled section" );
125 static void SectionPop();
127 /// return a pointer to the context for the current thread
128 static FProfileContext
* GetContext();
130 /// show profiles recorded. SORT_BY defines sort order.
131 typedef enum _SORT_BY
{ SORT_EXECUTION
, SORT_TIME
} SORT_BY
;
132 static void Display( SORT_BY sort
= SORT_TIME
);
136 // for efficiency: avoid re-allocating
137 static FTime end_time
;
140 typedef std::vector
<FProfileContext
*> FProfileContexts
;
141 static FProfileContexts contexts
;
143 static FSemaphore lock
;
147 class FProfileSection
{
152 void Display( const std::string
& prefix
, FProfiler::SORT_BY sort_by
);
157 static int EXEC_ORDER_ID
;
160 // LARGE_INTEGER start_time;
162 FProfileSection
* parent
;
166 typedef std::map
<const std::string
, FProfileSection
* > FProfileSections
;
168 // don't try this at home
169 /*struct less_than_comparator : public std::binary_function<const ProfileSection*,const ProfileSection*,bool>
171 result_type operator() ( first_argument_type a, second_argument_type b )
173 return ( a->avg_time * a->call_count < b->avg_time*b->call_count );
176 FProfileSections children
;
184 /** FFunctionProfiler
186 convenience class. designed to be used as a volatile instance, within a function/block.
190 class FFunctionProfiler
193 FFunctionProfiler( const char* function_name
)
194 { FProfiler::SectionPush(function_name
); }
196 { FProfiler::SectionPop(); }