| OLD | NEW |
| (Empty) | |
| 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "net/base/load_log_util.h" |
| 6 |
| 7 #include "base/string_util.h" |
| 8 |
| 9 namespace net { |
| 10 namespace { |
| 11 |
| 12 class FormatHelper { |
| 13 public: |
| 14 std::string ToString(const LoadLog* log) { |
| 15 entries_.clear(); |
| 16 |
| 17 // Pass 1: Match the start/end of indentation blocks. Fills |entries_| |
| 18 // with the results. |
| 19 PopulateEntries(log); |
| 20 |
| 21 // Pass 2: Figure out the maximum width of each column. This allows us |
| 22 // to right-justify text within each column. |
| 23 size_t max_time_width, max_indentation, max_type_width, max_dt_width; |
| 24 GetMaxExtent( |
| 25 &max_time_width, &max_indentation, &max_type_width, &max_dt_width); |
| 26 |
| 27 // Pass 3: Assemble the string. |
| 28 std::string result; |
| 29 |
| 30 const int kSpacesPerIndentation = 2; |
| 31 |
| 32 for (size_t i = 0; i < entries_.size(); ++i) { |
| 33 if (i > 0) |
| 34 result += "\n"; |
| 35 |
| 36 int indentation_spaces = entries_[i].indentation * kSpacesPerIndentation; |
| 37 std::string event_str = GetEventString(i); |
| 38 |
| 39 result += StringPrintf("t=%s: %s%s", |
| 40 PadStringLeft(GetTimeString(i), max_time_width).c_str(), |
| 41 PadStringLeft("", indentation_spaces).c_str(), |
| 42 event_str.c_str()); |
| 43 |
| 44 if (entries_[i].event->phase == LoadLog::PHASE_BEGIN) { |
| 45 // Summarize how long this block lasted. |
| 46 int padding = ((max_indentation - entries_[i].indentation) * |
| 47 kSpacesPerIndentation) + (max_type_width - event_str.size()); |
| 48 result += StringPrintf("%s [dt=%s]", |
| 49 PadStringLeft("", padding).c_str(), |
| 50 PadStringLeft(GetBlockDtString(i), max_dt_width).c_str()); |
| 51 } |
| 52 } |
| 53 |
| 54 return result; |
| 55 } |
| 56 |
| 57 private: |
| 58 struct Entry { |
| 59 explicit Entry(const LoadLog::Event* event) |
| 60 : event(event), indentation(0), block_index(-1) {} |
| 61 |
| 62 const LoadLog::Event* event; |
| 63 size_t indentation; |
| 64 int block_index; // The index of the matching start / end of block. |
| 65 }; |
| 66 |
| 67 void PopulateEntries(const LoadLog* log) { |
| 68 int current_indentation = 0; |
| 69 |
| 70 for (size_t i = 0; i < log->events().size(); ++i) { |
| 71 Entry entry(&log->events()[i]); |
| 72 |
| 73 entry.indentation = current_indentation; |
| 74 |
| 75 if (entry.event->phase == LoadLog::PHASE_BEGIN) { |
| 76 // Indent everything contained in this block. |
| 77 current_indentation++; |
| 78 } |
| 79 |
| 80 if (entry.event->phase == LoadLog::PHASE_END) { |
| 81 int start_index = FindStartOfBlockIndex(entry); |
| 82 if (start_index != -1) { |
| 83 // Point the start / end of block at each other. |
| 84 entry.block_index = start_index; |
| 85 entries_[start_index].block_index = i; |
| 86 |
| 87 // Restore the indentation prior to the block. |
| 88 // (Could be more than 1 level if close of blocks are missing). |
| 89 current_indentation = entries_[start_index].indentation; |
| 90 entry.indentation = current_indentation; |
| 91 } |
| 92 } |
| 93 |
| 94 entries_.push_back(entry); |
| 95 } |
| 96 } |
| 97 |
| 98 int FindStartOfBlockIndex(const Entry& entry) { |
| 99 DCHECK_EQ(LoadLog::PHASE_END, entry.event->phase); |
| 100 |
| 101 // Find the matching start of block by scanning backwards. |
| 102 for (int i = entries_.size() - 1; i >= 0; --i) { |
| 103 if (entries_[i].event->phase == LoadLog::PHASE_BEGIN && |
| 104 entries_[i].event->type == entry.event->type) { |
| 105 return i; |
| 106 } |
| 107 } |
| 108 return -1; // Start not found. |
| 109 } |
| 110 |
| 111 void GetMaxExtent(size_t* max_time_width, |
| 112 size_t* max_indentation, |
| 113 size_t* max_type_width, |
| 114 size_t* max_dt_width) { |
| 115 *max_time_width = *max_indentation = *max_type_width = *max_dt_width = 0; |
| 116 for (size_t i = 0; i < entries_.size(); ++i) { |
| 117 *max_time_width = std::max(*max_time_width, GetTimeString(i).size()); |
| 118 *max_type_width = std::max(*max_type_width, GetEventString(i).size()); |
| 119 *max_indentation = std::max(*max_indentation, entries_[i].indentation); |
| 120 |
| 121 if (entries_[i].event->phase == LoadLog::PHASE_BEGIN) |
| 122 *max_dt_width = std::max(*max_dt_width, GetBlockDtString(i).size()); |
| 123 } |
| 124 } |
| 125 |
| 126 std::string GetBlockDtString(size_t start_index) { |
| 127 int end_index = entries_[start_index].block_index; |
| 128 if (end_index == -1) { |
| 129 // Block is not closed, implicitly close it at EOF. |
| 130 end_index = entries_.size() - 1; |
| 131 } |
| 132 int64 dt_ms = (entries_[end_index].event->time - |
| 133 entries_[start_index].event->time).InMilliseconds(); |
| 134 |
| 135 return Int64ToString(dt_ms); |
| 136 } |
| 137 |
| 138 std::string GetTimeString(size_t index) { |
| 139 int64 t_ms = (entries_[index].event->time - |
| 140 base::TimeTicks()).InMilliseconds(); |
| 141 return Int64ToString(t_ms); |
| 142 } |
| 143 |
| 144 std::string GetEventString(size_t index) { |
| 145 const LoadLog::Event* event = entries_[index].event; |
| 146 const char* type_str = LoadLog::EventTypeToString(event->type); |
| 147 |
| 148 switch (event->phase) { |
| 149 case LoadLog::PHASE_BEGIN: |
| 150 return std::string("+") + type_str; |
| 151 case LoadLog::PHASE_END: |
| 152 return std::string("-") + type_str; |
| 153 case LoadLog::PHASE_NONE: |
| 154 return std::string(" ") + type_str; |
| 155 default: |
| 156 NOTREACHED(); |
| 157 return std::string(); |
| 158 } |
| 159 } |
| 160 |
| 161 static std::string PadStringLeft(const std::string& str, size_t width) { |
| 162 DCHECK_LE(str.size(), width); |
| 163 std::string padding; |
| 164 padding.resize(width - str.size(), ' '); |
| 165 return padding + str; |
| 166 } |
| 167 |
| 168 std::vector<Entry> entries_; |
| 169 }; |
| 170 |
| 171 } // namespace |
| 172 |
| 173 // static |
| 174 std::string LoadLogUtil::PrettyPrintAsEventTree(const LoadLog* log) { |
| 175 FormatHelper helper; |
| 176 return helper.ToString(log); |
| 177 } |
| 178 |
| 179 } // namespace net |
| OLD | NEW |