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