diff options
author | ericroman@google.com <ericroman@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-08-14 03:01:09 +0000 |
---|---|---|
committer | ericroman@google.com <ericroman@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-08-14 03:01:09 +0000 |
commit | 54e1377ea309c5d8ab318ee9691b46249d7441b6 (patch) | |
tree | 8471e44056027dff255ff5b22ba083a9482b41c3 /net/base/load_log_util.cc | |
parent | 672eca0fd191acd39c28430d1ed1f327594faff8 (diff) | |
download | chromium_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.cc | 179 |
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 |