summaryrefslogtreecommitdiffstats
path: root/remoting
diff options
context:
space:
mode:
authorhclam@google.com <hclam@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2011-04-05 18:03:31 +0000
committerhclam@google.com <hclam@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2011-04-05 18:03:31 +0000
commit778d599df45c985286cd70898187ecf7a6284eeb (patch)
treee4518f5d17d84f6613e0507c1dddc05ab1ddf23b /remoting
parent6ca1745021ac1b7822eb23a58c3985b2a91b293d (diff)
downloadchromium_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.cc49
-rw-r--r--remoting/base/rate_counter.h61
-rw-r--r--remoting/base/running_average.cc39
-rw-r--r--remoting/base/running_average.h57
-rw-r--r--remoting/client/chromoting_client.cc7
-rw-r--r--remoting/client/chromoting_client.h13
-rw-r--r--remoting/client/chromoting_stats.cc20
-rw-r--r--remoting/client/chromoting_stats.h29
-rw-r--r--remoting/client/plugin/chromoting_instance.cc4
-rw-r--r--remoting/client/plugin/chromoting_instance.h4
-rw-r--r--remoting/client/plugin/chromoting_scriptable_object.cc11
-rw-r--r--remoting/client/plugin/chromoting_scriptable_object.h5
-rw-r--r--remoting/remoting.gyp6
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',