00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "pStatView.h"
00020
00021 #include "pStatFrameData.h"
00022 #include "pStatCollectorDef.h"
00023 #include "vector_int.h"
00024 #include "plist.h"
00025 #include "pset.h"
00026
00027 #include <algorithm>
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 class FrameSample {
00039 public:
00040 typedef plist<FrameSample *> Started;
00041
00042 FrameSample() {
00043 _touched = false;
00044 _is_started = false;
00045 _pushed = false;
00046 _net_time = 0.0;
00047 }
00048 void data_point(float time, bool is_start, Started &started) {
00049 _touched = true;
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063 nassertv(is_start != _is_started);
00064
00065 _is_started = is_start;
00066
00067 if (_pushed) {
00068 nassertv(!_is_started);
00069 Started::iterator si = find(started.begin(), started.end(), this);
00070 nassertv(si != started.end());
00071 started.erase(si);
00072
00073 } else {
00074 if (_is_started) {
00075 _net_time -= time;
00076 push_all(time, started);
00077 started.push_back(this);
00078 } else {
00079 _net_time += time;
00080 Started::iterator si = find(started.begin(), started.end(), this);
00081 nassertv(si != started.end());
00082 started.erase(si);
00083 pop_one(time, started);
00084 }
00085 }
00086 }
00087 void push(float time) {
00088 if (!_pushed) {
00089 _pushed = true;
00090 if (_is_started) {
00091 _net_time += time;
00092 }
00093 }
00094 }
00095 void pop(float time) {
00096 if (_pushed) {
00097 _pushed = false;
00098 if (_is_started) {
00099 _net_time -= time;
00100 }
00101 }
00102 }
00103
00104 void push_all(float time, Started &started) {
00105 Started::iterator si;
00106 for (si = started.begin(); si != started.end(); ++si) {
00107 (*si)->push(time);
00108 }
00109 }
00110
00111 void pop_one(float time, Started &started) {
00112 Started::reverse_iterator si;
00113 for (si = started.rbegin(); si != started.rend(); ++si) {
00114 if ((*si)->_pushed) {
00115 (*si)->pop(time);
00116 return;
00117 }
00118 }
00119 }
00120
00121 bool _touched;
00122 bool _is_started;
00123 bool _pushed;
00124 float _net_time;
00125 };
00126
00127
00128
00129
00130
00131
00132
00133
00134 PStatView::
00135 PStatView() {
00136 _constraint = 0;
00137 _show_level = false;
00138 _all_collectors_known = false;
00139 _level_index = 0;
00140 }
00141
00142
00143
00144
00145
00146
00147 PStatView::
00148 ~PStatView() {
00149 clear_levels();
00150 }
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173 void PStatView::
00174 constrain(int collector, bool show_level) {
00175 _constraint = collector;
00176 _show_level = show_level;
00177 clear_levels();
00178 }
00179
00180
00181
00182
00183
00184
00185
00186 void PStatView::
00187 unconstrain() {
00188 constrain(0, false);
00189 }
00190
00191
00192
00193
00194
00195
00196 void PStatView::
00197 set_thread_data(const PStatThreadData *thread_data) {
00198 _thread_data = thread_data;
00199 _client_data = thread_data->get_client_data();
00200 clear_levels();
00201 _all_collectors_known = false;
00202 }
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219 void PStatView::
00220 set_to_frame(const PStatFrameData &frame_data) {
00221 nassertv(!_thread_data.is_null());
00222 nassertv(!_client_data.is_null());
00223
00224 if (_show_level) {
00225 update_level_data(frame_data);
00226 } else {
00227 update_time_data(frame_data);
00228 }
00229 }
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240 bool PStatView::
00241 all_collectors_known() const {
00242 return _all_collectors_known;
00243 }
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253 float PStatView::
00254 get_net_value() const {
00255 float net = 0.0;
00256 Levels::const_iterator li;
00257 for (li = _levels.begin(); li != _levels.end(); ++li) {
00258 net += (*li).second->_value_alone;
00259 }
00260
00261 return net;
00262 }
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273 const PStatViewLevel *PStatView::
00274 get_top_level() {
00275 return get_level(_constraint);
00276 }
00277
00278
00279
00280
00281
00282
00283
00284 bool PStatView::
00285 has_level(int collector) const {
00286 Levels::const_iterator li;
00287 li = _levels.find(collector);
00288 return (li != _levels.end());
00289 }
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300 PStatViewLevel *PStatView::
00301 get_level(int collector) {
00302 Levels::const_iterator li;
00303 li = _levels.find(collector);
00304 if (li != _levels.end()) {
00305 return (*li).second;
00306 }
00307
00308 PStatViewLevel *level = new PStatViewLevel;
00309 level->_collector = collector;
00310 level->_parent = NULL;
00311 _levels[collector] = level;
00312
00313 reset_level(level);
00314 return level;
00315 }
00316
00317
00318
00319
00320
00321
00322
00323 void PStatView::
00324 update_time_data(const PStatFrameData &frame_data) {
00325 int num_events = frame_data.get_num_events();
00326
00327 typedef pvector<FrameSample> Samples;
00328 Samples samples(_client_data->get_num_collectors());
00329
00330 FrameSample::Started started;
00331
00332 _all_collectors_known = true;
00333
00334
00335
00336 typedef pset<int> GotSamples;
00337 GotSamples got_samples;
00338
00339 int i;
00340 for (i = 0; i < num_events; i++) {
00341 int collector_index = frame_data.get_time_collector(i);
00342 bool is_start = frame_data.is_start(i);
00343
00344 if (!_client_data->has_collector(collector_index)) {
00345 _all_collectors_known = false;
00346
00347 } else {
00348 nassertv(collector_index >= 0 && collector_index < (int)samples.size());
00349
00350 if (_client_data->get_child_distance(_constraint, collector_index) >= 0) {
00351
00352
00353 if (is_start == samples[collector_index]._is_started) {
00354 nout << "Unexpected data point for "
00355 << _client_data->get_collector_fullname(collector_index)
00356 << "\n";
00357 } else {
00358 samples[collector_index].data_point(frame_data.get_time(i), is_start, started);
00359 got_samples.insert(collector_index);
00360 }
00361 }
00362 }
00363 }
00364
00365
00366
00367 Samples::iterator si;
00368 for (i = 0, si = samples.begin(); si != samples.end(); ++i, ++si) {
00369 if ((*si)._is_started) {
00370 nout << _client_data->get_collector_fullname(i)
00371 << " was not stopped at frame end!\n";
00372 (*si).data_point(frame_data.get_end(), false, started);
00373 }
00374 }
00375
00376 nassertv(started.empty());
00377
00378 bool any_new_levels = false;
00379
00380
00381
00382 Levels::iterator li, lnext;
00383 li = _levels.begin();
00384 while (li != _levels.end()) {
00385
00386
00387 lnext = li;
00388 ++lnext;
00389
00390 PStatViewLevel *level = (*li).second;
00391 if (reset_level(level)) {
00392 any_new_levels = true;
00393 }
00394
00395 int collector_index = level->_collector;
00396 GotSamples::iterator gi;
00397 gi = got_samples.find(collector_index);
00398 if (gi != got_samples.end()) {
00399 level->_value_alone = samples[collector_index]._net_time;
00400 got_samples.erase(gi);
00401 }
00402
00403 li = lnext;
00404 }
00405
00406
00407
00408 if (!got_samples.empty()) {
00409 any_new_levels = true;
00410
00411 GotSamples::const_iterator gi;
00412 for (gi = got_samples.begin(); gi != got_samples.end(); ++gi) {
00413 int collector_index = (*gi);
00414 PStatViewLevel *level = get_level(collector_index);
00415 level->_value_alone = samples[*gi]._net_time;
00416 }
00417 }
00418
00419 if (any_new_levels) {
00420 _level_index++;
00421 }
00422 }
00423
00424
00425
00426
00427
00428
00429
00430 void PStatView::
00431 update_level_data(const PStatFrameData &frame_data) {
00432 _all_collectors_known = true;
00433
00434
00435
00436 typedef pmap<int, float> GotValues;
00437 GotValues net_values;
00438
00439 int i;
00440 int num_levels = frame_data.get_num_levels();
00441 for (i = 0; i < num_levels; i++) {
00442 int collector_index = frame_data.get_level_collector(i);
00443 float value = frame_data.get_level(i);
00444
00445 if (!_client_data->has_collector(collector_index)) {
00446 _all_collectors_known = false;
00447
00448 } else {
00449 if (_client_data->get_child_distance(_constraint, collector_index) >= 0) {
00450 net_values[collector_index] = value;
00451 }
00452 }
00453 }
00454
00455
00456
00457
00458
00459 GotValues alone_values = net_values;
00460
00461 GotValues::iterator gi;
00462 for (gi = net_values.begin(); gi != net_values.end(); ++gi) {
00463 int collector_index = (*gi).first;
00464 float value = (*gi).second;
00465
00466
00467 while (collector_index != 0 && collector_index != _constraint) {
00468 const PStatCollectorDef &def =
00469 _client_data->get_collector_def(collector_index);
00470 int parent_index = def._parent_index;
00471 GotValues::iterator pi = alone_values.find(parent_index);
00472 if (pi != alone_values.end()) {
00473
00474 (*pi).second -= value;
00475 }
00476
00477 collector_index = parent_index;
00478 }
00479 }
00480
00481
00482 bool any_new_levels = false;
00483
00484
00485
00486 Levels::iterator li, lnext;
00487 li = _levels.begin();
00488 while (li != _levels.end()) {
00489
00490
00491 lnext = li;
00492 ++lnext;
00493
00494 PStatViewLevel *level = (*li).second;
00495 if (reset_level(level)) {
00496 any_new_levels = true;
00497 }
00498
00499 int collector_index = level->_collector;
00500 GotValues::iterator gi;
00501 gi = alone_values.find(collector_index);
00502 if (gi != alone_values.end()) {
00503 level->_value_alone = (*gi).second;
00504 alone_values.erase(gi);
00505 }
00506
00507 li = lnext;
00508 }
00509
00510
00511
00512 if (!alone_values.empty()) {
00513 any_new_levels = true;
00514
00515 GotValues::const_iterator gi;
00516 for (gi = alone_values.begin(); gi != alone_values.end(); ++gi) {
00517 int collector_index = (*gi).first;
00518 PStatViewLevel *level = get_level(collector_index);
00519 level->_value_alone = (*gi).second;
00520 }
00521 }
00522
00523 if (any_new_levels) {
00524 _level_index++;
00525 }
00526 }
00527
00528
00529
00530
00531
00532
00533 void PStatView::
00534 clear_levels() {
00535 Levels::iterator li;
00536 for (li = _levels.begin(); li != _levels.end(); ++li) {
00537 delete (*li).second;
00538 }
00539 _levels.clear();
00540 }
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555 bool PStatView::
00556 reset_level(PStatViewLevel *level) {
00557 bool any_changed = false;
00558 level->_value_alone = 0.0;
00559
00560 if (level->_collector == _constraint) {
00561 return false;
00562 }
00563
00564 if (_client_data->has_collector(level->_collector)) {
00565 int parent_index =
00566 _client_data->get_collector_def(level->_collector)._parent_index;
00567
00568 if (level->_parent == (PStatViewLevel *)NULL) {
00569
00570 PStatViewLevel *parent_level = get_level(parent_index);
00571 nassertr(parent_level != level, true);
00572
00573 level->_parent = parent_level;
00574 parent_level->_children.push_back(level);
00575 parent_level->sort_children(_client_data);
00576 any_changed = true;
00577
00578 } else if (level->_parent->_collector != parent_index) {
00579
00580
00581 PStatViewLevel *old_parent_level = level->_parent;
00582 nassertr(old_parent_level != level, true);
00583
00584 if (parent_index != 0) {
00585 PStatViewLevel *new_parent_level = get_level(parent_index);
00586 nassertr(new_parent_level != level, true);
00587 level->_parent = new_parent_level;
00588 new_parent_level->_children.push_back(level);
00589 new_parent_level->sort_children(_client_data);
00590 } else {
00591 level->_parent = NULL;
00592 }
00593
00594 PStatViewLevel::Children::iterator ci =
00595 find(old_parent_level->_children.begin(),
00596 old_parent_level->_children.end(),
00597 level);
00598
00599 nassertr(ci != old_parent_level->_children.end(), true);
00600 old_parent_level->_children.erase(ci);
00601 any_changed = true;
00602 }
00603 }
00604
00605 return any_changed;
00606 }
00607
00608