Civ backgrounds for minimap
[0ad.git] / source / ps / Profile.h
blob40ca66883b12e18ef1fc8e365a1dacd7244b84f8
1 /* Copyright (C) 2022 Wildfire Games.
2 * This file is part of 0 A.D.
4 * 0 A.D. is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 2 of the License, or
7 * (at your option) any later version.
9 * 0 A.D. is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with 0 A.D. If not, see <http://www.gnu.org/licenses/>.
19 * GPG3-style hierarchical profiler
22 #ifndef INCLUDED_PROFILE
23 #define INCLUDED_PROFILE
25 #include <vector>
27 #include "lib/adts/ring_buf.h"
28 #include "lib/posix/posix_pthread.h"
29 #include "ps/Profiler2.h"
30 #include "ps/Singleton.h"
33 #define PROFILE_AMORTIZE_FRAMES 30
34 #define PROFILE_AMORTIZE_TURNS 5
36 class CProfileManager;
37 class CProfileNodeTable;
39 // To profile scripts usefully, we use a call hook that's called on every enter/exit,
40 // and need to find the function name. But most functions are anonymous so we make do
41 // with filename plus line number instead.
42 // Computing the names is fairly expensive, and we need to return an interned char*
43 // for the profiler to hold a copy of, so we use boost::flyweight to construct interned
44 // strings per call location.
46 // TODO: Check again how much the overhead for getting filename and line really is and if
47 // it has increased with the new approach after the SpiderMonkey 31 upgrade.
49 class CProfileNode
51 NONCOPYABLE(CProfileNode);
52 public:
53 typedef std::vector<CProfileNode*>::iterator profile_iterator;
54 typedef std::vector<CProfileNode*>::const_iterator const_profile_iterator;
56 CProfileNode( const char* name, CProfileNode* parent );
57 ~CProfileNode();
59 const char* GetName() const { return name; }
61 double GetFrameCalls() const;
62 double GetFrameTime() const;
63 double GetTurnCalls() const;
64 double GetTurnTime() const;
66 const CProfileNode* GetChild( const char* name ) const;
67 const CProfileNode* GetScriptChild( const char* name ) const;
68 const std::vector<CProfileNode*>* GetChildren() const { return( &children ); }
69 const std::vector<CProfileNode*>* GetScriptChildren() const { return( &script_children ); }
71 bool CanExpand();
73 CProfileNode* GetChild( const char* name );
74 CProfileNode* GetScriptChild( const char* name );
75 CProfileNode* GetParent() const { return( parent ); }
77 // Resets timing information for this node and all its children
78 void Reset();
79 // Resets frame timings for this node and all its children
80 void Frame();
81 // Resets turn timings for this node and all its children
82 void Turn();
83 // Enters the node
84 void Call();
85 // Leaves the node. Returns true if the node has actually been left
86 bool Return();
88 private:
89 friend class CProfileManager;
90 friend class CProfileNodeTable;
92 const char* name;
94 int calls_frame_current;
95 int calls_turn_current;
96 RingBuf<int, PROFILE_AMORTIZE_FRAMES> calls_per_frame;
97 RingBuf<int, PROFILE_AMORTIZE_TURNS> calls_per_turn;
99 double time_frame_current;
100 double time_turn_current;
101 RingBuf<double, PROFILE_AMORTIZE_FRAMES> time_per_frame;
102 RingBuf<double, PROFILE_AMORTIZE_TURNS> time_per_turn;
104 double start;
105 int recursion;
107 CProfileNode* parent;
108 std::vector<CProfileNode*> children;
109 std::vector<CProfileNode*> script_children;
110 CProfileNodeTable* display_table;
113 class CProfileManager : public Singleton<CProfileManager>
115 public:
116 CProfileManager();
117 ~CProfileManager();
119 // Begins timing for a named subsection
120 void Start( const char* name );
121 void StartScript( const char* name );
123 // Ends timing for the current subsection
124 void Stop();
126 // Resets all timing information
127 void Reset();
128 // Resets frame timing information
129 void Frame();
130 // Resets turn timing information
131 // (Must not be called before Frame)
132 void Turn();
133 // Resets absolutely everything, at the end of this frame
134 void StructuralReset();
136 inline const CProfileNode* GetCurrent() { return( current ); }
137 inline const CProfileNode* GetRoot() { return( root ); }
139 private:
140 CProfileNode* root;
141 CProfileNode* current;
143 bool needs_structural_reset;
145 void PerformStructuralReset();
148 #define g_Profiler CProfileManager::GetSingleton()
150 class CProfileSample
152 public:
153 CProfileSample(const char* name);
154 ~CProfileSample();
157 // Put a PROFILE("xyz") block at the start of all code to be profiled.
158 // Profile blocks last until the end of the containing scope.
159 #define PROFILE(name) CProfileSample __profile(name)
160 // Cheat a bit to make things slightly easier on the user
161 #define PROFILE_START(name) { CProfileSample __profile(name)
162 #define PROFILE_END(name) }
164 // Do both old and new profilers simultaneously (1+2=3), for convenience.
165 #define PROFILE3(name) PROFILE(name); PROFILE2(name)
167 // Also do GPU
168 #define PROFILE3_GPU(name) PROFILE(name); PROFILE2(name); PROFILE2_GPU(name)
170 #endif // INCLUDED_PROFILE