Translated using Weblate (Russian)
[oweals/minetest.git] / src / profiler.h
1 /*
2 Minetest
3 Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as published by
7 the Free Software Foundation; either version 2.1 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20 #ifndef PROFILER_HEADER
21 #define PROFILER_HEADER
22
23 #include "irrlichttypes.h"
24 #include <string>
25 #include <map>
26
27 #include "threading/mutex.h"
28 #include "threading/mutex_auto_lock.h"
29 #include "util/timetaker.h"
30 #include "util/numeric.h"      // paging()
31 #include "debug.h"             // assert()
32
33 #define MAX_PROFILER_TEXT_ROWS 20
34
35 // Global profiler
36 class Profiler;
37 extern Profiler *g_profiler;
38
39 /*
40         Time profiler
41 */
42
43 class Profiler
44 {
45 public:
46         Profiler()
47         {
48         }
49
50         void add(const std::string &name, float value)
51         {
52                 MutexAutoLock lock(m_mutex);
53                 {
54                         /* No average shall have been used; mark add used as -2 */
55                         std::map<std::string, int>::iterator n = m_avgcounts.find(name);
56                         if(n == m_avgcounts.end())
57                                 m_avgcounts[name] = -2;
58                         else{
59                                 if(n->second == -1)
60                                         n->second = -2;
61                                 assert(n->second == -2);
62                         }
63                 }
64                 {
65                         std::map<std::string, float>::iterator n = m_data.find(name);
66                         if(n == m_data.end())
67                                 m_data[name] = value;
68                         else
69                                 n->second += value;
70                 }
71         }
72
73         void avg(const std::string &name, float value)
74         {
75                 MutexAutoLock lock(m_mutex);
76                 int &count = m_avgcounts[name];
77
78                 assert(count != -2);
79                 count = MYMAX(count, 0) + 1;
80                 m_data[name] += value;
81         }
82
83         void clear()
84         {
85                 MutexAutoLock lock(m_mutex);
86                 for(std::map<std::string, float>::iterator
87                                 i = m_data.begin();
88                                 i != m_data.end(); ++i)
89                 {
90                         i->second = 0;
91                 }
92                 m_avgcounts.clear();
93         }
94
95         void print(std::ostream &o)
96         {
97                 printPage(o, 1, 1);
98         }
99
100         float getValue(const std::string &name) const
101         {
102                 std::map<std::string, float>::const_iterator numerator = m_data.find(name);
103                 if (numerator == m_data.end())
104                         return 0.f;
105
106                 std::map<std::string, int>::const_iterator denominator = m_avgcounts.find(name);
107                 if (denominator != m_avgcounts.end()){
108                         if (denominator->second >= 1)
109                                 return numerator->second / denominator->second;
110                 }
111
112                 return numerator->second;
113         }
114
115         void printPage(std::ostream &o, u32 page, u32 pagecount)
116         {
117                 MutexAutoLock lock(m_mutex);
118
119                 u32 minindex, maxindex;
120                 paging(m_data.size(), page, pagecount, minindex, maxindex);
121
122                 for (std::map<std::string, float>::const_iterator i = m_data.begin();
123                                 i != m_data.end(); ++i) {
124                         if (maxindex == 0)
125                                 break;
126                         maxindex--;
127
128                         if (minindex != 0) {
129                                 minindex--;
130                                 continue;
131                         }
132
133                         int avgcount = 1;
134                         std::map<std::string, int>::const_iterator n = m_avgcounts.find(i->first);
135                         if (n != m_avgcounts.end()) {
136                                 if(n->second >= 1)
137                                         avgcount = n->second;
138                         }
139                         o << "  " << i->first << ": ";
140                         s32 clampsize = 40;
141                         s32 space = clampsize - i->first.size();
142                         for(s32 j = 0; j < space; j++) {
143                                 if (j % 2 == 0 && j < space - 1)
144                                         o << "-";
145                                 else
146                                         o << " ";
147                         }
148                         o << (i->second / avgcount);
149                         o << std::endl;
150                 }
151         }
152
153         typedef std::map<std::string, float> GraphValues;
154
155         void graphAdd(const std::string &id, float value)
156         {
157                 MutexAutoLock lock(m_mutex);
158                 std::map<std::string, float>::iterator i =
159                                 m_graphvalues.find(id);
160                 if(i == m_graphvalues.end())
161                         m_graphvalues[id] = value;
162                 else
163                         i->second += value;
164         }
165         void graphGet(GraphValues &result)
166         {
167                 MutexAutoLock lock(m_mutex);
168                 result = m_graphvalues;
169                 m_graphvalues.clear();
170         }
171
172         void remove(const std::string& name)
173         {
174                 MutexAutoLock lock(m_mutex);
175                 m_avgcounts.erase(name);
176                 m_data.erase(name);
177         }
178
179 private:
180         Mutex m_mutex;
181         std::map<std::string, float> m_data;
182         std::map<std::string, int> m_avgcounts;
183         std::map<std::string, float> m_graphvalues;
184 };
185
186 enum ScopeProfilerType{
187         SPT_ADD,
188         SPT_AVG,
189         SPT_GRAPH_ADD
190 };
191
192 class ScopeProfiler
193 {
194 public:
195         ScopeProfiler(Profiler *profiler, const std::string &name,
196                         ScopeProfilerType type = SPT_ADD);
197         ~ScopeProfiler();
198 private:
199         Profiler *m_profiler;
200         std::string m_name;
201         TimeTaker *m_timer;
202         enum ScopeProfilerType m_type;
203 };
204
205 #endif
206