LCOV - code coverage report
Current view: top level - source/ps - Profile.h (source / functions) Hit Total Coverage
Test: 0 A.D. test coverage report Lines: 0 4 0.0 %
Date: 2023-01-19 00:18:29 Functions: 0 4 0.0 %

          Line data    Source code
       1             : /* Copyright (C) 2022 Wildfire Games.
       2             :  * This file is part of 0 A.D.
       3             :  *
       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.
       8             :  *
       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.
      13             :  *
      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/>.
      16             :  */
      17             : 
      18             : /*
      19             :  * GPG3-style hierarchical profiler
      20             :  */
      21             : 
      22             : #ifndef INCLUDED_PROFILE
      23             : #define INCLUDED_PROFILE
      24             : 
      25             : #include <vector>
      26             : 
      27             : #include "lib/adts/ring_buf.h"
      28             : #include "lib/posix/posix_pthread.h"
      29             : #include "ps/Profiler2.h"
      30             : #include "ps/Singleton.h"
      31             : 
      32             : 
      33             : #define PROFILE_AMORTIZE_FRAMES 30
      34             : #define PROFILE_AMORTIZE_TURNS 5
      35             : 
      36             : class CProfileManager;
      37             : class CProfileNodeTable;
      38             : 
      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.
      45             : //
      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.
      48             : 
      49             : class CProfileNode
      50             : {
      51             :     NONCOPYABLE(CProfileNode);
      52             : public:
      53             :     typedef std::vector<CProfileNode*>::iterator profile_iterator;
      54             :     typedef std::vector<CProfileNode*>::const_iterator const_profile_iterator;
      55             : 
      56             :     CProfileNode( const char* name, CProfileNode* parent );
      57             :     ~CProfileNode();
      58             : 
      59           0 :     const char* GetName() const { return name; }
      60             : 
      61             :     double GetFrameCalls() const;
      62             :     double GetFrameTime() const;
      63             :     double GetTurnCalls() const;
      64             :     double GetTurnTime() const;
      65             : 
      66             :     const CProfileNode* GetChild( const char* name ) const;
      67             :     const CProfileNode* GetScriptChild( const char* name ) const;
      68           0 :     const std::vector<CProfileNode*>* GetChildren() const { return( &children ); }
      69           0 :     const std::vector<CProfileNode*>* GetScriptChildren() const { return( &script_children ); }
      70             : 
      71             :     bool CanExpand();
      72             : 
      73             :     CProfileNode* GetChild( const char* name );
      74             :     CProfileNode* GetScriptChild( const char* name );
      75           0 :     CProfileNode* GetParent() const { return( parent ); }
      76             : 
      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();
      87             : 
      88             : private:
      89             :     friend class CProfileManager;
      90             :     friend class CProfileNodeTable;
      91             : 
      92             :     const char* name;
      93             : 
      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;
      98             : 
      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;
     103             : 
     104             :     double start;
     105             :     int recursion;
     106             : 
     107             :     CProfileNode* parent;
     108             :     std::vector<CProfileNode*> children;
     109             :     std::vector<CProfileNode*> script_children;
     110             :     CProfileNodeTable* display_table;
     111             : };
     112             : 
     113             : class CProfileManager : public Singleton<CProfileManager>
     114             : {
     115             : public:
     116             :     CProfileManager();
     117             :     ~CProfileManager();
     118             : 
     119             :     // Begins timing for a named subsection
     120             :     void Start( const char* name );
     121             :     void StartScript( const char* name );
     122             : 
     123             :     // Ends timing for the current subsection
     124             :     void Stop();
     125             : 
     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();
     135             : 
     136             :     inline const CProfileNode* GetCurrent() { return( current ); }
     137             :     inline const CProfileNode* GetRoot() { return( root ); }
     138             : 
     139             : private:
     140             :     CProfileNode* root;
     141             :     CProfileNode* current;
     142             : 
     143             :     bool needs_structural_reset;
     144             : 
     145             :     void PerformStructuralReset();
     146             : };
     147             : 
     148             : #define g_Profiler CProfileManager::GetSingleton()
     149             : 
     150             : class CProfileSample
     151             : {
     152             : public:
     153             :     CProfileSample(const char* name);
     154             :     ~CProfileSample();
     155             : };
     156             : 
     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) }
     163             : 
     164             : // Do both old and new profilers simultaneously (1+2=3), for convenience.
     165             : #define PROFILE3(name) PROFILE(name); PROFILE2(name)
     166             : 
     167             : // Also do GPU
     168             : #define PROFILE3_GPU(name) PROFILE(name); PROFILE2(name); PROFILE2_GPU(name)
     169             : 
     170             : #endif // INCLUDED_PROFILE

Generated by: LCOV version 1.13