diff options
author | hclam@google.com <hclam@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-04-05 18:03:31 +0000 |
---|---|---|
committer | hclam@google.com <hclam@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-04-05 18:03:31 +0000 |
commit | 778d599df45c985286cd70898187ecf7a6284eeb (patch) | |
tree | e4518f5d17d84f6613e0507c1dddc05ab1ddf23b /remoting | |
parent | 6ca1745021ac1b7822eb23a58c3985b2a91b293d (diff) | |
download | chromium_src-778d599df45c985286cd70898187ecf7a6284eeb.zip chromium_src-778d599df45c985286cd70898187ecf7a6284eeb.tar.gz chromium_src-778d599df45c985286cd70898187ecf7a6284eeb.tar.bz2 |
Measure bandwidth for chromoting video channel
Define RunningAverage, TimedRunningAverage and use that to record
video bandwidth.
This doesn't account for overhead of protobuf envelop. However the number
should be small that can be ignored.
BUG=None
TEST=None
Review URL: http://codereview.chromium.org/6736009
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@80486 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'remoting')
-rw-r--r-- | remoting/base/rate_counter.cc | 49 | ||||
-rw-r--r-- | remoting/base/rate_counter.h | 61 | ||||
-rw-r--r-- | remoting/base/running_average.cc | 39 | ||||
-rw-r--r-- | remoting/base/running_average.h | 57 | ||||
-rw-r--r-- | remoting/client/chromoting_client.cc | 7 | ||||
-rw-r--r-- | remoting/client/chromoting_client.h | 13 | ||||
-rw-r--r-- | remoting/client/chromoting_stats.cc | 20 | ||||
-rw-r--r-- | remoting/client/chromoting_stats.h | 29 | ||||
-rw-r--r-- | remoting/client/plugin/chromoting_instance.cc | 4 | ||||
-rw-r--r-- | remoting/client/plugin/chromoting_instance.h | 4 | ||||
-rw-r--r-- | remoting/client/plugin/chromoting_scriptable_object.cc | 11 | ||||
-rw-r--r-- | remoting/client/plugin/chromoting_scriptable_object.h | 5 | ||||
-rw-r--r-- | remoting/remoting.gyp | 6 |
13 files changed, 302 insertions, 3 deletions
diff --git a/remoting/base/rate_counter.cc b/remoting/base/rate_counter.cc new file mode 100644 index 0000000..fff9b6c --- /dev/null +++ b/remoting/base/rate_counter.cc @@ -0,0 +1,49 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "remoting/base/rate_counter.h" + +namespace remoting { + +RateCounter::RateCounter(base::TimeDelta time_window) + : time_window_(time_window), + sum_(0) { +} + +RateCounter::~RateCounter() { +} + +void RateCounter::Record(int64 value) { + base::Time current_time = base::Time::Now(); + Evict(current_time); + + base::AutoLock auto_lock(lock_); + sum_ += value; + data_points_.push(std::make_pair(current_time, value)); +} + +double RateCounter::Rate() { + Evict(base::Time::Now()); + + base::AutoLock auto_lock(lock_); + return static_cast<double>(base::Time::kMillisecondsPerSecond) * sum_ / + time_window_.InMilliseconds(); +} + +void RateCounter::Evict(base::Time current_time) { + base::AutoLock auto_lock(lock_); + + // Remove data points outside of the window. + base::Time window_start = current_time - time_window_; + + while (!data_points_.empty()) { + if (data_points_.front().first > window_start) + break; + + sum_ -= data_points_.front().second; + data_points_.pop(); + } +} + +} // namespace remoting diff --git a/remoting/base/rate_counter.h b/remoting/base/rate_counter.h new file mode 100644 index 0000000..c427b96 --- /dev/null +++ b/remoting/base/rate_counter.h @@ -0,0 +1,61 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// RateCounter is defined to measure average rate over a given time window. +// Rate is reported as the sum of values recorded divided by the time window. +// This can be used for measuring bandwidth, bitrate, etc. + +// This class is thread-safe. + +#ifndef REMOTING_BASE_RATE_COUNTER_H_ +#define REMOTING_BASE_RATE_COUNTER_H_ + +#include <queue> +#include <utility> + +#include "base/basictypes.h" +#include "base/synchronization/lock.h" +#include "base/time.h" + +namespace remoting { + +class RateCounter { + public: + // Construct a counter for a specific time window. + RateCounter(base::TimeDelta time_window); + + virtual ~RateCounter(); + + // Record the data point. + void Record(int64 value); + + // Report the rate recorded. At the beginning of recording the numbers before + // |time_window| is reached the reported rate will not be accurate. + double Rate(); + + private: + // Helper function to evict old data points. + void Evict(base::Time current_time); + + // A data point consists of a timestamp and a data value. + typedef std::pair<base::Time, int64> DataPoint; + + // Duration of the time window. + base::TimeDelta time_window_; + + // Protects |data_points_| and |sum_|. + base::Lock lock_; + + // Keep the values of all the data points in a queue. + std::queue<DataPoint> data_points_; + + // Sum of values in |data_points_|. + int64 sum_; + + DISALLOW_COPY_AND_ASSIGN(RateCounter); +}; + +} // namespace remoting + +#endif // REMOTING_BASE_RATE_COUNTER_H_ diff --git a/remoting/base/running_average.cc b/remoting/base/running_average.cc new file mode 100644 index 0000000..4daa650 --- /dev/null +++ b/remoting/base/running_average.cc @@ -0,0 +1,39 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/logging.h" +#include "remoting/base/running_average.h" + +namespace remoting { + +RunningAverage::RunningAverage(int window_size) + : window_size_(window_size), + sum_(0) { + CHECK(window_size_); +} + +RunningAverage::~RunningAverage() { +} + +void RunningAverage::Record(int64 value) { + base::AutoLock auto_lock(lock_); + + data_points_.push_back(value); + sum_ += value; + + if (data_points_.size() > window_size_) { + sum_ -= data_points_[0]; + data_points_.pop_front(); + } +} + +double RunningAverage::Average() { + base::AutoLock auto_lock(lock_); + + if (data_points_.empty()) + return 0; + return static_cast<double>(sum_) / data_points_.size(); +} + +} // namespace remoting diff --git a/remoting/base/running_average.h b/remoting/base/running_average.h new file mode 100644 index 0000000..fadea1f --- /dev/null +++ b/remoting/base/running_average.h @@ -0,0 +1,57 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// RunningAverage defined in this file is used to generate statistics for +// bandwidth, latency and other performance metrics for remoting. Usually +// this data comes in as a stream and fluctuates a lot. They are processed by +// this class to generate a more stable value by taking average within a +// window of data points. + +// All classes defined are thread-safe. + +#ifndef REMOTING_BASE_RUNNING_AVERAGE_H_ +#define REMOTING_BASE_RUNNING_AVERAGE_H_ + +#include <deque> + +#include "base/basictypes.h" +#include "base/synchronization/lock.h" +#include "base/time.h" + +namespace remoting { + +class RunningAverage { + public: + // Construct a running average counter for a specific window size. The + // |windows_size| most recent values are kept and the average is reported. + RunningAverage(int window_size); + + virtual ~RunningAverage(); + + // Record the provided data point. + void Record(int64 value); + + // Return the average of data points in the last window. + double Average(); + + private: + // Size of the window. This is of type size_t to avoid casting when comparing + // with the size of |data_points_|. + size_t window_size_; + + // Protects |data_points_| and |sum_|. + base::Lock lock_; + + // Keep the values of all the data points. + std::deque<int64> data_points_; + + // Sum of values in |data_points_|. + int64 sum_; + + DISALLOW_COPY_AND_ASSIGN(RunningAverage); +}; + +} // namespace remoting + +#endif // REMOTING_BASE_RUNNING_AVERAGE_H_ diff --git a/remoting/client/chromoting_client.cc b/remoting/client/chromoting_client.cc index aee6df4..bf1ad39 100644 --- a/remoting/client/chromoting_client.cc +++ b/remoting/client/chromoting_client.cc @@ -92,6 +92,10 @@ void ChromotingClient::ClientDone() { } } +ChromotingStats* ChromotingClient::GetStats() { + return &stats_; +} + void ChromotingClient::Repaint() { if (message_loop() != MessageLoop::current()) { message_loop()->PostTask( @@ -125,6 +129,9 @@ void ChromotingClient::ProcessVideoPacket(const VideoPacket* packet, return; } + // Record size of the packet for statistics. + stats_.video_bandwidth()->Record(packet->data().size()); + received_packets_.push_back(QueuedVideoPacket(packet, done)); if (!packet_being_processed_) DispatchPacket(); diff --git a/remoting/client/chromoting_client.h b/remoting/client/chromoting_client.h index 83702db..f936ddb 100644 --- a/remoting/client/chromoting_client.h +++ b/remoting/client/chromoting_client.h @@ -4,13 +4,14 @@ // ChromotingClient is the controller for the Client implementation. -#ifndef REMOTING_CLIENT_CHROMOTING_CLIENT_H -#define REMOTING_CLIENT_CHROMOTING_CLIENT_H +#ifndef REMOTING_CLIENT_CHROMOTING_CLIENT_H_ +#define REMOTING_CLIENT_CHROMOTING_CLIENT_H_ #include <list> #include "base/task.h" #include "remoting/client/client_config.h" +#include "remoting/client/chromoting_stats.h" #include "remoting/client/chromoting_view.h" #include "remoting/protocol/client_stub.h" #include "remoting/protocol/connection_to_host.h" @@ -53,6 +54,9 @@ class ChromotingClient : public protocol::ConnectionToHost::HostEventCallback, void Stop(); void ClientDone(); + // Return the stats recorded by this client. + ChromotingStats* GetStats(); + // Signals that the associated view may need updating. virtual void Repaint(); @@ -125,6 +129,9 @@ class ChromotingClient : public protocol::ConnectionToHost::HostEventCallback, // safe to dispatch another message. bool packet_being_processed_; + // Record the statistics of the connection. + ChromotingStats stats_; + DISALLOW_COPY_AND_ASSIGN(ChromotingClient); }; @@ -132,4 +139,4 @@ class ChromotingClient : public protocol::ConnectionToHost::HostEventCallback, DISABLE_RUNNABLE_METHOD_REFCOUNT(remoting::ChromotingClient); -#endif // REMOTING_CLIENT_CHROMOTING_CLIENT_H +#endif // REMOTING_CLIENT_CHROMOTING_CLIENT_H_ diff --git a/remoting/client/chromoting_stats.cc b/remoting/client/chromoting_stats.cc new file mode 100644 index 0000000..33f10173bf --- /dev/null +++ b/remoting/client/chromoting_stats.cc @@ -0,0 +1,20 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "remoting/client/chromoting_stats.h" + +namespace { + +// The default window of bandwidth in seconds. +static const int kBandwidthWindow = 3; + +} // namespace + +namespace remoting { + +ChromotingStats::ChromotingStats() + : video_bandwidth_(base::TimeDelta::FromSeconds(kBandwidthWindow)) { +} + +} // namespace remoting diff --git a/remoting/client/chromoting_stats.h b/remoting/client/chromoting_stats.h new file mode 100644 index 0000000..171c46e --- /dev/null +++ b/remoting/client/chromoting_stats.h @@ -0,0 +1,29 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// ChromotingStats defines a bundle of performance counters and statistics +// for chromoting. + +#ifndef REMOTING_CLIENT_CHROMOTING_STATS_H_ +#define REMOTING_CLIENT_CHROMOTING_STATS_H_ + +#include "remoting/base/rate_counter.h" + +namespace remoting { + +class ChromotingStats { + public: + ChromotingStats(); + + RateCounter* video_bandwidth() { return &video_bandwidth_; } + + private: + RateCounter video_bandwidth_; + + DISALLOW_COPY_AND_ASSIGN(ChromotingStats); +}; + +} // namespace remoting + +#endif // REMOTING_CLIENT_CHROMOTING_STATS_H_ diff --git a/remoting/client/plugin/chromoting_instance.cc b/remoting/client/plugin/chromoting_instance.cc index 45497c5..a23598c 100644 --- a/remoting/client/plugin/chromoting_instance.cc +++ b/remoting/client/plugin/chromoting_instance.cc @@ -277,4 +277,8 @@ pp::Var ChromotingInstance::GetInstanceObject() { return instance_object_; } +ChromotingStats* ChromotingInstance::GetStats() { + return client_->GetStats(); +} + } // namespace remoting diff --git a/remoting/client/plugin/chromoting_instance.h b/remoting/client/plugin/chromoting_instance.h index 44c4c18..8c5aee8 100644 --- a/remoting/client/plugin/chromoting_instance.h +++ b/remoting/client/plugin/chromoting_instance.h @@ -39,6 +39,7 @@ class ConnectionToHost; } // namespace protocol class ChromotingClient; +class ChromotingStats; class ClientContext; class InputHandler; class JingleThread; @@ -78,6 +79,9 @@ class ChromotingInstance : public pp::Instance { void LogDebugInfo(const std::string& info); + // Return statistics record by ChromotingClient. + ChromotingStats* GetStats(); + private: FRIEND_TEST_ALL_PREFIXES(ChromotingInstanceTest, TestCaseSetup); diff --git a/remoting/client/plugin/chromoting_scriptable_object.cc b/remoting/client/plugin/chromoting_scriptable_object.cc index 9a3e2c0..64d6cd5 100644 --- a/remoting/client/plugin/chromoting_scriptable_object.cc +++ b/remoting/client/plugin/chromoting_scriptable_object.cc @@ -8,6 +8,7 @@ #include "base/stringprintf.h" #include "ppapi/cpp/var.h" #include "remoting/client/client_config.h" +#include "remoting/client/chromoting_stats.h" #include "remoting/client/plugin/chromoting_instance.h" #include "remoting/client/plugin/pepper_xmpp_proxy.h" @@ -26,6 +27,7 @@ const char kLoginChallenge[] = "loginChallenge"; const char kSendIq[] = "sendIq"; const char kQualityAttribute[] = "quality"; const char kStatusAttribute[] = "status"; +const char kVideoBandwidthAttribute[] = "videoBandwidth"; } // namespace @@ -69,6 +71,9 @@ void ChromotingScriptableObject::Init() { AddAttribute(kDesktopWidth, Var(0)); AddAttribute(kDesktopHeight, Var(0)); + // Statistics. + AddAttribute(kVideoBandwidthAttribute, Var()); + AddMethod("connect", &ChromotingScriptableObject::DoConnect); AddMethod("connectSandboxed", &ChromotingScriptableObject::DoConnectSandboxed); @@ -126,6 +131,12 @@ Var ChromotingScriptableObject::GetProperty(const Var& name, Var* exception) { return ScriptableObject::GetProperty(name, exception); } + // If this is a statistics attribute then return the value from + // ChromotingStats structure. + if (name.AsString() == kVideoBandwidthAttribute) { + return instance_->GetStats()->video_bandwidth()->Rate(); + } + // TODO(ajwong): This incorrectly return a null object if a function // property is requested. return properties_[iter->second].attribute; diff --git a/remoting/client/plugin/chromoting_scriptable_object.h b/remoting/client/plugin/chromoting_scriptable_object.h index 09ac054..399fb6d 100644 --- a/remoting/client/plugin/chromoting_scriptable_object.h +++ b/remoting/client/plugin/chromoting_scriptable_object.h @@ -13,6 +13,11 @@ // // // Connection status. // readonly attribute unsigned short status; +// +// // Statistics. +// // Video Bandwidth in bytes per second. +// readonly attribute float videoBandwidth; +// // // Constants for connection status. // const unsigned short STATUS_UNKNOWN = 0; // const unsigned short STATUS_CONNECTING = 1; diff --git a/remoting/remoting.gyp b/remoting/remoting.gyp index f2080f1..74c5817 100644 --- a/remoting/remoting.gyp +++ b/remoting/remoting.gyp @@ -159,6 +159,10 @@ 'base/encoder_vp8.h', 'base/encoder_row_based.cc', 'base/encoder_row_based.h', + 'base/rate_counter.cc', + 'base/rate_counter.h', + 'base/running_average.cc', + 'base/running_avarage.h', 'base/tracer.cc', 'base/tracer.h', 'base/types.h', @@ -272,6 +276,8 @@ 'sources': [ 'client/chromoting_client.cc', 'client/chromoting_client.h', + 'client/chromoting_stats.cc', + 'client/chromoting_stats.h', 'client/chromoting_view.cc', 'client/chromoting_view.h', 'client/client_config.h', |