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
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
This is a convenience class to specialize ConfigVariable as a boolean type.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
This is a convenience class to specialize ConfigVariable as a set of floating-point types representin...
int get_current_pstat_minor_version()
Returns the current minor version number of the PStats protocol.
This is a convenience class to specialize ConfigVariable as a floating- point type.
This is a convenience class to specialize ConfigVariable as a string type.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
int get_current_pstat_major_version()
Returns the current major version number of the PStats protocol.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
This is a convenience class to specialize ConfigVariable as an integer type.
Defines the details about the Collectors: the name, the suggested color, etc.
Manages the communications to report statistics via a network connection to a remote PStatServer.
Definition: pStatClient.h:263
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.