15 #include "pStatStripChart.h" 16 #include "pStatClientData.h" 17 #include "pStatMonitor.h" 19 #include "pStatFrameData.h" 20 #include "pStatCollectorDef.h" 21 #include "string_utils.h" 22 #include "config_pstats.h" 33 int thread_index,
int collector_index,
int xsize,
int ysize) :
35 _thread_index(thread_index),
37 _collector_index(collector_index)
39 _scroll_mode = pstats_scroll_mode;
40 _average_mode =
false;
47 _value_height = 1.0/10.0;
51 _title_unknown =
true;
56 _unit_name = def._level_units;
59 set_default_vertical_scale();
81 _next_frame = min(frame_number, _next_frame);
101 if (latest > _next_frame) {
102 draw_frames(_next_frame, latest);
104 _next_frame = latest;
112 while (di != _data.end() &&
114 dec_label_usage((*di).second);
121 if (_level_index != _view.get_level_index()) {
147 if (_collector_index != collector_index) {
148 _collector_index = collector_index;
149 _title_unknown =
true;
170 if (def._suggested_scale != 0.0) {
171 set_vertical_scale(def._suggested_scale);
176 set_vertical_scale(2.0 / get_target_frame_rate());
188 double max_value = 0.0;
190 int frame_number = -1;
191 for (
int x = 0; x <= _xsize; x++) {
192 double time = pixel_to_timestamp(x);
196 if (thread_data->
has_frame(frame_number)) {
197 double net_value = get_net_value(frame_number);
198 max_value = max(max_value, net_value);
204 if (max_value == 0.0) {
205 set_vertical_scale(1.0);
207 set_vertical_scale(max_value * 1.1);
222 double time = pixel_to_timestamp(xpoint);
230 double start_time = pixel_to_timestamp(xpoint);
235 compute_average_pixel_data(fdata, then_i, now_i, start_time);
236 double overall_value = 0.0;
239 FrameData::const_iterator fi;
240 for (fi = fdata.begin(); fi != fdata.end(); ++fi) {
241 const ColorData &cd = (*fi);
242 overall_value += cd._net_value;
243 y = height_to_pixel(overall_value);
245 return cd._collector_index;
251 const FrameData &fdata = get_frame_data(frame_number);
252 double overall_value = 0.0;
255 FrameData::const_iterator fi;
256 for (fi = fdata.begin(); fi != fdata.end(); ++fi) {
257 const ColorData &cd = (*fi);
258 overall_value += cd._net_value;
259 y = height_to_pixel(overall_value);
261 return cd._collector_index;
279 _title_unknown =
false;
285 if (_view.get_show_level()) {
286 if (!def._level_units.empty()) {
287 text +=
" (" + def._level_units +
")";
293 _title_unknown =
true;
296 if (_thread_index != 0) {
298 text +=
" (" + client_data->
get_thread_name(_thread_index) +
" thread)";
300 _title_unknown =
true;
315 return _title_unknown;
324 void PStatStripChart::
327 FrameData::iterator ai;
328 FrameData::const_iterator bi;
331 bi = additional.begin();
335 if (fdata.size() == additional.size()) {
339 while (ai != fdata.end() &&
340 (*ai)._collector_index == (*bi)._collector_index) {
341 (*ai)._net_value += ((*bi)._net_value * weight);
346 if (ai == fdata.end()) {
355 result.reserve(max(fdata.size(), additional.size()));
356 FrameData::const_iterator ci;
357 for (ci = fdata.begin(); ci != ai; ++ci) {
358 result.push_back(*ci);
364 result.reserve(max(fdata.size(), additional.size()));
367 while (ai != fdata.end() && bi != additional.end()) {
368 if ((*ai)._i < (*bi)._i) {
370 result.push_back(*ai);
373 }
else if ((*bi)._i < (*ai)._i) {
376 scaled._collector_index = (*bi)._collector_index;
377 scaled._i = (*bi)._i;
378 scaled._net_value = (*bi)._net_value * weight;
379 result.push_back(scaled);
385 combined._collector_index = (*ai)._collector_index;
386 combined._i = (*bi)._i;
387 combined._net_value = (*ai)._net_value + (*bi)._net_value * weight;
388 result.push_back(combined);
394 while (ai != fdata.end()) {
396 result.push_back(*ai);
400 while (bi != additional.end()) {
403 scaled._collector_index = (*bi)._collector_index;
404 scaled._i = (*bi)._i;
405 scaled._net_value = (*bi)._net_value * weight;
406 result.push_back(scaled);
419 void PStatStripChart::
420 scale_frame_data(
FrameData &fdata,
double factor) {
421 FrameData::iterator fi;
422 for (fi = fdata.begin(); fi != fdata.end(); ++fi) {
423 (*fi)._net_value *= factor;
437 get_frame_data(
int frame_number) {
438 Data::const_iterator di;
439 di = _data.find(frame_number);
440 if (di != _data.end()) {
445 _view.set_to_frame(thread_data->
get_frame(frame_number));
451 for (
int i = 0; i < num_children; i++) {
454 cd._collector_index = (
unsigned short)child->
get_collector();
455 cd._i = (
unsigned short)i;
457 if (cd._net_value != 0.0) {
465 cd._collector_index = (
unsigned short)level->
get_collector();
466 cd._i = (
unsigned short)num_children;
468 if (cd._net_value > 0.0) {
472 inc_label_usage(fdata);
492 void PStatStripChart::
494 int &then_i,
int &now_i,
double now) {
503 double then = now - pstats_average_time;
506 while (then_i <= latest_frame &&
510 while (now_i <= latest_frame &&
522 accumulate_frame_data(result, get_frame_data(then_i),
527 for (
int frame_number = then_i + 1;
528 frame_number < now_i;
530 accumulate_frame_data(result, get_frame_data(frame_number),
537 accumulate_frame_data(result, get_frame_data(now_i), now - last);
540 scale_frame_data(result, 1.0f / (now - then));
549 double PStatStripChart::
550 get_net_value(
int frame_number)
const {
554 double net_value = 0.0;
555 FrameData::const_iterator fi;
556 for (fi = frame.begin(); fi != frame.end(); ++fi) {
557 const ColorData &cd = (*fi);
558 net_value += cd._net_value;
570 double PStatStripChart::
571 get_average_net_value()
const {
577 double now = _time_width + _start_time;
578 double then = now - pstats_average_time;
580 int num_frames = now_i - then_i + 1;
582 if (_collector_index == 0 && !_view.get_show_level()) {
590 double now = now_frame_data.
get_end();
591 double elapsed_time = (now - then_frame_data.
get_start());
592 return elapsed_time / (double)num_frames;
602 double net_value = 0.0f;
603 double net_time = 0.0f;
610 net_value += get_net_value(then_i) * this_time;
611 net_time += this_time;
614 for (
int frame_number = then_i + 1;
615 frame_number <= now_i;
618 net_value += get_net_value(frame_number) * this_time;
619 net_time += this_time;
622 return net_value / net_time;
634 void PStatStripChart::
635 changed_size(
int xsize,
int ysize) {
636 if (xsize != _xsize || ysize != _ysize) {
639 if (_xsize > 0 && _ysize > 0) {
640 _cursor_pixel = xsize * _cursor_pixel / _xsize;
644 draw_pixels(0, _xsize);
648 double old_start_time = _start_time;
651 _start_time -= _time_width;
652 draw_pixels(_cursor_pixel, _xsize);
655 _start_time = old_start_time;
656 draw_pixels(0, _cursor_pixel);
669 void PStatStripChart::
672 draw_pixels(0, _xsize);
682 void PStatStripChart::
695 void PStatStripChart::
706 void PStatStripChart::
707 copy_region(
int,
int,
int) {
718 void PStatStripChart::
719 begin_draw(
int,
int) {
730 void PStatStripChart::
741 void PStatStripChart::
742 draw_empty(
int,
int) {
752 void PStatStripChart::
764 void PStatStripChart::
777 void PStatStripChart::
787 _client_data(client_data) {
789 bool operator () (
int a,
int b)
const {
802 void PStatStripChart::
808 for (
int i = 0; i < num_children; i++) {
811 if (is_label_used(collector_index)) {
812 _labels.push_back(collector_index);
817 sort(_labels.begin(), _labels.end(), sort_labels);
820 _labels.push_back(collector_index);
822 _labels_changed =
true;
823 _level_index = _view.get_level_index();
832 void PStatStripChart::
833 normal_guide_bars() {
834 update_guide_bars(4, _value_height);
843 void PStatStripChart::
844 draw_frames(
int first_frame,
int last_frame) {
860 if (thread_data->
has_frame(first_frame)) {
870 if (_first_data && !_scroll_mode) {
871 first_pixel = min(_cursor_pixel, first_pixel);
875 if (last_pixel - first_pixel >= _xsize) {
883 if (last_pixel <= _xsize) {
885 _cursor_pixel = last_pixel;
886 draw_pixels(first_pixel, last_pixel);
891 int slide_pixels = last_pixel - _xsize;
892 copy_region(slide_pixels, first_pixel, 0);
893 first_pixel -= slide_pixels;
894 last_pixel -= slide_pixels;
895 _start_time += (double)slide_pixels / (
double)_xsize * _time_width;
896 draw_pixels(first_pixel, last_pixel);
901 draw_pixels(first_pixel, _xsize);
902 _start_time = pixel_to_timestamp(_xsize);
903 last_pixel -= _xsize;
904 _cursor_pixel = last_pixel;
905 draw_pixels(0, last_pixel);
915 void PStatStripChart::
916 draw_pixels(
int first_pixel,
int last_pixel) {
917 begin_draw(first_pixel, last_pixel);
920 if (_average_mode && !thread_data->
is_empty()) {
922 double start_time = pixel_to_timestamp(first_pixel);
925 for (
int x = first_pixel; x <= last_pixel; x++) {
926 if (x == _cursor_pixel && !_scroll_mode) {
930 compute_average_pixel_data(fdata, then_i, now_i, pixel_to_timestamp(x));
931 draw_slice(x, 1, fdata);
938 int frame_number = -1;
940 while (x <= last_pixel) {
941 if (x == _cursor_pixel && !_scroll_mode) {
946 double time = pixel_to_timestamp(x);
949 int stop_pixel = last_pixel;
951 stop_pixel = min(stop_pixel, _cursor_pixel);
953 while (x + w < stop_pixel &&
957 if (thread_data->
has_frame(frame_number)) {
958 draw_slice(x, w, get_frame_data(frame_number));
967 end_draw(first_pixel, last_pixel);
975 void PStatStripChart::
976 clear_label_usage() {
977 _label_usage.clear();
989 void PStatStripChart::
990 dec_label_usage(
const FrameData &fdata) {
991 FrameData::const_iterator fi;
992 for (fi = fdata.begin(); fi != fdata.end(); ++fi) {
993 const ColorData &cd = (*fi);
994 nassertv(cd._collector_index < (
int)_label_usage.size());
995 nassertv(_label_usage[cd._collector_index] > 0);
996 _label_usage[cd._collector_index]--;
997 if (_label_usage[cd._collector_index] == 0) {
1016 void PStatStripChart::
1017 inc_label_usage(
const FrameData &fdata) {
1018 FrameData::const_iterator fi;
1019 for (fi = fdata.begin(); fi != fdata.end(); ++fi) {
1020 const ColorData &cd = (*fi);
1021 while (cd._collector_index >= (
int)_label_usage.size()) {
1022 _label_usage.push_back(0);
1024 nassertv(_label_usage[cd._collector_index] >= 0);
1025 _label_usage[cd._collector_index]++;
1026 if (_label_usage[cd._collector_index] == 1) {
bool first_data() const
Returns true if the chart has seen its first data appear on it, false if it is still a virgin chart...
void set_auto_vertical_scale()
Sets the vertical scale to make all the data visible.
void new_data(int frame_number)
Indicates that new data has become available.
const PStatViewLevel * get_child(int n) const
Returns the nth child of this Level/Collector.
const PStatFrameData & get_frame(int frame_number) const
Returns a FrameData structure associated with the indicated frame number.
int get_frame_number_at_time(double time, int hint=-1) const
Returns the frame number of the latest frame not later than the indicated time.
bool get_elapsed_frames(int &then_i, int &now_i) const
Computes the oldest frame number not older than pstats_average_time seconds, and the newest frame num...
The data associated with a particular client, but not with any one particular frame or thread: the li...
double get_value_alone() const
Returns the total level value (or elapsed time value) for this Collector, not including any values ac...
This is an abstract base class for several different kinds of graphs that have a few things in common...
const PStatCollectorDef & get_collector_def(int index) const
Returns the nth collector definition.
string get_collector_fullname(int index) const
Returns the "full name" of the indicated collector.
int get_num_threads() const
Returns the total number of threads the Data knows about.
This is an abstract class that presents the interface for drawing a basic strip-chart, showing the relative value over an interval of time for several different collectors, differentiated by bands of color.
double get_oldest_time() const
Returns the timestamp (in seconds elapsed since connection) of the oldest available frame...
int get_collector_under_pixel(int xpoint, int ypoint)
Return the collector index associated with the particular band of color at the indicated pixel locati...
This is our own Panda specialization on the default STL vector.
This is a single level value, or band of color, within a View.
double get_net_value() const
Returns the total level value (or elapsed time) represented by this Collector, including all values i...
This is an abstract class that presents the interface to any number of different front-ends for the s...
bool has_collector(int index) const
Returns true if the indicated collector has been defined by the client already, false otherwise...
void update()
Updates the chart with the latest data.
bool has_thread(int index) const
Returns true if the indicated thread has been defined by the client already, false otherwise...
Contains the raw timing and level data for a single frame.
string get_title_text()
Returns the text suitable for the title label on the top line.
A View boils down the frame data to a linear list of times spent in a number of different Collectors...
int get_num_collectors() const
Returns the total number of collectors the Data knows about.
A collection of FrameData structures for recently-received frames within a particular thread...
bool is_title_unknown() const
Returns true if get_title_text() has never yet returned an answer, false if it has.
bool has_frame(int frame_number) const
Returns true if we have received data for the indicated frame number from the client and we still hav...
void set_collector_index(int collector_index)
Changes the collector represented by this strip chart.
int get_collector() const
Returns the Collector index associated with this level.
double get_end() const
Returns the time of the last data point in the frame data.
void set_default_vertical_scale()
Sets the vertical scale according to the suggested scale of the base collector, if any...
int get_num_children() const
Returns the number of children of this Level/Collector.
Defines the details about the Collectors: the name, the suggested color, etc.
bool is_empty() const
Returns true if the structure contains no frames, false otherwise.
double get_start() const
Returns the time of the first data point in the frame data.
int get_latest_frame_number() const
Returns the frame number of the most recent frame stored in the data.
double get_net_time() const
Returns the total time elapsed for the frame.
string get_thread_name(int index) const
Returns the name of the indicated thread.