Update StatsReport and by extension StatsCollector to reduce data copying.
Summary of changes:
* We're now using an enum for types instead of strings which both eliminates unecessary string creations+copies and further restricts the type to a known set at compile time.
* IDs are now a separate type instead of a string, copying of Values is not possible and values are const to allow grabbing references outside of the statscollector.
* StatsReport member variables are no longer public.
* Consolidated code in StatsCollector (e.g. merged PrepareLocalReport and PrepareRemoteReport).
* Refactored methods that forced copies of string (e.g. ExtractValueFromReport).
* More asserts for thread correctness.
* Using std::list for the StatsSet instead of a set since order is not important and updates are more efficient in list<>.
BUG=2822
R=hta@webrtc.org, perkj@webrtc.org
Review URL: https://webrtc-codereview.appspot.com/40439004
git-svn-id: http://webrtc.googlecode.com/svn/trunk@8110 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/talk/app/webrtc/statstypes.h b/talk/app/webrtc/statstypes.h
index 2bc0f33..8f132db 100644
--- a/talk/app/webrtc/statstypes.h
+++ b/talk/app/webrtc/statstypes.h
@@ -32,11 +32,13 @@
#define TALK_APP_WEBRTC_STATSTYPES_H_
#include <algorithm>
-#include <set>
+#include <list>
#include <string>
#include <vector>
#include "webrtc/base/basictypes.h"
+#include "webrtc/base/linked_ptr.h"
+#include "webrtc/base/scoped_ptr.h"
#include "webrtc/base/common.h"
#include "webrtc/base/linked_ptr.h"
#include "webrtc/base/scoped_ptr.h"
@@ -46,35 +48,71 @@
class StatsReport {
public:
- // TODO(tommi): Remove this ctor after removing reliance upon it in Chromium
- // (mock_peer_connection_impl.cc).
- StatsReport() : timestamp_(0) {}
+ // Indicates whether a track is for sending or receiving.
+ // Used in reports for audio/video tracks.
+ enum Direction {
+ kSend = 0,
+ kReceive,
+ };
- // TODO(tommi): Make protected and disallow copy completely once not needed.
- StatsReport(const StatsReport& src);
+ enum StatsType {
+ // StatsReport types.
+ // A StatsReport of |type| = "googSession" contains overall information
+ // about the thing libjingle calls a session (which may contain one
+ // or more RTP sessions.
+ kStatsReportTypeSession,
- // Constructor is protected to force use of StatsSet.
- // TODO(tommi): Make this ctor protected.
- explicit StatsReport(const std::string& id);
+ // A StatsReport of |type| = "googTransport" contains information
+ // about a libjingle "transport".
+ kStatsReportTypeTransport,
- // TODO(tommi): Make this protected.
- StatsReport& operator=(const StatsReport& src);
+ // A StatsReport of |type| = "googComponent" contains information
+ // about a libjingle "channel" (typically, RTP or RTCP for a transport).
+ // This is intended to be the same thing as an ICE "Component".
+ kStatsReportTypeComponent,
- // Operators provided for STL container/algorithm support.
- bool operator<(const StatsReport& other) const;
- bool operator==(const StatsReport& other) const;
- // Special support for being able to use std::find on a container
- // without requiring a new StatsReport instance.
- bool operator==(const std::string& other_id) const;
+ // A StatsReport of |type| = "googCandidatePair" contains information
+ // about a libjingle "connection" - a single source/destination port pair.
+ // This is intended to be the same thing as an ICE "candidate pair".
+ kStatsReportTypeCandidatePair,
- // The unique identifier for this object.
- // This is used as a key for this report in ordered containers,
- // so it must never be changed.
- // TODO(tommi): Make this member variable const.
- std::string id_; // See below for contents.
- std::string type; // See below for contents.
+ // A StatsReport of |type| = "VideoBWE" is statistics for video Bandwidth
+ // Estimation, which is global per-session. The |id| field is "bweforvideo"
+ // (will probably change in the future).
+ kStatsReportTypeBwe,
- // StatsValue names.
+ // A StatsReport of |type| = "ssrc" is statistics for a specific rtp stream.
+ // The |id| field is the SSRC in decimal form of the rtp stream.
+ kStatsReportTypeSsrc,
+
+ // A StatsReport of |type| = "remoteSsrc" is statistics for a specific
+ // rtp stream, generated by the remote end of the connection.
+ kStatsReportTypeRemoteSsrc,
+
+ // A StatsReport of |type| = "googTrack" is statistics for a specific media
+ // track. The |id| field is the track id.
+ kStatsReportTypeTrack,
+
+ // A StatsReport of |type| = "localcandidate" or "remotecandidate" is
+ // attributes on a specific ICE Candidate. It links to its connection pair
+ // by candidate id. The string value is taken from
+ // http://w3c.github.io/webrtc-stats/#rtcstatstype-enum*.
+ kStatsReportTypeIceLocalCandidate,
+ kStatsReportTypeIceRemoteCandidate,
+
+ // A StatsReport of |type| = "googCertificate" contains an SSL certificate
+ // transmitted by one of the endpoints of this connection. The |id| is
+ // controlled by the fingerprint, and is used to identify the certificate in
+ // the Channel stats (as "googLocalCertificateId" or
+ // "googRemoteCertificateId") and in any child certificates (as
+ // "googIssuerId").
+ kStatsReportTypeCertificate,
+
+ // A StatsReport of |type| = "datachannel" with statistics for a
+ // particular DataChannel.
+ kStatsReportTypeDataChannel,
+ };
+
enum StatsValueName {
kStatsValueNameActiveConnection,
kStatsValueNameAudioInputLevel,
@@ -183,40 +221,54 @@
class Id {
public:
- Id(const std::string& id) : id_(id) {}
- Id(const Id& id) : id_(id.id_) {}
- const std::string& ToString() const { return id_; }
- private:
- const std::string id_;
+ virtual ~Id();
+ StatsType type() const;
+ virtual bool Equals(const Id& other) const;
+ virtual std::string ToString() const = 0;
+
+ protected:
+ Id(StatsType type); // Only meant for derived classes.
+ const StatsType type_;
};
struct Value {
- // The copy ctor can't be declared as explicit due to problems with STL.
- Value(const Value& other);
- explicit Value(StatsValueName name);
Value(StatsValueName name, const std::string& value);
- // TODO(tommi): Remove this operator once we don't need it.
- // The operator is provided for compatibility with STL containers.
- // The public |name| member variable is otherwise meant to be read-only.
- Value& operator=(const Value& other);
-
// Returns the string representation of |name|.
const char* display_name() const;
const StatsValueName name;
+ // TODO(tommi): Support more value types than string.
+ const std::string value;
- std::string value;
+ private:
+ DISALLOW_COPY_AND_ASSIGN(Value);
};
typedef rtc::linked_ptr<Value> ValuePtr;
typedef std::vector<ValuePtr> Values;
- typedef const char* StatsType;
// Ownership of |id| is passed to |this|.
explicit StatsReport(rtc::scoped_ptr<Id> id);
+ // Factory functions for various types of stats IDs.
+ static rtc::scoped_ptr<Id> NewBandwidthEstimationId();
static rtc::scoped_ptr<Id> NewTypedId(StatsType type, const std::string& id);
+ static rtc::scoped_ptr<Id> NewIdWithDirection(
+ StatsType type, const std::string& id, Direction direction);
+ static rtc::scoped_ptr<Id> NewCandidateId(bool local, const std::string& id);
+ static rtc::scoped_ptr<Id> NewComponentId(
+ const std::string& content_name, int component);
+ static rtc::scoped_ptr<Id> NewCandidatePairId(
+ const std::string& content_name, int component, int index);
+
+ const Id& id() const { return *id_.get(); }
+ StatsType type() const { return id_->type(); }
+ double timestamp() const { return timestamp_; }
+ void set_timestamp(double t) { timestamp_ = t; }
+ const Values& values() const { return values_; }
+
+ const char* TypeToString() const;
void AddValue(StatsValueName name, const std::string& value);
void AddValue(StatsValueName name, int64 value);
@@ -228,122 +280,55 @@
void ResetValues();
- const Id id() const { return Id(id_); }
- double timestamp() const { return timestamp_; }
- void set_timestamp(double t) { timestamp_ = t; }
- const Values& values() const { return values_; }
+ const Value* FindValue(StatsValueName name) const;
- const char* TypeToString() const { return type.c_str(); }
-
+ private:
+ // The unique identifier for this object.
+ // This is used as a key for this report in ordered containers,
+ // so it must never be changed.
+ const rtc::scoped_ptr<Id> id_;
double timestamp_; // Time since 1970-01-01T00:00:00Z in milliseconds.
Values values_;
- // TODO(tommi): These should all be enum values.
-
- // StatsReport types.
- // A StatsReport of |type| = "googSession" contains overall information
- // about the thing libjingle calls a session (which may contain one
- // or more RTP sessions.
- static const char kStatsReportTypeSession[];
-
- // A StatsReport of |type| = "googTransport" contains information
- // about a libjingle "transport".
- static const char kStatsReportTypeTransport[];
-
- // A StatsReport of |type| = "googComponent" contains information
- // about a libjingle "channel" (typically, RTP or RTCP for a transport).
- // This is intended to be the same thing as an ICE "Component".
- static const char kStatsReportTypeComponent[];
-
- // A StatsReport of |type| = "googCandidatePair" contains information
- // about a libjingle "connection" - a single source/destination port pair.
- // This is intended to be the same thing as an ICE "candidate pair".
- static const char kStatsReportTypeCandidatePair[];
-
- // StatsReport of |type| = "VideoBWE" is statistics for video Bandwidth
- // Estimation, which is global per-session. The |id| field is "bweforvideo"
- // (will probably change in the future).
- static const char kStatsReportTypeBwe[];
-
- // StatsReport of |type| = "ssrc" is statistics for a specific rtp stream.
- // The |id| field is the SSRC in decimal form of the rtp stream.
- static const char kStatsReportTypeSsrc[];
-
- // StatsReport of |type| = "remoteSsrc" is statistics for a specific
- // rtp stream, generated by the remote end of the connection.
- static const char kStatsReportTypeRemoteSsrc[];
-
- // StatsReport of |type| = "googTrack" is statistics for a specific media
- // track. The |id| field is the track id.
- static const char kStatsReportTypeTrack[];
-
- // StatsReport of |type| = "localcandidate" or "remotecandidate" is attributes
- // on a specific ICE Candidate. It links to its connection pair by candidate
- // id. The string value is taken from
- // http://w3c.github.io/webrtc-stats/#rtcstatstype-enum*.
- static const char kStatsReportTypeIceLocalCandidate[];
- static const char kStatsReportTypeIceRemoteCandidate[];
-
- // A StatsReport of |type| = "googCertificate" contains an SSL certificate
- // transmitted by one of the endpoints of this connection. The |id| is
- // controlled by the fingerprint, and is used to identify the certificate in
- // the Channel stats (as "googLocalCertificateId" or
- // "googRemoteCertificateId") and in any child certificates (as
- // "googIssuerId").
- static const char kStatsReportTypeCertificate[];
-
- // The id of StatsReport of type VideoBWE.
- static const char kStatsReportVideoBweId[];
-
- // A StatsReport of |type| = "datachannel" with statistics for a
- // particular DataChannel.
- static const char kStatsReportTypeDataChannel[];
-};
-
-// This class is provided for the cases where we need to keep
-// snapshots of reports around. This is an edge case.
-// TODO(tommi): Move into the private section of StatsSet.
-class StatsReportCopyable : public StatsReport {
- public:
- StatsReportCopyable(const std::string& id) : StatsReport(id) {}
- explicit StatsReportCopyable(const StatsReport& src)
- : StatsReport(src) {}
-
- using StatsReport::operator=;
+ DISALLOW_COPY_AND_ASSIGN(StatsReport);
};
// Typedef for an array of const StatsReport pointers.
// Ownership of the pointers held by this implementation is assumed to lie
// elsewhere and lifetime guarantees are made by the implementation that uses
-// this type. In the StatsCollector, object ownership lies with the StatsSet
-// class.
+// this type. In the StatsCollector, object ownership lies with the
+// StatsCollection class.
typedef std::vector<const StatsReport*> StatsReports;
// A map from the report id to the report.
// This class wraps an STL container and provides a limited set of
// functionality in order to keep things simple.
// TODO(tommi): Use a thread checker here (currently not in libjingle).
-class StatsSet {
+class StatsCollection {
public:
- StatsSet();
- ~StatsSet();
+ StatsCollection();
+ ~StatsCollection();
- typedef std::set<StatsReportCopyable> Container;
+ // TODO(tommi): shared_ptr (or linked_ptr)?
+ typedef std::list<StatsReport*> Container;
typedef Container::iterator iterator;
typedef Container::const_iterator const_iterator;
const_iterator begin() const;
const_iterator end() const;
+ size_t size() const;
// Creates a new report object with |id| that does not already
// exist in the list of reports.
- StatsReport* InsertNew(const std::string& id);
- StatsReport* FindOrAddNew(const std::string& id);
- StatsReport* ReplaceOrAddNew(const std::string& id);
+ StatsReport* InsertNew(rtc::scoped_ptr<StatsReport::Id> id);
+ StatsReport* FindOrAddNew(rtc::scoped_ptr<StatsReport::Id> id);
+ StatsReport* ReplaceOrAddNew(rtc::scoped_ptr<StatsReport::Id> id);
// Looks for a report with the given |id|. If one is not found, NULL
// will be returned.
- StatsReport* Find(const std::string& id);
+ StatsReport* Find(const StatsReport::Id& id);
+ // TODO(tommi): we should only need one of these.
+ StatsReport* Find(const rtc::scoped_ptr<StatsReport::Id>& id);
private:
Container list_;