Panda3D
pStatProperties.cxx
Go to the documentation of this file.
1 /**
2  * PANDA 3D SOFTWARE
3  * Copyright (c) Carnegie Mellon University. All rights reserved.
4  *
5  * All use of this software is subject to the terms of the revised BSD
6  * license. You should have received a copy of this license along
7  * with this source code in a file named "LICENSE."
8  *
9  * @file pStatProperties.cxx
10  * @author drose
11  * @date 2001-05-17
12  */
13 
14 #include "pStatProperties.h"
15 #include "pStatCollectorDef.h"
16 #include "pStatClient.h"
17 #include "config_pstatclient.h"
18 #include "configVariableBool.h"
19 #include "configVariableColor.h"
20 #include "configVariableDouble.h"
21 #include "configVariableInt.h"
22 #include "configVariableString.h"
23 
24 #include <ctype.h>
25 
26 using std::string;
27 
28 static const int current_pstat_major_version = 3;
29 static const int current_pstat_minor_version = 0;
30 // Initialized at 2.0 on 51801, when version numbers were first added.
31 // Incremented to 2.1 on 52101 to add support for TCP frame data. Incremented
32 // to 3.0 on 42805 to bump TCP headers to 32 bits.
33 
34 /**
35  * Returns the current major version number of the PStats protocol. This is
36  * the version number that will be reported by clients running this code, and
37  * that will be expected by servers running this code.
38  *
39  * The major version numbers must match exactly in order for a communication
40  * to be successful.
41  */
42 int
44  return current_pstat_major_version;
45 }
46 
47 /**
48  * Returns the current minor version number of the PStats protocol. This is
49  * the version number that will be reported by clients running this code, and
50  * that will be expected by servers running this code.
51  *
52  * The minor version numbers need not match exactly, but the server must be >=
53  * the client.
54  */
55 int
57  return current_pstat_minor_version;
58 }
59 
60 
61 #ifdef DO_PSTATS
62 
63 /*
64  * The rest of this file defines the predefined properties (color, sort, etc.)
65  * for the various PStatCollectors that may be defined within Panda or even
66  * elsewhere. It is a little strange to defined these properties here instead
67  * of where the collectors are actually declared, but it's handy to have them
68  * all in one place, so we can easily see which colors are available, etc. It
69  * also makes the declarations a lot simpler, since there are quite a few
70  * esoteric parameters to specify. We could define these in some external
71  * data file that is read in at runtime, so that you could extend this list
72  * without having to relink panda, but then there are the usual problems with
73  * ensuring that the file is available to you at runtime. The heck with it.
74  * At least, no other file depends on this file, so it may be modified without
75  * forcing anything else to be recompiled.
76  */
77 
78 typedef PStatCollectorDef::ColorDef ColorDef;
79 
80 struct TimeCollectorProperties {
81  bool is_active;
82  const char *name;
83  ColorDef color;
84  double suggested_scale;
85 };
86 
87 struct LevelCollectorProperties {
88  bool is_active;
89  const char *name;
90  ColorDef color;
91  const char *units;
92  double suggested_scale;
93  double inv_factor;
94 };
95 
96 static TimeCollectorProperties time_properties[] = {
97  { 1, "Frame", { 0.95, 1.0, 0.35 } },
98  { 1, "Wait", { 0.6, 0.6, 0.6 } },
99  { 0, "Wait:Mutex block", { 0.5, 0.0, 1.0 } },
100  { 1, "Wait:Thread sync", { 0.0, 1.0, 0.5 } },
101  { 1, "Wait:Clock Wait", { 0.2, 0.8, 0.2 } },
102  { 1, "Wait:Clock Wait:Sleep", { 0.9, 0.4, 0.8 } },
103  { 1, "Wait:Clock Wait:Spin", { 0.2, 0.8, 1.0 } },
104  { 1, "Wait:Flip", { 1.0, 0.6, 0.3 } },
105  { 1, "Wait:Flip:Begin", { 0.3, 0.3, 0.9 } },
106  { 1, "Wait:Flip:End", { 0.9, 0.3, 0.6 } },
107  { 1, "App", { 0.0, 0.4, 0.8 }, 1.0 / 30.0 },
108  { 1, "App:Collisions", { 1.0, 0.5, 0.0 } },
109  { 1, "App:Collisions:Reset", { 0.0, 0.0, 0.5 } },
110  { 0, "App:Data graph", { 0.5, 0.8, 0.4 } },
111  { 1, "App:Show code", { 0.8, 0.2, 1.0 } },
112  { 0, "App:Show code:Nametags", { 0.8, 0.8, 1.0 } },
113  { 0, "App:Show code:Nametags:2d", { 0.0, 0.0, 0.5 } },
114  { 0, "App:Show code:Nametags:2d:Contents", { 0.0, 0.5, 0.0 } },
115  { 0, "App:Show code:Nametags:2d:Adjust", { 0.5, 0.0, 0.5 } },
116  { 0, "App:Show code:Nametags:3d", { 1.0, 0.0, 0.0 } },
117  { 0, "App:Show code:Nametags:3d:Contents", { 0.0, 0.5, 0.0 } },
118  { 0, "App:Show code:Nametags:3d:Adjust", { 0.5, 0.0, 0.5 } },
119  { 1, "Cull", { 0.21, 0.68, 0.37 }, 1.0 / 30.0 },
120  { 1, "Cull:Setup", { 0.7, 0.4, 0.5 } },
121  { 1, "Cull:Sort", { 0.3, 0.3, 0.6 } },
122  { 1, "*", { 0.1, 0.1, 0.5 } },
123  { 1, "*:Show fps", { 0.5, 0.8, 1.0 } },
124  { 1, "*:Munge", { 0.3, 0.3, 0.9 } },
125  { 1, "*:Munge:Geom", { 0.4, 0.2, 0.8 } },
126  { 1, "*:Munge:Sprites", { 0.2, 0.8, 0.4 } },
127  { 0, "*:Munge:Data", { 0.7, 0.5, 0.2 } },
128  { 0, "*:Munge:Rotate", { 0.9, 0.8, 0.5 } },
129  { 0, "*:Munge:Decompose", { 0.1, 0.3, 0.1 } },
130  { 1, "*:PStats", { 0.4, 0.8, 1.0 } },
131  { 1, "*:Animation", { 1.0, 0.0, 1.0 } },
132  { 0, "*:Flatten", { 0.0, 0.7, 0.4 } },
133  { 0, "*:State Cache", { 0.4, 0.7, 0.7 } },
134  { 0, "*:NodePath", { 0.1, 0.6, 0.8 } },
135  { 1, "Draw", { 0.83, 0.02, 0.01 }, 1.0 / 30.0 },
136  { 1, "Draw:Make current", { 0.4, 0.2, 0.6 } },
137  { 1, "Draw:Copy texture", { 0.2, 0.6, 0.4 } },
138  { 1, "Draw:Transfer data", { 0.8, 0.0, 0.6 } },
139  { 1, "Draw:Transfer data:Vertex buffer", { 0.0, 0.1, 0.9 } },
140  { 1, "Draw:Transfer data:Index buffer", { 0.1, 0.9, 0.0 } },
141  { 1, "Draw:Transfer data:Texture", { 0.9, 0.0, 0.1 } },
142  { 1, "Draw:Transfer data:Display lists", { 0.5, 0.0, 0.9 } },
143  { 1, "Draw:Clear", { 0.0, 0.8, 0.6 } },
144  { 1, "Draw:Flush", { 0.9, 0.2, 0.7 } },
145  { 1, "Draw:Sync", { 0.5, 0.7, 0.7 } },
146  { 0, "Draw:Transform", { 0.0, 0.5, 0.0 } },
147  { 1, "Draw:Primitive", { 0.0, 0.0, 0.5 } },
148  { 1, "Draw:Set State", { 0.2, 0.6, 0.8 } },
149  { 1, "Draw:Wait occlusion", { 1.0, 0.5, 0.0 } },
150  { 1, "Draw:Bind FBO", { 0.0, 0.8, 0.8 } },
151  { 0, nullptr }
152 };
153 
154 static LevelCollectorProperties level_properties[] = {
155  { 1, "Graphics memory", { 0.0, 0.0, 1.0 }, "MB", 64, 1048576 },
156  { 1, "Buffer switch", { 0.0, 0.6, 0.8 }, "", 500 },
157  { 1, "Buffer switch:Vertex", { 0.8, 0.0, 0.6 } },
158  { 1, "Buffer switch:Index", { 0.8, 0.6, 0.3 } },
159  { 1, "Geom cache size", { 0.6, 0.8, 0.6 }, "", 500 },
160  { 1, "Geom cache size:Active", { 0.9, 1.0, 0.3 }, "", 500 },
161  { 1, "Geom cache operations", { 1.0, 0.6, 0.6 }, "", 500 },
162  { 1, "Geom cache operations:record", { 0.2, 0.4, 0.8 } },
163  { 1, "Geom cache operations:erase", { 0.4, 0.8, 0.2 } },
164  { 1, "Geom cache operations:evict", { 0.8, 0.2, 0.4 } },
165  { 1, "Data transferred", { 0.0, 0.2, 0.4 }, "MB", 12, 1048576 },
166  { 1, "Primitive batches", { 0.2, 0.5, 0.9 }, "", 500 },
167  { 1, "Primitive batches:Other", { 0.2, 0.2, 0.2 } },
168  { 1, "Primitive batches:Triangles", { 0.8, 0.8, 0.8 } },
169  { 1, "Primitive batches:Triangle fans", { 0.8, 0.5, 0.2 } },
170  { 1, "Primitive batches:Triangle strips",{ 0.2, 0.5, 0.8 } },
171  { 1, "Primitive batches:Display lists", { 0.8, 0.5, 1.0 } },
172  { 1, "SW Sprites", { 0.2, 0.7, 0.3 }, "K", 10, 1000 },
173  { 1, "Vertices", { 0.5, 0.2, 0.0 }, "K", 10, 1000 },
174  { 1, "Vertices:Other", { 0.2, 0.2, 0.2 } },
175  { 1, "Vertices:Triangles", { 0.8, 0.8, 0.8 } },
176  { 1, "Vertices:Triangle fans", { 0.8, 0.5, 0.2 } },
177  { 1, "Vertices:Triangle strips", { 0.2, 0.5, 0.8 } },
178  { 1, "Vertices:Indexed triangle strips", { 0.5, 0.2, 0.8 } },
179  { 1, "Vertices:Display lists", { 0.8, 0.5, 1.0 } },
180  { 1, "Vertices:Immediate mode", { 1.0, 0.5, 0.0 } },
181  { 1, "Pixels", { 0.8, 0.3, 0.7 }, "M", 5, 1000000 },
182  { 1, "Nodes", { 0.4, 0.2, 0.8 }, "", 500.0 },
183  { 1, "Nodes:GeomNodes", { 0.8, 0.2, 0.0 } },
184  { 1, "Geoms", { 0.4, 0.8, 0.3 }, "", 500.0 },
185  { 1, "Cull volumes", { 0.7, 0.6, 0.9 }, "", 500.0 },
186  { 1, "Cull volumes:Transforms", { 0.9, 0.6, 0.0 } },
187  { 1, "State changes", { 1.0, 0.5, 0.2 }, "", 500.0 },
188  { 1, "State changes:Other", { 0.2, 0.2, 0.2 } },
189  { 1, "State changes:Transforms", { 0.2, 0.2, 0.8 } },
190  { 1, "State changes:Textures", { 0.8, 0.2, 0.2 } },
191  { 1, "Occlusion tests", { 0.9, 0.8, 0.3 }, "", 500.0 },
192  { 1, "Occlusion results", { 0.3, 0.9, 0.8 }, "", 500.0 },
193  { 1, "System memory", { 0.5, 1.0, 0.5 }, "MB", 64, 1048576 },
194  { 1, "System memory:Heap", { 0.2, 0.2, 1.0 } },
195  { 1, "System memory:Heap:Overhead", { 0.3, 0.4, 0.6 } },
196  { 1, "System memory:Heap:Single", { 0.8, 0.3, 0.3 } },
197  { 1, "System memory:Heap:Array", { 0.1, 0.3, 1.0 } },
198  { 1, "System memory:Heap:Overhead", { 0.9, 0.7, 0.8 } },
199  { 1, "System memory:Heap:External", { 0.2, 0.2, 0.5 } },
200  { 1, "System memory:MMap", { 0.9, 0.4, 0.7 } },
201  { 1, "Vertex Data", { 1.0, 0.4, 0.0 }, "MB", 64, 1048576 },
202  { 1, "Vertex Data:Independent", { 0.9, 0.1, 0.9 } },
203  { 1, "Vertex Data:Small", { 0.2, 0.3, 0.4 } },
204  { 1, "Vertex Data:Pending", { 0.6, 0.8, 1.0 } },
205  { 1, "Vertex Data:Resident", { 0.9, 1.0, 0.7 } },
206  { 1, "Vertex Data:Compressed", { 0.5, 0.1, 0.4 } },
207  { 1, "Vertex Data:Disk", { 0.6, 0.9, 0.1 } },
208  { 1, "Vertex Data:Disk:Unused", { 0.8, 0.4, 0.5 } },
209  { 1, "Vertex Data:Disk:Used", { 0.2, 0.1, 0.6 } },
210  { 1, "TransformStates", { 1.0, 0.5, 0.5 }, "", 5000 },
211  { 1, "TransformStates:On nodes", { 0.2, 0.8, 1.0 } },
212  { 1, "TransformStates:Cached", { 1.0, 0.0, 0.2 } },
213  { 1, "TransformStates:Unused", { 0.2, 0.2, 0.2 } },
214  { 1, "RenderStates", { 0.5, 0.5, 1.0 }, "", 1000 },
215  { 1, "RenderStates:On nodes", { 0.2, 0.8, 1.0 } },
216  { 1, "RenderStates:Cached", { 1.0, 0.0, 0.2 } },
217  { 1, "RenderStates:Unused", { 0.2, 0.2, 0.2 } },
218  { 1, "PipelineCyclers", { 0.5, 0.5, 1.0 }, "", 50000 },
219  { 1, "Dirty PipelineCyclers", { 0.2, 0.2, 0.2 }, "", 5000 },
220  { 1, "Collision Volumes", { 1.0, 0.8, 0.5 }, "", 500 },
221  { 1, "Collision Tests", { 0.5, 0.8, 1.0 }, "", 100 },
222  { 1, "Command latency", { 0.8, 0.2, 0.0 }, "ms", 10, 1.0 / 1000.0 },
223  { 0, nullptr }
224 };
225 
226 
227 /**
228  * Looks up the collector in the compiled-in table defined above, and sets its
229  * properties appropriately if it is found.
230  */
231 static void
232 initialize_collector_def_from_table(const string &fullname, PStatCollectorDef *def) {
233  int i;
234 
235  for (i = 0;
236  time_properties[i].name != nullptr;
237  i++) {
238  const TimeCollectorProperties &tp = time_properties[i];
239  if (fullname == tp.name) {
240  def->_sort = i;
241  if (!def->_active_explicitly_set) {
242  def->_is_active = tp.is_active;
243  }
244  def->_suggested_color = tp.color;
245  if (tp.suggested_scale != 0.0) {
246  def->_suggested_scale = tp.suggested_scale;
247  }
248  return;
249  }
250  }
251 
252  for (i = 0;
253  level_properties[i].name != nullptr;
254  i++) {
255  const LevelCollectorProperties &lp = level_properties[i];
256  if (fullname == lp.name) {
257  def->_sort = i;
258  if (!def->_active_explicitly_set) {
259  def->_is_active = lp.is_active;
260  }
261  def->_suggested_color = lp.color;
262  if (lp.suggested_scale != 0.0) {
263  def->_suggested_scale = lp.suggested_scale;
264  }
265  if (lp.units != nullptr) {
266  def->_level_units = lp.units;
267  }
268  if (lp.inv_factor != 0.0) {
269  def->_factor = 1.0 / lp.inv_factor;
270  }
271  return;
272  }
273  }
274 }
275 
276 
277 /**
278  * This is the only accessor function into this table. The PStatCollectorDef
279  * constructor calls it when a new PStatCollectorDef is created. It should
280  * look up in the table and find a matching definition for this def by name;
281  * if one is found, the properties are applied.
282  */
283 void
284 initialize_collector_def(const PStatClient *client, PStatCollectorDef *def) {
285  string fullname;
286 
287  if (def->_index == 0) {
288  fullname = def->_name;
289  } else {
290  fullname = client->get_collector_fullname(def->_index);
291  }
292 
293  // First, check the compiled-in defaults.
294  initialize_collector_def_from_table(fullname, def);
295 
296  // Then, look to Config for more advice. To do this, we first change the
297  // name to something more like a Config variable name. We replace colons
298  // and spaces with hyphens, eliminate other punctuation, and make all
299  // letters lowercase.
300 
301  string config_name;
302  string::const_iterator ni;
303  for (ni = fullname.begin(); ni != fullname.end(); ++ni) {
304  switch (*ni) {
305  case ':':
306  case ' ':
307  case '\n':
308  case '\r':
309  case '\t':
310  config_name += '-';
311  break;
312 
313  default:
314  if (isalnum(*ni)) {
315  config_name += tolower(*ni);
316  }
317  }
318  }
319 
320  ConfigVariableBool pstats_active
321  ("pstats-active-" + config_name, true, "", ConfigVariable::F_dynamic);
322  ConfigVariableInt pstats_sort
323  ("pstats-sort-" + config_name, def->_sort, "", ConfigVariable::F_dynamic);
324  ConfigVariableDouble pstats_scale
325  ("pstats-scale-" + config_name, def->_suggested_scale, "", ConfigVariable::F_dynamic);
326  ConfigVariableString pstats_units
327  ("pstats-units-" + config_name, def->_level_units, "", ConfigVariable::F_dynamic);
328  ConfigVariableDouble pstats_factor
329  ("pstats-factor-" + config_name, 1.0, "", ConfigVariable::F_dynamic);
330  ConfigVariableColor pstats_color
331  ("pstats-color-" + config_name, LColor::zero(), "", ConfigVariable::F_dynamic);
332 
333  if (pstats_active.has_value()) {
334  def->_is_active = pstats_active;
335  def->_active_explicitly_set = true;
336  }
337 
338  def->_sort = pstats_sort;
339  def->_suggested_scale = pstats_scale;
340  def->_level_units = pstats_units;
341  if (pstats_factor.has_value()) {
342  def->_factor = pstats_factor;
343  }
344 
345  if (pstats_color.has_value()) {
346  def->_suggested_color.r = pstats_color[0];
347  def->_suggested_color.g = pstats_color[1];
348  def->_suggested_color.b = pstats_color[2];
349  }
350 }
351 
352 #endif // DO_PSTATS
ConfigVariableBool
This is a convenience class to specialize ConfigVariable as a boolean type.
Definition: configVariableBool.h:23
configVariableColor.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
pStatProperties.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PStatCollectorDef
Defines the details about the Collectors: the name, the suggested color, etc.
Definition: pStatCollectorDef.h:29
configVariableDouble.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
get_current_pstat_major_version
int get_current_pstat_major_version()
Returns the current major version number of the PStats protocol.
Definition: pStatProperties.cxx:43
configVariableInt.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
get_current_pstat_minor_version
int get_current_pstat_minor_version()
Returns the current minor version number of the PStats protocol.
Definition: pStatProperties.cxx:56
PStatClient
Manages the communications to report statistics via a network connection to a remote PStatServer.
Definition: pStatClient.h:263
ConfigVariableColor
This is a convenience class to specialize ConfigVariable as a set of floating-point types representin...
Definition: configVariableColor.h:35
configVariableBool.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
config_pstatclient.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
pStatClient.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
ConfigVariableDouble
This is a convenience class to specialize ConfigVariable as a floating- point type.
Definition: configVariableDouble.h:24
pStatCollectorDef.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
configVariableString.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
ConfigVariableInt
This is a convenience class to specialize ConfigVariable as an integer type.
Definition: configVariableInt.h:24
PStatCollectorDef::ColorDef
Definition: pStatCollectorDef.h:38
ConfigVariableString
This is a convenience class to specialize ConfigVariable as a string type.
Definition: configVariableString.h:23