From 866507bb1745064e8c190818b6cd64b474d1a752 Mon Sep 17 00:00:00 2001 From: David Rose Date: Mon, 21 May 2001 23:49:53 +0000 Subject: [PATCH] Add pstats timing of wrt calls --- panda/src/graph/Sources.pp | 2 +- panda/src/graph/wrt.I | 5 +- panda/src/graph/wrt.cxx | 7 +- panda/src/graph/wrt.h | 5 + panda/src/mathutil/boundingHexahedron.cxx | 2 +- panda/src/net/connectionWriter.cxx | 12 ++ panda/src/net/connectionWriter.h | 2 + panda/src/pstatclient/Sources.pp | 5 +- panda/src/pstatclient/config_pstats.cxx | 2 +- panda/src/pstatclient/config_pstats.h | 2 + panda/src/pstatclient/pStatClient.cxx | 74 +++++--- panda/src/pstatclient/pStatClient.h | 2 +- .../pstatclient/pStatClientControlMessage.cxx | 9 +- .../pstatclient/pStatClientControlMessage.h | 6 +- panda/src/pstatclient/pStatClientVersion.I | 49 +++++ panda/src/pstatclient/pStatClientVersion.cxx | 19 ++ panda/src/pstatclient/pStatClientVersion.h | 39 ++++ panda/src/pstatclient/pStatCollectorDef.cxx | 5 +- panda/src/pstatclient/pStatCollectorDef.h | 4 +- panda/src/pstatclient/pStatFrameData.cxx | 3 +- panda/src/pstatclient/pStatFrameData.h | 3 +- panda/src/pstatclient/pStatProperties.cxx | 176 +++++++++++++----- pandatool/src/pstatserver/pStatClientData.h | 3 +- pandatool/src/pstatserver/pStatReader.cxx | 35 +++- 24 files changed, 379 insertions(+), 92 deletions(-) create mode 100644 panda/src/pstatclient/pStatClientVersion.I create mode 100644 panda/src/pstatclient/pStatClientVersion.cxx create mode 100644 panda/src/pstatclient/pStatClientVersion.h diff --git a/panda/src/graph/Sources.pp b/panda/src/graph/Sources.pp index 7a9298aeff..757215a500 100644 --- a/panda/src/graph/Sources.pp +++ b/panda/src/graph/Sources.pp @@ -4,7 +4,7 @@ #begin lib_target #define TARGET graph #define LOCAL_LIBS \ - putil mathutil + pstatclient putil mathutil #define SOURCES \ allAttributesWrapper.I allAttributesWrapper.T \ diff --git a/panda/src/graph/wrt.I b/panda/src/graph/wrt.I index f526d164ba..2337276700 100644 --- a/panda/src/graph/wrt.I +++ b/panda/src/graph/wrt.I @@ -392,7 +392,6 @@ cached_wrt_base(const Node *from, InputIterator2 to_arcs_begin, InputIterator2 to_arcs_end, TransitionWrapper &result, TypeHandle graph_type) { - UpdateSeq now = last_graph_update(graph_type); TransitionWrapper net_from_trans = TransitionWrapper::init_from(result); @@ -506,6 +505,8 @@ wrt_base(const Node *from, InputIterator2 to_arcs_begin, InputIterator2 to_arcs_end, TransitionWrapper &result, TypeHandle graph_type) { + PStatTimer timer(_wrt_pcollector); + #ifndef NDEBUG if (!cache_wrt) { uncached_wrt_base(from, from_arcs_begin, from_arcs_end, @@ -874,6 +875,8 @@ template INLINE_GRAPH Node * wrt_subtree(NodeRelation *arc, Node *to, UpdateSeq as_of, UpdateSeq now, TransitionWrapper &result, TypeHandle graph_type) { + PStatTimer timer(_wrt_subtree_pcollector); + #ifndef NDEBUG if (!cache_wrt) { // If we aren't caching wrt, compute it explicitly. diff --git a/panda/src/graph/wrt.cxx b/panda/src/graph/wrt.cxx index 83252f51d3..bc1e0d2497 100644 --- a/panda/src/graph/wrt.cxx +++ b/panda/src/graph/wrt.cxx @@ -5,6 +5,7 @@ #include "wrt.h" -// There's no real need to have this file, but it's sometimes a little -// cleaner to guarantee that every .h file gets scanned when this -// directory is built. +#ifndef CPPPARSER +PStatCollector _wrt_pcollector("WRT"); +PStatCollector _wrt_subtree_pcollector("WRT:subtree"); +#endif diff --git a/panda/src/graph/wrt.h b/panda/src/graph/wrt.h index 34f454e726..83ea406ca6 100644 --- a/panda/src/graph/wrt.h +++ b/panda/src/graph/wrt.h @@ -13,6 +13,8 @@ #include "config_graph.h" #include +#include +#include class Node; @@ -127,6 +129,9 @@ INLINE_GRAPH Node * wrt_subtree(NodeRelation *arc, Node *to, UpdateSeq as_of, UpdateSeq now, TransitionWrapper &result, TypeHandle graph_type); +// This is used to count the amount of time spend in calls to wrt(). +extern EXPCL_PANDA PStatCollector _wrt_pcollector; +extern EXPCL_PANDA PStatCollector _wrt_subtree_pcollector; #ifndef DONT_INLINE_GRAPH #include "wrt.I" diff --git a/panda/src/mathutil/boundingHexahedron.cxx b/panda/src/mathutil/boundingHexahedron.cxx index 84206f1aea..e5e73a52ec 100644 --- a/panda/src/mathutil/boundingHexahedron.cxx +++ b/panda/src/mathutil/boundingHexahedron.cxx @@ -304,7 +304,7 @@ set_planes() { // transforming it with a -1 matrix. We do this by ensuring that // the centroid is in front of all of the planes (actually, we only // need to test the first plane). - if (_planes[0].dist_to_plane(_centroid) >= 0) { + if (_planes[0].dist_to_plane(_centroid) > 0) { // Oops! We're flipped! Rebuild the planes in the opposite // direction. _planes[0] = Planef(_points[0], _points[2], _points[3]); diff --git a/panda/src/net/connectionWriter.cxx b/panda/src/net/connectionWriter.cxx index e3d6509061..2a3a98b166 100644 --- a/panda/src/net/connectionWriter.cxx +++ b/panda/src/net/connectionWriter.cxx @@ -111,6 +111,7 @@ send(const Datagram &datagram, const PT(Connection) &connection) { } } + //////////////////////////////////////////////////////////////////// // Function: ConnectionWriter::send // Access: Public @@ -158,6 +159,17 @@ send(const Datagram &datagram, const PT(Connection) &connection, } } +//////////////////////////////////////////////////////////////////// +// Function: ConnectionWriter::is_valid_for_udp +// Access: Public +// Description: Returns true if the datagram is small enough to be +// sent over a UDP packet, false otherwise. +//////////////////////////////////////////////////////////////////// +bool ConnectionWriter:: +is_valid_for_udp(const Datagram &datagram) const { + return (int)datagram.get_length() <= maximum_udp_datagram; +} + //////////////////////////////////////////////////////////////////// // Function: ConnectionWriter::get_manager // Access: Public diff --git a/panda/src/net/connectionWriter.h b/panda/src/net/connectionWriter.h index be7c3c1cd8..5f162c7e47 100644 --- a/panda/src/net/connectionWriter.h +++ b/panda/src/net/connectionWriter.h @@ -41,6 +41,8 @@ PUBLISHED: const PT(Connection) &connection, const NetAddress &address); + bool is_valid_for_udp(const Datagram &datagram) const; + ConnectionManager *get_manager() const; bool is_immediate() const; int get_num_threads() const; diff --git a/panda/src/pstatclient/Sources.pp b/panda/src/pstatclient/Sources.pp index 10dfa2fbaf..59f55340b9 100644 --- a/panda/src/pstatclient/Sources.pp +++ b/panda/src/pstatclient/Sources.pp @@ -9,7 +9,9 @@ #define SOURCES \ config_pstats.cxx config_pstats.h pStatClient.I pStatClient.cxx \ - pStatClient.h pStatClientControlMessage.cxx \ + pStatClient.h \ + pStatClientVersion.I pStatClientVersion.cxx pStatClientVersion.h \ + pStatClientControlMessage.cxx \ pStatClientControlMessage.h \ pStatCollector.I pStatCollector.h \ pStatCollectorDef.cxx \ @@ -22,6 +24,7 @@ #define INSTALL_HEADERS \ config_pstats.h pStatClient.I pStatClient.h \ + pStatClientVersion.I pStatClientVersion.h \ pStatClientControlMessage.h pStatCollector.I pStatCollector.h \ pStatCollectorDef.h pStatFrameData.I pStatFrameData.h \ pStatProperties.h \ diff --git a/panda/src/pstatclient/config_pstats.cxx b/panda/src/pstatclient/config_pstats.cxx index e05b61be7a..380e8dcb77 100644 --- a/panda/src/pstatclient/config_pstats.cxx +++ b/panda/src/pstatclient/config_pstats.cxx @@ -7,7 +7,7 @@ #include -Configure(config_pstats); +ConfigureDef(config_pstats); NotifyCategoryDef(pstats, ""); ConfigureFn(config_pstats) { diff --git a/panda/src/pstatclient/config_pstats.h b/panda/src/pstatclient/config_pstats.h index 2bfb43ffb7..53a71b877b 100644 --- a/panda/src/pstatclient/config_pstats.h +++ b/panda/src/pstatclient/config_pstats.h @@ -9,9 +9,11 @@ #include #include +#include // Configure variables for pstats package. +ConfigureDecl(config_pstats, EXPCL_PANDA, EXPTP_PANDA); NotifyCategoryDecl(pstats, EXPCL_PANDA, EXPTP_PANDA); extern EXPCL_PANDA string get_pstats_name(); diff --git a/panda/src/pstatclient/pStatClient.cxx b/panda/src/pstatclient/pStatClient.cxx index 5c15836a15..df7262415e 100644 --- a/panda/src/pstatclient/pStatClient.cxx +++ b/panda/src/pstatclient/pStatClient.cxx @@ -325,7 +325,7 @@ make_thread(const string &name) { Thread thread; thread._name = name; thread._is_active = false; - thread._last_packet = 0.0; + thread._next_packet = 0.0; thread._frame_number = 0; _threads.push_back(thread); @@ -435,7 +435,7 @@ ns_disconnect() { for (ti = _threads.begin(); ti != _threads.end(); ++ti) { (*ti)._frame_number = 0; (*ti)._is_active = false; - (*ti)._last_packet = 0.0; + (*ti)._next_packet = 0.0; (*ti)._frame_data.clear(); } @@ -472,7 +472,8 @@ start(int collector_index, int thread_index, float as_of) { nassertv(collector_index >= 0 && collector_index < (int)_collectors.size()); nassertv(thread_index >= 0 && thread_index < (int)_threads.size()); - if (_threads[thread_index]._is_active) { + if (_collectors[collector_index]._def->_is_active && + _threads[thread_index]._is_active) { if (_collectors[collector_index]._per_thread[thread_index]._nested_count == 0) { // This collector wasn't already started in this thread; record // a new data point. @@ -494,7 +495,8 @@ stop(int collector_index, int thread_index, float as_of) { nassertv(collector_index >= 0 && collector_index < (int)_collectors.size()); nassertv(thread_index >= 0 && thread_index < (int)_threads.size()); - if (_threads[thread_index]._is_active) { + if (_collectors[collector_index]._def->_is_active && + _threads[thread_index]._is_active) { if (_collectors[collector_index]._per_thread[thread_index]._nested_count == 0) { pstats_cat.warning() << "Collector " << get_collector_fullname(collector_index) @@ -525,8 +527,11 @@ stop(int collector_index, int thread_index, float as_of) { //////////////////////////////////////////////////////////////////// void PStatClient:: clear_level(int collector_index, int thread_index) { - _collectors[collector_index]._per_thread[thread_index]._has_level = false; - _collectors[collector_index]._per_thread[thread_index]._level = 0.0; + if (_collectors[collector_index]._def->_is_active && + _threads[thread_index]._is_active) { + _collectors[collector_index]._per_thread[thread_index]._has_level = false; + _collectors[collector_index]._per_thread[thread_index]._level = 0.0; + } } //////////////////////////////////////////////////////////////////// @@ -540,9 +545,12 @@ clear_level(int collector_index, int thread_index) { //////////////////////////////////////////////////////////////////// void PStatClient:: set_level(int collector_index, int thread_index, float level) { - level *= _collectors[collector_index]._def->_factor; - _collectors[collector_index]._per_thread[thread_index]._has_level = true; - _collectors[collector_index]._per_thread[thread_index]._level = level; + if (_collectors[collector_index]._def->_is_active && + _threads[thread_index]._is_active) { + level *= _collectors[collector_index]._def->_factor; + _collectors[collector_index]._per_thread[thread_index]._has_level = true; + _collectors[collector_index]._per_thread[thread_index]._level = level; + } } //////////////////////////////////////////////////////////////////// @@ -558,9 +566,12 @@ set_level(int collector_index, int thread_index, float level) { //////////////////////////////////////////////////////////////////// void PStatClient:: add_level(int collector_index, int thread_index, float increment) { - increment *= _collectors[collector_index]._def->_factor; - _collectors[collector_index]._per_thread[thread_index]._has_level = true; - _collectors[collector_index]._per_thread[thread_index]._level += increment; + if (_collectors[collector_index]._def->_is_active && + _threads[thread_index]._is_active) { + increment *= _collectors[collector_index]._def->_factor; + _collectors[collector_index]._per_thread[thread_index]._has_level = true; + _collectors[collector_index]._per_thread[thread_index]._level += increment; + } } //////////////////////////////////////////////////////////////////// @@ -626,23 +637,42 @@ void PStatClient:: transmit_frame_data(int thread_index) { nassertv(thread_index >= 0 && thread_index < (int)_threads.size()); if (_is_connected && _threads[thread_index]._is_active) { - - // We don't want to send too many packets in a hurry and flood the - // server. In fact, we don't want to send more than - // _max_rate packets per second, per thread. - float min_packet_delay = 1.0 / _max_rate; - float now = _clock.get_real_time(); - if (now - _threads[thread_index]._last_packet > min_packet_delay) { - nassertv(_got_udp_port); + // We don't want to send too many packets in a hurry and flood the + // server. Check that enough time has elapsed for us to send a + // new packet. If not, we'll drop this packet into the void and + // send a new one next time around. + float now = _clock.get_real_time(); + if (now >= _threads[thread_index]._next_packet) { + // We don't want to send more than _max_rate UDP-size packets + // per second, per thread. + float packet_delay = 1.0 / _max_rate; // Send new data. NetDatagram datagram; + // We always start with a zero byte, to differentiate it from a + // control message. + datagram.add_uint8(0); + datagram.add_uint16(thread_index); datagram.add_uint32(_threads[thread_index]._frame_number); _threads[thread_index]._frame_data.write_datagram(datagram); - _writer.send(datagram, _udp_connection, _server); - _threads[thread_index]._last_packet = now; + + if (_writer.is_valid_for_udp(datagram)) { + nassertv(_got_udp_port); + _writer.send(datagram, _udp_connection, _server); + + } else { + _writer.send(datagram, _tcp_connection); + // If our packets are so large that we must ship them via TCP, + // then artificially slow down the packet rate even further. + int packet_ratio = + (datagram.get_length() + maximum_udp_datagram - 1) / + maximum_udp_datagram; + packet_delay *= (float)packet_ratio; + } + + _threads[thread_index]._next_packet = now + packet_delay; } } } diff --git a/panda/src/pstatclient/pStatClient.h b/panda/src/pstatclient/pStatClient.h index 1c8461d60a..04368209b8 100644 --- a/panda/src/pstatclient/pStatClient.h +++ b/panda/src/pstatclient/pStatClient.h @@ -127,7 +127,7 @@ private: PStatFrameData _frame_data; bool _is_active; int _frame_number; - float _last_packet; + float _next_packet; }; typedef vector Threads; Threads _threads; diff --git a/panda/src/pstatclient/pStatClientControlMessage.cxx b/panda/src/pstatclient/pStatClientControlMessage.cxx index ed9bc94d08..a687206295 100644 --- a/panda/src/pstatclient/pStatClientControlMessage.cxx +++ b/panda/src/pstatclient/pStatClientControlMessage.cxx @@ -5,6 +5,7 @@ #include "config_pstats.h" #include "pStatClientControlMessage.h" +#include "pStatClientVersion.h" #include #include @@ -68,7 +69,7 @@ encode(Datagram &datagram) const { // Returns true on success, false on error. //////////////////////////////////////////////////////////////////// bool PStatClientControlMessage:: -decode(const Datagram &datagram) { +decode(const Datagram &datagram, PStatClientVersion *version) { DatagramIterator source(datagram); _type = (Type)source.get_uint8(); @@ -91,7 +92,7 @@ decode(const Datagram &datagram) { _collectors.clear(); for (int i = 0; i < num; i++) { PStatCollectorDef *def = new PStatCollectorDef; - def->read_datagram(source); + def->read_datagram(source, version); _collectors.push_back(def); } } @@ -108,6 +109,10 @@ decode(const Datagram &datagram) { } break; + case T_datagram: + // Not, strictly speaking, a control message. + return false; + default: pstats_cat.error() << "Read invalid PStatClientControlMessage type: " << (int)_type << "\n"; diff --git a/panda/src/pstatclient/pStatClientControlMessage.h b/panda/src/pstatclient/pStatClientControlMessage.h index 0109d4ca49..b52e63d110 100644 --- a/panda/src/pstatclient/pStatClientControlMessage.h +++ b/panda/src/pstatclient/pStatClientControlMessage.h @@ -13,6 +13,7 @@ #include class Datagram; +class PStatClientVersion; //////////////////////////////////////////////////////////////////// // Class : PStatClientControlMessage @@ -25,13 +26,14 @@ public: PStatClientControlMessage(); void encode(Datagram &datagram) const; - bool decode(const Datagram &datagram); + bool decode(const Datagram &datagram, PStatClientVersion *version); enum Type { - T_invalid, + T_datagram = 0, T_hello, T_define_collectors, T_define_threads, + T_invalid }; Type _type; diff --git a/panda/src/pstatclient/pStatClientVersion.I b/panda/src/pstatclient/pStatClientVersion.I new file mode 100644 index 0000000000..d52801523b --- /dev/null +++ b/panda/src/pstatclient/pStatClientVersion.I @@ -0,0 +1,49 @@ +// Filename: pStatClientVersion.I +// Created by: drose (21May01) +// +//////////////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////////////// +// Function: PStatClientVersion::get_major_version +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE int PStatClientVersion:: +get_major_version() const { + return _major_version; +} + +//////////////////////////////////////////////////////////////////// +// Function: PStatClientVersion::get_minor_version +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE int PStatClientVersion:: +get_minor_version() const { + return _minor_version; +} + +//////////////////////////////////////////////////////////////////// +// Function: PStatClientVersion::set_version +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE void PStatClientVersion:: +set_version(int major, int minor) { + _major_version = major; + _minor_version = minor; +} + +//////////////////////////////////////////////////////////////////// +// Function: PStatClientVersion::is_at_least +// Access: Public +// Description: Returns true if the client version is at least the +// indicated major/minor version number, false +// otherwise. +//////////////////////////////////////////////////////////////////// +INLINE bool PStatClientVersion:: +is_at_least(int major, int minor) const { + return (_major_version > major || + (_major_version == major && _minor_version >= minor)); +} diff --git a/panda/src/pstatclient/pStatClientVersion.cxx b/panda/src/pstatclient/pStatClientVersion.cxx new file mode 100644 index 0000000000..855896bbb3 --- /dev/null +++ b/panda/src/pstatclient/pStatClientVersion.cxx @@ -0,0 +1,19 @@ +// Filename: pStatClientVersion.cxx +// Created by: drose (21May01) +// +//////////////////////////////////////////////////////////////////// + +#include "pStatClientVersion.h" +#include "pStatProperties.h" + + +//////////////////////////////////////////////////////////////////// +// Function: PStatClientVersion::Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +PStatClientVersion:: +PStatClientVersion() { + _major_version = get_current_pstat_major_version(); + _minor_version = get_current_pstat_minor_version(); +} diff --git a/panda/src/pstatclient/pStatClientVersion.h b/panda/src/pstatclient/pStatClientVersion.h new file mode 100644 index 0000000000..e0b5f6c207 --- /dev/null +++ b/panda/src/pstatclient/pStatClientVersion.h @@ -0,0 +1,39 @@ +// Filename: pStatClientVersion.h +// Created by: drose (21May01) +// +//////////////////////////////////////////////////////////////////// + +#ifndef PSTATCLIENTVERSION_H +#define PSTATCLIENTVERSION_H + +#include + +#include +#include + +//////////////////////////////////////////////////////////////////// +// Class : PStatClientVersion +// Description : Records the version number of a particular client. +// Normally this will be the same as +// get_current_pstat_major/minor_version(). +//////////////////////////////////////////////////////////////////// +class PStatClientVersion : public ReferenceCount { +public: + PStatClientVersion(); + + INLINE int get_major_version() const; + INLINE int get_minor_version() const; + + INLINE void set_version(int major, int minor); + + INLINE bool is_at_least(int major, int minor) const; + +private: + int _major_version; + int _minor_version; +}; + +#include "pStatClientVersion.I" + +#endif + diff --git a/panda/src/pstatclient/pStatCollectorDef.cxx b/panda/src/pstatclient/pStatCollectorDef.cxx index 2bdb992ba7..20de3477fb 100644 --- a/panda/src/pstatclient/pStatCollectorDef.cxx +++ b/panda/src/pstatclient/pStatCollectorDef.cxx @@ -22,6 +22,7 @@ PStatCollectorDef() { _sort = -1; _suggested_scale = 0.0; _factor = 1.0; + _is_active = true; } //////////////////////////////////////////////////////////////////// @@ -39,6 +40,7 @@ PStatCollectorDef(int index, const string &name) : _sort = -1; _suggested_scale = 0.0; _factor = 1.0; + _is_active = true; } //////////////////////////////////////////////////////////////////// @@ -55,6 +57,7 @@ set_parent(const PStatCollectorDef &parent) { _level_units = parent._level_units; _suggested_scale = parent._suggested_scale; _factor = parent._factor; + _is_active = parent._is_active; } //////////////////////////////////////////////////////////////////// @@ -81,7 +84,7 @@ write_datagram(Datagram &destination) const { // Description: Extracts the collectorDef definition from the datagram. //////////////////////////////////////////////////////////////////// void PStatCollectorDef:: -read_datagram(DatagramIterator &source) { +read_datagram(DatagramIterator &source, PStatClientVersion *) { _index = source.get_int16(); _name = source.get_string(); _parent_index = source.get_int16(); diff --git a/panda/src/pstatclient/pStatCollectorDef.h b/panda/src/pstatclient/pStatCollectorDef.h index 94542d9467..155faab1ee 100644 --- a/panda/src/pstatclient/pStatCollectorDef.h +++ b/panda/src/pstatclient/pStatCollectorDef.h @@ -13,6 +13,7 @@ class Datagram; class DatagramIterator; class PStatClient; +class PStatClientVersion; //////////////////////////////////////////////////////////////////// // Class : PStatCollectorDef @@ -26,7 +27,7 @@ public: void set_parent(const PStatCollectorDef &parent); void write_datagram(Datagram &destination) const; - void read_datagram(DatagramIterator &source); + void read_datagram(DatagramIterator &source, PStatClientVersion *version); int _index; string _name; @@ -36,6 +37,7 @@ public: string _level_units; float _suggested_scale; float _factor; + bool _is_active; }; #endif diff --git a/panda/src/pstatclient/pStatFrameData.cxx b/panda/src/pstatclient/pStatFrameData.cxx index fd262b50b1..79a60039d5 100644 --- a/panda/src/pstatclient/pStatFrameData.cxx +++ b/panda/src/pstatclient/pStatFrameData.cxx @@ -4,6 +4,7 @@ //////////////////////////////////////////////////////////////////// #include "pStatFrameData.h" +#include "pStatClientVersion.h" #include #include @@ -35,7 +36,7 @@ write_datagram(Datagram &destination) const { // Description: Extracts the FrameData definition from the datagram. //////////////////////////////////////////////////////////////////// void PStatFrameData:: -read_datagram(DatagramIterator &source) { +read_datagram(DatagramIterator &source, PStatClientVersion *) { clear(); int i; diff --git a/panda/src/pstatclient/pStatFrameData.h b/panda/src/pstatclient/pStatFrameData.h index 5bb5022b69..9f4aedaf05 100644 --- a/panda/src/pstatclient/pStatFrameData.h +++ b/panda/src/pstatclient/pStatFrameData.h @@ -14,6 +14,7 @@ class Datagram; class DatagramIterator; +class PStatClientVersion; //////////////////////////////////////////////////////////////////// // Class : PStatFrameData @@ -47,7 +48,7 @@ public: INLINE float get_level(int n) const; void write_datagram(Datagram &destination) const; - void read_datagram(DatagramIterator &source); + void read_datagram(DatagramIterator &source, PStatClientVersion *version); private: class DataPoint { diff --git a/panda/src/pstatclient/pStatProperties.cxx b/panda/src/pstatclient/pStatProperties.cxx index a78f83b227..d2a8754b71 100644 --- a/panda/src/pstatclient/pStatProperties.cxx +++ b/panda/src/pstatclient/pStatProperties.cxx @@ -6,6 +6,14 @@ #include "pStatProperties.h" #include "pStatCollectorDef.h" #include "pStatClient.h" +#include "config_pstats.h" + +#include + +static const int current_pstat_major_version = 2; +static const int current_pstat_minor_version = 1; +// Initialized at 2.0 on 5/18/01, when version numbers were first added. +// Incremented to 2.1 on 5/21/01 to add support for TCP frame data. //////////////////////////////////////////////////////////////////// // Function: get_current_pstat_major_version @@ -19,7 +27,7 @@ //////////////////////////////////////////////////////////////////// int get_current_pstat_major_version() { - return 2; + return current_pstat_major_version; } //////////////////////////////////////////////////////////////////// @@ -34,7 +42,7 @@ get_current_pstat_major_version() { //////////////////////////////////////////////////////////////////// int get_current_pstat_minor_version() { - return 0; + return current_pstat_minor_version; } @@ -67,12 +75,14 @@ struct ColorDef { }; struct TimeCollectorProperties { + bool is_active; const char *name; ColorDef color; float suggested_scale; }; struct LevelCollectorProperties { + bool is_active; const char *name; ColorDef color; const char *units; @@ -81,57 +91,50 @@ struct LevelCollectorProperties { }; static TimeCollectorProperties time_properties[] = { - { "App", { 0.0, 1.0, 1.0 }, 1.0 / 30.0 }, - { "App:Animation", { 1.0, 0.0, 1.0 } }, - { "App:Collisions", { 1.0, 0.5, 0.0 } }, - { "App:Data graph", { 0.5, 0.8, 0.4 } }, - { "App:Show code", { 0.8, 0.2, 1.0 } }, - { "Cull", { 0.0, 1.0, 0.0 }, 1.0 / 30.0 }, - { "Draw", { 1.0, 0.0, 0.0 }, 1.0 / 30.0 }, - { "Draw:Swap buffers", { 0.5, 1.0, 0.8 } }, - { "Draw:Clear", { 0.5, 0.7, 0.7 } }, - { "Draw:Show fps", { 0.5, 0.8, 1.0 } }, - { "Draw:Make current", { 1.0, 0.6, 0.3 } }, - { NULL } + { 1, "App", { 0.0, 1.0, 1.0 }, 1.0 / 30.0 }, + { 1, "App:Animation", { 1.0, 0.0, 1.0 } }, + { 1, "App:Collisions", { 1.0, 0.5, 0.0 } }, + { 1, "App:Data graph", { 0.5, 0.8, 0.4 } }, + { 1, "App:Show code", { 0.8, 0.2, 1.0 } }, + { 1, "Cull", { 0.0, 1.0, 0.0 }, 1.0 / 30.0 }, + { 1, "Draw", { 1.0, 0.0, 0.0 }, 1.0 / 30.0 }, + { 1, "Draw:Swap buffers", { 0.5, 1.0, 0.8 } }, + { 1, "Draw:Clear", { 0.5, 0.7, 0.7 } }, + { 1, "Draw:Show fps", { 0.5, 0.8, 1.0 } }, + { 1, "Draw:Make current", { 1.0, 0.6, 0.3 } }, + { 0, "WRT", { 0.0, 0.0, 1.0 } }, + { 0, "WRT:Subtree", { 0.3, 1.0, 0.3 } }, + { 0, NULL } }; static LevelCollectorProperties level_properties[] = { - { "Texture usage", { 1.0, 0.0, 0.0 }, "MB", 12, 1048576 }, - { "Texture usage:Active", { 1.0, 1.0, 0.0 } }, - { "Texture memory", { 0.0, 0.0, 1.0 }, "MB", 12, 1048576 }, - { "Texture memory:In use", { 0.0, 1.0, 1.0 } }, - { "Vertices", { 0.5, 0.2, 0.0 }, "K", 10, 1000 }, - { "Vertices:Other", { 0.2, 0.2, 0.2 } }, - { "Vertices:Triangles", { 0.8, 0.8, 0.8 } }, - { "Vertices:Triangle fans", { 0.8, 0.5, 0.2 } }, - { "Vertices:Triangle strips", { 0.2, 0.5, 0.8 } }, - { "Nodes", { 0.4, 0.2, 0.8 }, "", 500.0 }, - { "Nodes:GeomNodes", { 0.8, 0.2, 0.0 } }, - { "State changes", { 1.0, 0.5, 0.2 }, "", 500.0 }, - { "State changes:Transforms", { 0.2, 0.2, 0.8 }, }, - { "State changes:Textures", { 0.8, 0.2, 0.2 }, }, - { NULL } + { 1, "Texture usage", { 1.0, 0.0, 0.0 }, "MB", 12, 1048576 }, + { 1, "Texture usage:Active", { 1.0, 1.0, 0.0 } }, + { 1, "Texture memory", { 0.0, 0.0, 1.0 }, "MB", 12, 1048576 }, + { 1, "Texture memory:In use", { 0.0, 1.0, 1.0 } }, + { 1, "Vertices", { 0.5, 0.2, 0.0 }, "K", 10, 1000 }, + { 1, "Vertices:Other", { 0.2, 0.2, 0.2 } }, + { 1, "Vertices:Triangles", { 0.8, 0.8, 0.8 } }, + { 1, "Vertices:Triangle fans", { 0.8, 0.5, 0.2 } }, + { 1, "Vertices:Triangle strips", { 0.2, 0.5, 0.8 } }, + { 1, "Nodes", { 0.4, 0.2, 0.8 }, "", 500.0 }, + { 1, "Nodes:GeomNodes", { 0.8, 0.2, 0.0 } }, + { 1, "State changes", { 1.0, 0.5, 0.2 }, "", 500.0 }, + { 1, "State changes:Transforms", { 0.2, 0.2, 0.8 }, }, + { 1, "State changes:Textures", { 0.8, 0.2, 0.2 }, }, + { 0, NULL } }; //////////////////////////////////////////////////////////////////// -// Function: initialize_collector_def -// Description: This is the only accessor function into this table. -// The PStatCollectorDef constructor calls it when a new -// PStatCollectorDef is created. It should look up in -// the table and find a matching definition for this def -// by name; if one is found, the properties are applied. +// Function: initialize_collector_def_from_table +// Description: Looks up the collector in the compiled-in table +// defined above, and sets its properties appropriately +// if it is found. //////////////////////////////////////////////////////////////////// -void -initialize_collector_def(PStatClient *client, PStatCollectorDef *def) { +static void +initialize_collector_def_from_table(const string &fullname, PStatCollectorDef *def) { int i; - string fullname; - - if (def->_index == 0) { - fullname = def->_name; - } else { - fullname = client->get_collector_fullname(def->_index); - } for (i = 0; time_properties[i].name != (const char *)NULL; @@ -139,6 +142,7 @@ initialize_collector_def(PStatClient *client, PStatCollectorDef *def) { const TimeCollectorProperties &tp = time_properties[i]; if (fullname == tp.name) { def->_sort = i; + def->_is_active = tp.is_active; def->_suggested_color.set(tp.color.r, tp.color.g, tp.color.b); if (tp.suggested_scale != 0.0) { def->_suggested_scale = tp.suggested_scale; @@ -153,6 +157,7 @@ initialize_collector_def(PStatClient *client, PStatCollectorDef *def) { const LevelCollectorProperties &lp = level_properties[i]; if (fullname == lp.name) { def->_sort = i; + def->_is_active = lp.is_active; def->_suggested_color.set(lp.color.r, lp.color.g, lp.color.b); if (lp.suggested_scale != 0.0) { def->_suggested_scale = lp.suggested_scale; @@ -168,4 +173,87 @@ initialize_collector_def(PStatClient *client, PStatCollectorDef *def) { } } + +//////////////////////////////////////////////////////////////////// +// Function: initialize_collector_def +// Description: This is the only accessor function into this table. +// The PStatCollectorDef constructor calls it when a new +// PStatCollectorDef is created. It should look up in +// the table and find a matching definition for this def +// by name; if one is found, the properties are applied. +//////////////////////////////////////////////////////////////////// +void +initialize_collector_def(PStatClient *client, PStatCollectorDef *def) { + string fullname; + + if (def->_index == 0) { + fullname = def->_name; + } else { + fullname = client->get_collector_fullname(def->_index); + } + + // First, check the compiled-in defaults. + initialize_collector_def_from_table(fullname, def); + + // Then, look to Config for more advice. To do this, we first + // change the name to something more like a Config variable name. + // We replace colons and spaces with hyphens, eliminate other + // punctuation, and make all letters lowercase. + + string config_name; + string::const_iterator ni; + for (ni = fullname.begin(); ni != fullname.end(); ++ni) { + switch (*ni) { + case ':': + case ' ': + case '\n': + case '\r': + case '\t': + config_name += '-'; + break; + + default: + if (isalnum(*ni)) { + config_name += tolower(*ni); + } + } + } + + def->_is_active = + config_pstats.GetBool("pstats-active-" + config_name, def->_is_active); + def->_sort = + config_pstats.GetInt("pstats-sort-" + config_name, def->_sort); + def->_suggested_scale = + config_pstats.GetFloat("pstats-scale-" + config_name, def->_suggested_scale); + def->_level_units = + config_pstats.GetString("pstats-units-" + config_name, def->_level_units); + def->_level_units = + config_pstats.GetString("pstats-units-" + config_name, def->_level_units); + if (!config_pstats.GetString("pstats-factor-" + config_name, "").empty()) { + def->_factor = + 1.0/config_pstats.GetFloat("pstats-factor-" + config_name, 1.0); + } + + // Get and decode the color string. We allow any three + // floating-point numbers, with any kind of non-digit characters + // between them. + string color_str = + config_pstats.GetString("pstats-color-" + config_name, ""); + if (!color_str.empty()) { + const char *cstr = color_str.c_str(); + const char *p = cstr; + + int i = 0; + while (i < 3 && *p != '\0') { + while (*p != '\0' && !(isdigit(*p) || *p == '.')) { + p++; + } + char *q; + def->_suggested_color[i] = strtod(p, &q); + p = q; + i++; + } + } +} + #endif // DO_PSTATS diff --git a/pandatool/src/pstatserver/pStatClientData.h b/pandatool/src/pstatserver/pStatClientData.h index aedf9ddf29..f567445711 100644 --- a/pandatool/src/pstatserver/pStatClientData.h +++ b/pandatool/src/pstatserver/pStatClientData.h @@ -10,6 +10,7 @@ #include "pStatThreadData.h" +#include #include #include @@ -23,7 +24,7 @@ class PStatReader; // with any one particular frame or thread: the list of // collectors and threads, for instance. //////////////////////////////////////////////////////////////////// -class PStatClientData : public ReferenceCount { +class PStatClientData : public PStatClientVersion { public: PStatClientData(PStatReader *reader); ~PStatClientData(); diff --git a/pandatool/src/pstatserver/pStatReader.cxx b/pandatool/src/pstatserver/pStatReader.cxx index 63492bd1e6..12cc8ae3ec 100644 --- a/pandatool/src/pstatserver/pStatReader.cxx +++ b/pandatool/src/pstatserver/pStatReader.cxx @@ -158,8 +158,12 @@ receive_datagram(const NetDatagram &datagram) { if (connection == _tcp_connection) { PStatClientControlMessage message; - if (message.decode(datagram)) { + if (message.decode(datagram, _client_data)) { handle_client_control_message(message); + + } else if (message._type == PStatClientControlMessage::T_datagram) { + handle_client_udp_data(datagram); + } else { nout << "Got unexpected message from client.\n"; } @@ -183,15 +187,16 @@ handle_client_control_message(const PStatClientControlMessage &message) { switch (message._type) { case PStatClientControlMessage::T_hello: { - int current_major_version = get_current_pstat_major_version(); - int current_minor_version = get_current_pstat_minor_version(); + _client_data->set_version(message._major_version, message._minor_version); + int server_major_version = get_current_pstat_major_version(); + int server_minor_version = get_current_pstat_minor_version(); - if (message._major_version != current_major_version || - (message._major_version == current_major_version && - message._minor_version > current_minor_version)) { + if (message._major_version != server_major_version || + (message._major_version == server_major_version && + message._minor_version > server_minor_version)) { _monitor->bad_version(message._client_hostname, message._client_progname, message._major_version, message._minor_version, - current_major_version, current_minor_version); + server_major_version, server_minor_version); _monitor->close(); } else { _monitor->hello_from(message._client_hostname, message._client_progname); @@ -233,12 +238,26 @@ handle_client_control_message(const PStatClientControlMessage &message) { //////////////////////////////////////////////////////////////////// void PStatReader:: handle_client_udp_data(const Datagram &datagram) { + if (!_monitor->is_client_known()) { + // If we haven't heard a "hello" from the client yet, we don't + // know what version data it will be sending us, so we can't + // decode the data. Chances are good we can't display it sensibly + // yet anyway. Ignore frame data until we get that hello. + return; + } + DatagramIterator source(datagram); + if (_client_data->is_at_least(2, 1)) { + // Throw away the zero byte at the beginning. + int initial_byte = source.get_uint8(); + nassertv(initial_byte == 0); + } + int thread_index = source.get_uint16(); int frame_number = source.get_uint32(); PStatFrameData *frame_data = new PStatFrameData; - frame_data->read_datagram(source); + frame_data->read_datagram(source, _client_data); // Check to see if any new collectors have level data. int num_levels = frame_data->get_num_levels();