diff options
author | yuweih <yuweih@chromium.org> | 2016-03-23 15:41:05 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2016-03-23 22:43:12 +0000 |
commit | d2a0c5cb1217570e7b3da52415f7326f48928053 (patch) | |
tree | 5e09f3caa5a6e6824e0b1ae9ec5b320532422b39 /remoting | |
parent | 7d9e04b799588c9cce868eae6ab7570514600895 (diff) | |
download | chromium_src-d2a0c5cb1217570e7b3da52415f7326f48928053.zip chromium_src-d2a0c5cb1217570e7b3da52415f7326f48928053.tar.gz chromium_src-d2a0c5cb1217570e7b3da52415f7326f48928053.tar.bz2 |
Show max latency on client's status bar
Will later also consider storing max latency data in server
BUG=560950
Committed: https://crrev.com/e37a467453f3814a9ecb0eb6769bd7c58b61cbae
Cr-Commit-Position: refs/heads/master@{#382663}
Review URL: https://codereview.chromium.org/1811833002
Cr-Commit-Position: refs/heads/master@{#382957}
Diffstat (limited to 'remoting')
-rw-r--r-- | remoting/base/BUILD.gn | 2 | ||||
-rw-r--r-- | remoting/base/running_average_unittest.cc | 60 | ||||
-rw-r--r-- | remoting/base/running_samples.cc (renamed from remoting/base/running_average.cc) | 26 | ||||
-rw-r--r-- | remoting/base/running_samples.h (renamed from remoting/base/running_average.h) | 30 | ||||
-rw-r--r-- | remoting/base/running_samples_unittest.cc | 92 | ||||
-rw-r--r-- | remoting/client/jni/chromoting_jni_instance.cc | 19 | ||||
-rw-r--r-- | remoting/client/plugin/chromoting_instance.cc | 15 | ||||
-rw-r--r-- | remoting/client/server_log_entry_client.cc | 10 | ||||
-rw-r--r-- | remoting/protocol/capture_scheduler.h | 6 | ||||
-rw-r--r-- | remoting/protocol/performance_tracker.h | 22 | ||||
-rw-r--r-- | remoting/remoting_srcs.gypi | 4 | ||||
-rw-r--r-- | remoting/remoting_test.gypi | 2 | ||||
-rw-r--r-- | remoting/webapp/base/js/chromoting_event.js | 10 | ||||
-rw-r--r-- | remoting/webapp/base/js/connection_stats.js | 31 | ||||
-rw-r--r-- | remoting/webapp/base/js/session_logger.js | 5 | ||||
-rw-r--r-- | remoting/webapp/base/js/stats_accumulator.js | 25 |
16 files changed, 237 insertions, 122 deletions
diff --git a/remoting/base/BUILD.gn b/remoting/base/BUILD.gn index 8a039e1..b8577c1 100644 --- a/remoting/base/BUILD.gn +++ b/remoting/base/BUILD.gn @@ -65,7 +65,7 @@ source_set("unit_tests") { "rate_counter_unittest.cc", "rsa_key_pair_unittest.cc", "run_all_unittests.cc", - "running_average_unittest.cc", + "running_samples_unittest.cc", "test_rsa_key_pair.h", "typed_buffer_unittest.cc", "util_unittest.cc", diff --git a/remoting/base/running_average_unittest.cc b/remoting/base/running_average_unittest.cc deleted file mode 100644 index e731573..0000000 --- a/remoting/base/running_average_unittest.cc +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright 2013 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 <stddef.h> -#include <stdint.h> - -#include "base/macros.h" -#include "remoting/base/running_average.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace remoting { - -static const int64_t kTestValues[] = { 10, 20, 30, 10, 25, 16, 15 }; - -// Average across a single element, i.e. just return the most recent. -TEST(RunningAverageTest, OneElementWindow) { - RunningAverage running_average(1); - EXPECT_EQ(0, running_average.Average()); - - for (size_t i = 0; i < arraysize(kTestValues); ++i) { - running_average.Record(kTestValues[i]); - EXPECT_EQ(static_cast<double>(kTestValues[i]), running_average.Average()); - } -} - -// Average the two most recent elements. -TEST(RunningAverageTest, TwoElementWindow) { - RunningAverage running_average(2); - EXPECT_EQ(0, running_average.Average()); - - for (size_t i = 0; i < arraysize(kTestValues); ++i) { - running_average.Record(kTestValues[i]); - - double expected = kTestValues[i]; - if (i > 0) - expected = (expected + kTestValues[i-1]) / 2; - - EXPECT_EQ(expected, running_average.Average()); - } -} - -// Average across all the elements if the window size exceeds the element count. -TEST(RunningAverageTest, LongWindow) { - RunningAverage running_average(arraysize(kTestValues) + 1); - EXPECT_EQ(0, running_average.Average()); - - for (size_t i = 0; i < arraysize(kTestValues); ++i) { - running_average.Record(kTestValues[i]); - - double expected = 0.0; - for (size_t j = 0; j <= i; ++j) - expected += kTestValues[j]; - expected /= i + 1; - - EXPECT_EQ(expected, running_average.Average()); - } -} - -} // namespace remoting diff --git a/remoting/base/running_average.cc b/remoting/base/running_samples.cc index 5e24c0d..d76a1a6 100644 --- a/remoting/base/running_average.cc +++ b/remoting/base/running_samples.cc @@ -1,22 +1,23 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Copyright 2016 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/running_average.h" +#include "remoting/base/running_samples.h" + +#include <algorithm> #include "base/logging.h" namespace remoting { -RunningAverage::RunningAverage(int window_size) - : window_size_(window_size), - sum_(0) { +RunningSamples::RunningSamples(int window_size) + : window_size_(window_size) { DCHECK_GT(window_size, 0); } -RunningAverage::~RunningAverage() {} +RunningSamples::~RunningSamples() {} -void RunningAverage::Record(int64_t value) { +void RunningSamples::Record(int64_t value) { DCHECK(thread_checker_.CalledOnValidThread()); data_points_.push_back(value); @@ -28,7 +29,7 @@ void RunningAverage::Record(int64_t value) { } } -double RunningAverage::Average() { +double RunningSamples::Average() const { DCHECK(thread_checker_.CalledOnValidThread()); if (data_points_.empty()) @@ -36,4 +37,13 @@ double RunningAverage::Average() { return static_cast<double>(sum_) / data_points_.size(); } +int64_t RunningSamples::Max() const { + DCHECK(thread_checker_.CalledOnValidThread()); + + if (data_points_.empty()) + return 0; + + return *std::max_element(data_points_.begin(), data_points_.end()); +} + } // namespace remoting diff --git a/remoting/base/running_average.h b/remoting/base/running_samples.h index e41234e..3f5078d 100644 --- a/remoting/base/running_average.h +++ b/remoting/base/running_samples.h @@ -1,9 +1,9 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Copyright 2016 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. -#ifndef REMOTING_BASE_RUNNING_AVERAGE_H_ -#define REMOTING_BASE_RUNNING_AVERAGE_H_ +#ifndef REMOTING_BASE_RUNNING_SAMPLES_H_ +#define REMOTING_BASE_RUNNING_SAMPLES_H_ #include <stddef.h> #include <stdint.h> @@ -15,20 +15,26 @@ namespace remoting { -// Calculates the average of the most recent N recorded samples. +// Calculates the maximum or average of the most recent N recorded samples. // This is typically used to smooth out random variation in point samples // over bandwidth, frame rate, etc. -class RunningAverage { +class RunningSamples { public: - // Constructs a helper to average over the |window_size| most recent samples. - explicit RunningAverage(int window_size); - virtual ~RunningAverage(); + // Constructs a running sample helper that stores |window_size| most + // recent samples. + explicit RunningSamples(int window_size); + virtual ~RunningSamples(); // Records a point sample. void Record(int64_t value); // Returns the average over up to |window_size| of the most recent samples. - double Average(); + // 0 if no sample available + double Average() const; + + // Returns the max over up to |window_size| of the most recent samples. + // 0 if no sample available + int64_t Max() const; private: // Stores the desired window size, as size_t to avoid casting when comparing @@ -39,13 +45,13 @@ class RunningAverage { std::deque<int64_t> data_points_; // Holds the sum of the samples in |data_points_|. - int64_t sum_; + int64_t sum_ = 0; base::ThreadChecker thread_checker_; - DISALLOW_COPY_AND_ASSIGN(RunningAverage); + DISALLOW_COPY_AND_ASSIGN(RunningSamples); }; } // namespace remoting -#endif // REMOTING_BASE_RUNNING_AVERAGE_H_ +#endif // REMOTING_BASE_RUNNING_SAMPLES_H_ diff --git a/remoting/base/running_samples_unittest.cc b/remoting/base/running_samples_unittest.cc new file mode 100644 index 0000000..2c2c7f5 --- /dev/null +++ b/remoting/base/running_samples_unittest.cc @@ -0,0 +1,92 @@ +// Copyright 2013 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 <stddef.h> +#include <stdint.h> + +#include "base/macros.h" +#include "remoting/base/running_samples.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace remoting { + +typedef void (*TestFunction)(size_t i, RunningSamples& samples); + +static const int64_t kTestValues[] = { 10, 20, 30, 10, 25, 16, 15 }; + +// Test framework that verifies average() and max() at beginning, iterates +// through all elements and meanwhile calls your own test function +static void TestFramework(int windowSize, TestFunction testFn) { + RunningSamples samples(windowSize); + EXPECT_EQ(0, samples.Average()); + EXPECT_EQ(0, samples.Max()); + + for (size_t i = 0; i < arraysize(kTestValues); ++i) { + samples.Record(kTestValues[i]); + testFn(i, samples); + } +} + +// Average across a single element, i.e. just return the most recent. +TEST(RunningSamplesTest, AverageOneElementWindow) { + TestFramework(1, [](size_t i, RunningSamples& samples) { + EXPECT_EQ(static_cast<double>(kTestValues[i]), samples.Average()); + }); +} + +// Average the two most recent elements. +TEST(RunningSamplesTest, AverageTwoElementWindow) { + TestFramework(2, [](size_t i, RunningSamples& samples) { + double expected = kTestValues[i]; + if (i > 0) + expected = (expected + kTestValues[i-1]) / 2; + + EXPECT_EQ(expected, samples.Average()); + }); +} + +// Average across all the elements if the window size exceeds the element count. +TEST(RunningSamplesTest, AverageLongWindow) { + TestFramework(arraysize(kTestValues) + 1, + [](size_t i, RunningSamples& samples) { + double expected = 0.0; + for (size_t j = 0; j <= i; ++j) + expected += kTestValues[j]; + expected /= i + 1; + + EXPECT_EQ(expected, samples.Average()); + }); +} + +// Max of a single element, i.e. just return the most recent. +TEST(RunningSamplesTest, MaxOneElementWindow) { + TestFramework(1, [](size_t i, RunningSamples& samples) { + EXPECT_EQ(static_cast<double>(kTestValues[i]), samples.Max()); + }); +} + +// Max of the two most recent elements. +TEST(RunningSamplesTest, MaxTwoElementWindow) { + TestFramework(2, [](size_t i, RunningSamples& samples) { + double expected = kTestValues[i]; + if (i > 0) + expected = expected > kTestValues[i-1] ? expected : kTestValues[i-1]; + + EXPECT_EQ(expected, samples.Max()); + }); +} + +// Max of all the elements if the window size exceeds the element count. +TEST(RunningSamplesTest, MaxLongWindow) { + TestFramework(arraysize(kTestValues) + 1, + [](size_t i, RunningSamples& samples) { + int64_t expected = -1; + for (size_t j = 0; j <= i; ++j) + expected = expected > kTestValues[j] ? expected : kTestValues[j]; + + EXPECT_EQ(expected, samples.Max()); + }); +} + +} // namespace remoting
\ No newline at end of file diff --git a/remoting/client/jni/chromoting_jni_instance.cc b/remoting/client/jni/chromoting_jni_instance.cc index f7adccc..1af00bc 100644 --- a/remoting/client/jni/chromoting_jni_instance.cc +++ b/remoting/client/jni/chromoting_jni_instance.cc @@ -11,6 +11,7 @@ #include "base/bind.h" #include "base/callback_helpers.h" +#include "base/format_macros.h" #include "base/logging.h" #include "jingle/glue/thread_wrapper.h" #include "net/socket/client_socket_factory.h" @@ -484,12 +485,20 @@ void ChromotingJniInstance::LogPerfStats() { __android_log_print( ANDROID_LOG_INFO, "stats", - "Bandwidth:%.0f FrameRate:%.1f Capture:%.1f Encode:%.1f " - "Decode:%.1f Render:%.1f Latency:%.0f", + "Bandwidth:%.0f FrameRate:%.1f;" + " (Avg, Max) Capture:%.1f, %" PRId64 " Encode:%.1f, %" PRId64 + " Decode:%.1f, %" PRId64 " Render:%.1f, %" PRId64 " RTL:%.0f, %" PRId64, perf_tracker_->video_bandwidth(), perf_tracker_->video_frame_rate(), - perf_tracker_->video_capture_ms(), perf_tracker_->video_encode_ms(), - perf_tracker_->video_decode_ms(), perf_tracker_->video_paint_ms(), - perf_tracker_->round_trip_ms()); + perf_tracker_->video_capture_ms().Average(), + perf_tracker_->video_capture_ms().Max(), + perf_tracker_->video_encode_ms().Average(), + perf_tracker_->video_encode_ms().Max(), + perf_tracker_->video_decode_ms().Average(), + perf_tracker_->video_decode_ms().Max(), + perf_tracker_->video_paint_ms().Average(), + perf_tracker_->video_paint_ms().Max(), + perf_tracker_->round_trip_ms().Average(), + perf_tracker_->round_trip_ms().Max()); client_status_logger_->LogStatistics(perf_tracker_.get()); diff --git a/remoting/client/plugin/chromoting_instance.cc b/remoting/client/plugin/chromoting_instance.cc index e0ca0d5..a7c5601 100644 --- a/remoting/client/plugin/chromoting_instance.cc +++ b/remoting/client/plugin/chromoting_instance.cc @@ -1034,11 +1034,16 @@ void ChromotingInstance::UpdatePerfStatsInUI() { scoped_ptr<base::DictionaryValue> data(new base::DictionaryValue()); data->SetDouble("videoBandwidth", perf_tracker_.video_bandwidth()); data->SetDouble("videoFrameRate", perf_tracker_.video_frame_rate()); - data->SetDouble("captureLatency", perf_tracker_.video_capture_ms()); - data->SetDouble("encodeLatency", perf_tracker_.video_encode_ms()); - data->SetDouble("decodeLatency", perf_tracker_.video_decode_ms()); - data->SetDouble("renderLatency", perf_tracker_.video_paint_ms()); - data->SetDouble("roundtripLatency", perf_tracker_.round_trip_ms()); + data->SetDouble("captureLatency", perf_tracker_.video_capture_ms().Average()); + data->SetDouble("maxCaptureLatency", perf_tracker_.video_capture_ms().Max()); + data->SetDouble("encodeLatency", perf_tracker_.video_encode_ms().Average()); + data->SetDouble("maxEncodeLatency", perf_tracker_.video_encode_ms().Max()); + data->SetDouble("decodeLatency", perf_tracker_.video_decode_ms().Average()); + data->SetDouble("maxDecodeLatency", perf_tracker_.video_decode_ms().Max()); + data->SetDouble("renderLatency", perf_tracker_.video_paint_ms().Average()); + data->SetDouble("maxRenderLatency", perf_tracker_.video_paint_ms().Max()); + data->SetDouble("roundtripLatency", perf_tracker_.round_trip_ms().Average()); + data->SetDouble("maxRoundtripLatency", perf_tracker_.round_trip_ms().Max()); PostLegacyJsonMessage("onPerfStats", std::move(data)); } diff --git a/remoting/client/server_log_entry_client.cc b/remoting/client/server_log_entry_client.cc index 0686159..290165f 100644 --- a/remoting/client/server_log_entry_client.cc +++ b/remoting/client/server_log_entry_client.cc @@ -117,15 +117,15 @@ scoped_ptr<ServerLogEntry> MakeLogEntryForStatistics( entry->Set("video-bandwidth", StringPrintf("%.2f", perf_tracker->video_bandwidth())); entry->Set("capture-latency", - StringPrintf("%.2f", perf_tracker->video_capture_ms())); + StringPrintf("%.2f", perf_tracker->video_capture_ms().Average())); entry->Set("encode-latency", - StringPrintf("%.2f", perf_tracker->video_encode_ms())); + StringPrintf("%.2f", perf_tracker->video_encode_ms().Average())); entry->Set("decode-latency", - StringPrintf("%.2f", perf_tracker->video_decode_ms())); + StringPrintf("%.2f", perf_tracker->video_decode_ms().Average())); entry->Set("render-latency", - StringPrintf("%.2f", perf_tracker->video_frame_rate())); + StringPrintf("%.2f", perf_tracker->video_paint_ms().Average())); entry->Set("roundtrip-latency", - StringPrintf("%.2f", perf_tracker->round_trip_ms())); + StringPrintf("%.2f", perf_tracker->round_trip_ms().Average())); return entry; } diff --git a/remoting/protocol/capture_scheduler.h b/remoting/protocol/capture_scheduler.h index 54e2229d..3f4369a 100644 --- a/remoting/protocol/capture_scheduler.h +++ b/remoting/protocol/capture_scheduler.h @@ -13,7 +13,7 @@ #include "base/time/tick_clock.h" #include "base/time/time.h" #include "base/timer/timer.h" -#include "remoting/base/running_average.h" +#include "remoting/base/running_samples.h" #include "remoting/protocol/video_feedback_stub.h" namespace remoting { @@ -88,8 +88,8 @@ class CaptureScheduler : public VideoFeedbackStub { int num_of_processors_; - RunningAverage capture_time_; - RunningAverage encode_time_; + RunningSamples capture_time_; + RunningSamples encode_time_; // Number of frames pending encoding. int num_encoding_frames_; diff --git a/remoting/protocol/performance_tracker.h b/remoting/protocol/performance_tracker.h index 3e5bf2c..c31ca91 100644 --- a/remoting/protocol/performance_tracker.h +++ b/remoting/protocol/performance_tracker.h @@ -13,7 +13,7 @@ #include "base/macros.h" #include "base/timer/timer.h" #include "remoting/base/rate_counter.h" -#include "remoting/base/running_average.h" +#include "remoting/base/running_samples.h" namespace remoting { @@ -49,11 +49,11 @@ class PerformanceTracker { double video_bandwidth() { return video_bandwidth_.Rate(); } double video_frame_rate() { return video_frame_rate_.Rate(); } double video_packet_rate() { return video_packet_rate_.Rate(); } - double video_capture_ms() { return video_capture_ms_.Average(); } - double video_encode_ms() { return video_encode_ms_.Average(); } - double video_decode_ms() { return video_decode_ms_.Average(); } - double video_paint_ms() { return video_paint_ms_.Average(); } - double round_trip_ms() { return round_trip_ms_.Average(); } + const RunningSamples& video_capture_ms() { return video_capture_ms_; } + const RunningSamples& video_encode_ms() { return video_encode_ms_; } + const RunningSamples& video_decode_ms() { return video_decode_ms_; } + const RunningSamples& video_paint_ms() { return video_paint_ms_; } + const RunningSamples& round_trip_ms() { return round_trip_ms_; } // Record stats for a video-packet. void RecordVideoPacketStats(const VideoPacket& packet); @@ -113,11 +113,11 @@ class PerformanceTracker { // The following running-averages are uploaded to UMA per video packet and // also used for display to users, averaged over the N most recent samples. // N = kLatencySampleSize. - RunningAverage video_capture_ms_; - RunningAverage video_encode_ms_; - RunningAverage video_decode_ms_; - RunningAverage video_paint_ms_; - RunningAverage round_trip_ms_; + RunningSamples video_capture_ms_; + RunningSamples video_encode_ms_; + RunningSamples video_decode_ms_; + RunningSamples video_paint_ms_; + RunningSamples round_trip_ms_; // Used to update UMA stats, if set. UpdateUmaCustomHistogramCallback uma_custom_counts_updater_; diff --git a/remoting/remoting_srcs.gypi b/remoting/remoting_srcs.gypi index adba780..c6cd2e1 100644 --- a/remoting/remoting_srcs.gypi +++ b/remoting/remoting_srcs.gypi @@ -25,8 +25,8 @@ 'base/rate_counter.h', 'base/rsa_key_pair.cc', 'base/rsa_key_pair.h', - 'base/running_average.cc', - 'base/running_average.h', + 'base/running_samples.cc', + 'base/running_samples.h', 'base/scoped_sc_handle_win.h', 'base/socket_reader.cc', 'base/socket_reader.h', diff --git a/remoting/remoting_test.gypi b/remoting/remoting_test.gypi index 761607e..5f193e9 100644 --- a/remoting/remoting_test.gypi +++ b/remoting/remoting_test.gypi @@ -232,7 +232,7 @@ 'base/rate_counter_unittest.cc', 'base/rsa_key_pair_unittest.cc', 'base/run_all_unittests.cc', - 'base/running_average_unittest.cc', + 'base/running_samples_unittest.cc', 'base/test_rsa_key_pair.h', 'base/typed_buffer_unittest.cc', 'base/util_unittest.cc', diff --git a/remoting/webapp/base/js/chromoting_event.js b/remoting/webapp/base/js/chromoting_event.js index 476f879c..0f6fedd 100644 --- a/remoting/webapp/base/js/chromoting_event.js +++ b/remoting/webapp/base/js/chromoting_event.js @@ -79,6 +79,16 @@ remoting.ChromotingEvent = function(type) { this.render_latency; /** @type {number} */ this.roundtrip_latency; + /** @type {number} */ + this.max_capture_latency; + /** @type {number} */ + this.max_encode_latency; + /** @type {number} */ + this.max_decode_latency; + /** @type {number} */ + this.max_render_latency; + /** @type {number} */ + this.max_roundtrip_latency; /** @type {remoting.ChromotingEvent.Mode} */ this.mode; /** @type {remoting.ChromotingEvent.SignalStrategyType} */ diff --git a/remoting/webapp/base/js/connection_stats.js b/remoting/webapp/base/js/connection_stats.js index d08a527..61d5680 100644 --- a/remoting/webapp/base/js/connection_stats.js +++ b/remoting/webapp/base/js/connection_stats.js @@ -123,23 +123,36 @@ remoting.ConnectionStats.prototype.update = function(stats) { /** * @param {number} value * @param {string} units + * @param {number} digits * @return {string} Formatted number. */ - function formatStatNumber(value, units) { + function formatStatNumber(value, units, digits) { if (value != undefined) { - return value.toFixed(2) + ' ' + units; + return value.toFixed(digits) + ' ' + units; } else { return "n/a"; } } + /** + * @param {string} type + * @param {number} avg + * @param {number} max + * @return {string} "type: avg, max; " e.g. "RTT: 8.0, 13; " + */ + function formatStat(type, avg, max) { + return type + ': ' + avg.toFixed(1) + ', ' + max + '; '; + } + var statistics = document.getElementById('statistics'); this.statsElement_.innerText = ( - 'Bandwidth: ' + formatStatNumber(videoBandwidth, units) + - ', Frame Rate: ' + formatStatNumber(stats.videoFrameRate, 'fps') + - ', Capture: ' + formatStatNumber(stats.captureLatency, 'ms') + - ', Encode: ' + formatStatNumber(stats.encodeLatency, 'ms') + - ', Decode: ' + formatStatNumber(stats.decodeLatency, 'ms') + - ', Render: ' + formatStatNumber(stats.renderLatency, 'ms') + - ', Latency: ' + formatStatNumber(stats.roundtripLatency, 'ms')); + '(avg, max in ms) ' + + formatStat('Capture', stats.captureLatency, stats.maxCaptureLatency) + + formatStat('Encode', stats.encodeLatency, stats.maxEncodeLatency) + + formatStat('Decode', stats.decodeLatency, stats.maxDecodeLatency) + + formatStat('Render', stats.renderLatency, stats.maxRenderLatency) + + formatStat('RTT', stats.roundtripLatency, stats.maxRoundtripLatency) + + 'Bandwidth: ' + formatStatNumber(videoBandwidth, units, 2) + '; ' + + 'Frame Rate: ' + formatStatNumber(stats.videoFrameRate, 'fps', 1) + ); }; diff --git a/remoting/webapp/base/js/session_logger.js b/remoting/webapp/base/js/session_logger.js index 6f26c9a..4e4eba9 100644 --- a/remoting/webapp/base/js/session_logger.js +++ b/remoting/webapp/base/js/session_logger.js @@ -291,6 +291,11 @@ remoting.SessionLogger.prototype.makeStats_ = function() { entry.decode_latency = perfStats.decodeLatency; entry.render_latency = perfStats.renderLatency; entry.roundtrip_latency = perfStats.roundtripLatency; + entry.max_capture_latency = perfStats.maxCaptureLatency; + entry.max_encode_latency = perfStats.maxEncodeLatency; + entry.max_decode_latency = perfStats.maxDecodeLatency; + entry.max_render_latency = perfStats.maxRenderLatency; + entry.max_roundtrip_latency = perfStats.maxRoundtripLatency; return entry; } return null; diff --git a/remoting/webapp/base/js/stats_accumulator.js b/remoting/webapp/base/js/stats_accumulator.js index e0edd49..e8bda09 100644 --- a/remoting/webapp/base/js/stats_accumulator.js +++ b/remoting/webapp/base/js/stats_accumulator.js @@ -94,6 +94,26 @@ remoting.StatsAccumulator.prototype.calcMean = function(key) { }; /** + * Finds the max of the values for a given key. + * + * @param {string} key + * @return {number} the max of the values for that key + */ +remoting.StatsAccumulator.prototype.calcMax = function(key) { + /** + * @param {Array<number>} values + * @return {number} + */ + var calcMax = function(values) { + if (!values || !values.length) { + return 0; + } + return Math.max.apply(null, values); + }; + return this.map(key, calcMax); +}; + +/** * Applies a given map to the list of values for a given key. * * @param {string} key @@ -131,10 +151,15 @@ remoting.StatsAccumulator.prototype.getPerfStats = function() { var stats = new remoting.ClientSession.PerfStats(); stats.videoBandwidth = this.calcMean('videoBandwidth'); stats.captureLatency = this.calcMean('captureLatency'); + stats.maxCaptureLatency = this.calcMax('maxCaptureLatency'); stats.encodeLatency = this.calcMean('encodeLatency'); + stats.maxEncodeLatency = this.calcMax('maxEncodeLatency'); stats.decodeLatency = this.calcMean('decodeLatency'); + stats.maxDecodeLatency = this.calcMax('maxDecodeLatency'); stats.renderLatency = this.calcMean('renderLatency'); + stats.maxRenderLatency = this.calcMax('maxRenderLatency'); stats.roundtripLatency = this.calcMean('roundtripLatency'); + stats.maxRoundtripLatency = this.calcMax('maxRoundtripLatency'); for (var key in stats) { if (stats[key] !== 0) { |