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