First pass at some Downloads UMA to get a handle on downloads performance.

BUG=None


Review URL: http://codereview.chromium.org/8135032

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@108309 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/content/browser/download/download_file_manager.cc b/content/browser/download/download_file_manager.cc
index d131d47..755e6e9 100644
--- a/content/browser/download/download_file_manager.cc
+++ b/content/browser/download/download_file_manager.cc
@@ -17,6 +17,7 @@
 #include "content/browser/download/download_file.h"
 #include "content/browser/download/download_manager.h"
 #include "content/browser/download/download_request_handle.h"
+#include "content/browser/download/download_stats.h"
 #include "content/browser/renderer_host/resource_dispatcher_host.h"
 #include "content/browser/tab_contents/tab_contents.h"
 #include "content/public/browser/browser_thread.h"
@@ -156,6 +157,8 @@
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
   scoped_ptr<content::ContentVector> contents(buffer->ReleaseContents());
 
+  download_stats::RecordFileThreadReceiveBuffers(contents->size());
+
   DownloadFile* download_file = GetDownloadFile(global_id);
   bool had_error = false;
   for (size_t i = 0; i < contents->size(); ++i) {
diff --git a/content/browser/download/download_resource_handler.cc b/content/browser/download/download_resource_handler.cc
index 51e197c..6be964c 100644
--- a/content/browser/download/download_resource_handler.cc
+++ b/content/browser/download/download_resource_handler.cc
@@ -156,6 +156,7 @@
   DCHECK(buf && buf_size);
   if (!read_buffer_) {
     *buf_size = min_size < 0 ? kReadBufSize : min_size;
+    last_buffer_size_ = *buf_size;
     read_buffer_ = new net::IOBuffer(*buf_size);
   }
   *buf = read_buffer_.get();
@@ -164,6 +165,20 @@
 
 // Pass the buffer to the download file writer.
 bool DownloadResourceHandler::OnReadCompleted(int request_id, int* bytes_read) {
+  base::TimeTicks now(base::TimeTicks::Now());
+  if (!last_read_time_.is_null()) {
+    double seconds_since_last_read = (now - last_read_time_).InSecondsF();
+    if (now == last_read_time_)
+      // Use 1/10 ms as a "very small number" so that we avoid
+      // divide-by-zero error and still record a very high potential bandwidth.
+      seconds_since_last_read = 0.00001;
+
+    double actual_bandwidth = (*bytes_read)/seconds_since_last_read;
+    double potential_bandwidth = last_buffer_size_/seconds_since_last_read;
+    download_stats::RecordBandwidth(actual_bandwidth, potential_bandwidth);
+  }
+  last_read_time_ = now;
+
   if (!*bytes_read)
     return true;
   DCHECK(read_buffer_);
diff --git a/content/browser/download/download_resource_handler.h b/content/browser/download/download_resource_handler.h
index a7dc77c..016756c 100644
--- a/content/browser/download/download_resource_handler.h
+++ b/content/browser/download/download_resource_handler.h
@@ -33,6 +33,8 @@
   typedef base::Callback<void(DownloadId, net::Error)>
     OnStartedCallback;
 
+  static const size_t kLoadsToWrite = 100;  // number of data buffers queued
+
   // started_cb will be called exactly once.
   DownloadResourceHandler(ResourceDispatcherHost* rdh,
                           int render_process_host_id,
@@ -103,8 +105,9 @@
   bool is_paused_;
   base::OneShotTimer<DownloadResourceHandler> pause_timer_;
   base::TimeTicks download_start_time_;  // used to collect stats.
+  base::TimeTicks last_read_time_;        // used to collect stats.
+  size_t last_buffer_size_;               // used to collect stats.
   static const int kReadBufSize = 32768;  // bytes
-  static const size_t kLoadsToWrite = 100;  // number of data buffers queued
   static const int kThrottleTimeMs = 200;  // milliseconds
 
   DISALLOW_COPY_AND_ASSIGN(DownloadResourceHandler);
diff --git a/content/browser/download/download_stats.cc b/content/browser/download/download_stats.cc
index 856e62af..0a44050 100644
--- a/content/browser/download/download_stats.cc
+++ b/content/browser/download/download_stats.cc
@@ -6,6 +6,7 @@
 
 #include "base/metrics/histogram.h"
 #include "base/string_util.h"
+#include "content/browser/download/download_resource_handler.h"
 #include "content/browser/download/interrupt_reasons.h"
 
 namespace download_stats {
@@ -177,6 +178,23 @@
                             DOWNLOAD_CONTENT_MAX);
 }
 
+void RecordFileThreadReceiveBuffers(size_t num_buffers) {
+    UMA_HISTOGRAM_CUSTOM_COUNTS(
+      "Download.FileThreadReceiveBuffers", num_buffers, 1,
+      DownloadResourceHandler::kLoadsToWrite,
+      DownloadResourceHandler::kLoadsToWrite);
+}
+
+void RecordBandwidth(double actual_bandwidth, double potential_bandwidth) {
+  UMA_HISTOGRAM_CUSTOM_COUNTS(
+      "Download.ActualBandwidth", actual_bandwidth, 1, 1000000000, 50);
+  UMA_HISTOGRAM_CUSTOM_COUNTS(
+      "Download.PotentialBandwidth", potential_bandwidth, 1, 1000000000, 50);
+  UMA_HISTOGRAM_PERCENTAGE(
+      "Download.BandwidthUsed",
+      (int) ((actual_bandwidth * 100)/ potential_bandwidth));
+}
+
 void RecordOpen(const base::Time& end, bool first) {
   if (!end.is_null()) {
     UMA_HISTOGRAM_LONG_TIMES("Download.OpenTime", (base::Time::Now() - end));
diff --git a/content/browser/download/download_stats.h b/content/browser/download/download_stats.h
index 54b7dc47..f3e25fa 100644
--- a/content/browser/download/download_stats.h
+++ b/content/browser/download/download_stats.h
@@ -92,6 +92,14 @@
 // Record WRITE_LOOP_COUNT and number of loops.
 void RecordDownloadWriteLoopCount(int count);
 
+// Record the number of buffers piled up by the IO thread
+// before the file thread gets to draining them.
+void RecordFileThreadReceiveBuffers(size_t num_buffers);
+
+// Record the bandwidth seen in DownloadResourceHandler
+// |actual_bandwidth| and |potential_bandwidth| are in bytes/second.
+void RecordBandwidth(double actual_bandwidth, double potential_bandwidth);
+
 // Record the time of both the first open and all subsequent opens since the
 // download completed.
 void RecordOpen(const base::Time& end, bool first);