summaryrefslogtreecommitdiffstats
path: root/net/base/load_log_util.cc
diff options
context:
space:
mode:
authorericroman@google.com <ericroman@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2009-08-14 03:01:09 +0000
committerericroman@google.com <ericroman@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2009-08-14 03:01:09 +0000
commit54e1377ea309c5d8ab318ee9691b46249d7441b6 (patch)
tree8471e44056027dff255ff5b22ba083a9482b41c3 /net/base/load_log_util.cc
parent672eca0fd191acd39c28430d1ed1f327594faff8 (diff)
downloadchromium_src-54e1377ea309c5d8ab318ee9691b46249d7441b6.zip
chromium_src-54e1377ea309c5d8ab318ee9691b46249d7441b6.tar.gz
chromium_src-54e1377ea309c5d8ab318ee9691b46249d7441b6.tar.bz2
Implement LoadLog, and hook up HostResolverImpl to LoadLog.
The functionality in load_log_util.h is currently unused, but since it motivates the implementation of LoadLog, figured it should be included with this review. Note that I decided against defining the loggable event types as LoadStates, since I wanted more flexibility in adding crazy stuff, and they really seem too implementation specific to be in LoadStates. BUG=http://crbug.com/14478 TEST=net_unittests Review URL: http://codereview.chromium.org/165404 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@23412 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net/base/load_log_util.cc')
-rw-r--r--net/base/load_log_util.cc179
1 files changed, 179 insertions, 0 deletions
diff --git a/net/base/load_log_util.cc b/net/base/load_log_util.cc
new file mode 100644
index 0000000..28304d0
--- /dev/null
+++ b/net/base/load_log_util.cc
@@ -0,0 +1,179 @@
+// Copyright (c) 2009 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 "net/base/load_log_util.h"
+
+#include "base/string_util.h"
+
+namespace net {
+namespace {
+
+class FormatHelper {
+ public:
+ std::string ToString(const LoadLog* log) {
+ entries_.clear();
+
+ // Pass 1: Match the start/end of indentation blocks. Fills |entries_|
+ // with the results.
+ PopulateEntries(log);
+
+ // Pass 2: Figure out the maximum width of each column. This allows us
+ // to right-justify text within each column.
+ size_t max_time_width, max_indentation, max_type_width, max_dt_width;
+ GetMaxExtent(
+ &max_time_width, &max_indentation, &max_type_width, &max_dt_width);
+
+ // Pass 3: Assemble the string.
+ std::string result;
+
+ const int kSpacesPerIndentation = 2;
+
+ for (size_t i = 0; i < entries_.size(); ++i) {
+ if (i > 0)
+ result += "\n";
+
+ int indentation_spaces = entries_[i].indentation * kSpacesPerIndentation;
+ std::string event_str = GetEventString(i);
+
+ result += StringPrintf("t=%s: %s%s",
+ PadStringLeft(GetTimeString(i), max_time_width).c_str(),
+ PadStringLeft("", indentation_spaces).c_str(),
+ event_str.c_str());
+
+ if (entries_[i].event->phase == LoadLog::PHASE_BEGIN) {
+ // Summarize how long this block lasted.
+ int padding = ((max_indentation - entries_[i].indentation) *
+ kSpacesPerIndentation) + (max_type_width - event_str.size());
+ result += StringPrintf("%s [dt=%s]",
+ PadStringLeft("", padding).c_str(),
+ PadStringLeft(GetBlockDtString(i), max_dt_width).c_str());
+ }
+ }
+
+ return result;
+ }
+
+ private:
+ struct Entry {
+ explicit Entry(const LoadLog::Event* event)
+ : event(event), indentation(0), block_index(-1) {}
+
+ const LoadLog::Event* event;
+ size_t indentation;
+ int block_index; // The index of the matching start / end of block.
+ };
+
+ void PopulateEntries(const LoadLog* log) {
+ int current_indentation = 0;
+
+ for (size_t i = 0; i < log->events().size(); ++i) {
+ Entry entry(&log->events()[i]);
+
+ entry.indentation = current_indentation;
+
+ if (entry.event->phase == LoadLog::PHASE_BEGIN) {
+ // Indent everything contained in this block.
+ current_indentation++;
+ }
+
+ if (entry.event->phase == LoadLog::PHASE_END) {
+ int start_index = FindStartOfBlockIndex(entry);
+ if (start_index != -1) {
+ // Point the start / end of block at each other.
+ entry.block_index = start_index;
+ entries_[start_index].block_index = i;
+
+ // Restore the indentation prior to the block.
+ // (Could be more than 1 level if close of blocks are missing).
+ current_indentation = entries_[start_index].indentation;
+ entry.indentation = current_indentation;
+ }
+ }
+
+ entries_.push_back(entry);
+ }
+ }
+
+ int FindStartOfBlockIndex(const Entry& entry) {
+ DCHECK_EQ(LoadLog::PHASE_END, entry.event->phase);
+
+ // Find the matching start of block by scanning backwards.
+ for (int i = entries_.size() - 1; i >= 0; --i) {
+ if (entries_[i].event->phase == LoadLog::PHASE_BEGIN &&
+ entries_[i].event->type == entry.event->type) {
+ return i;
+ }
+ }
+ return -1; // Start not found.
+ }
+
+ void GetMaxExtent(size_t* max_time_width,
+ size_t* max_indentation,
+ size_t* max_type_width,
+ size_t* max_dt_width) {
+ *max_time_width = *max_indentation = *max_type_width = *max_dt_width = 0;
+ for (size_t i = 0; i < entries_.size(); ++i) {
+ *max_time_width = std::max(*max_time_width, GetTimeString(i).size());
+ *max_type_width = std::max(*max_type_width, GetEventString(i).size());
+ *max_indentation = std::max(*max_indentation, entries_[i].indentation);
+
+ if (entries_[i].event->phase == LoadLog::PHASE_BEGIN)
+ *max_dt_width = std::max(*max_dt_width, GetBlockDtString(i).size());
+ }
+ }
+
+ std::string GetBlockDtString(size_t start_index) {
+ int end_index = entries_[start_index].block_index;
+ if (end_index == -1) {
+ // Block is not closed, implicitly close it at EOF.
+ end_index = entries_.size() - 1;
+ }
+ int64 dt_ms = (entries_[end_index].event->time -
+ entries_[start_index].event->time).InMilliseconds();
+
+ return Int64ToString(dt_ms);
+ }
+
+ std::string GetTimeString(size_t index) {
+ int64 t_ms = (entries_[index].event->time -
+ base::TimeTicks()).InMilliseconds();
+ return Int64ToString(t_ms);
+ }
+
+ std::string GetEventString(size_t index) {
+ const LoadLog::Event* event = entries_[index].event;
+ const char* type_str = LoadLog::EventTypeToString(event->type);
+
+ switch (event->phase) {
+ case LoadLog::PHASE_BEGIN:
+ return std::string("+") + type_str;
+ case LoadLog::PHASE_END:
+ return std::string("-") + type_str;
+ case LoadLog::PHASE_NONE:
+ return std::string(" ") + type_str;
+ default:
+ NOTREACHED();
+ return std::string();
+ }
+ }
+
+ static std::string PadStringLeft(const std::string& str, size_t width) {
+ DCHECK_LE(str.size(), width);
+ std::string padding;
+ padding.resize(width - str.size(), ' ');
+ return padding + str;
+ }
+
+ std::vector<Entry> entries_;
+};
+
+} // namespace
+
+// static
+std::string LoadLogUtil::PrettyPrintAsEventTree(const LoadLog* log) {
+ FormatHelper helper;
+ return helper.ToString(log);
+}
+
+} // namespace net