| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "base/trace_event/heap_profiler_stack_frame_deduplicator.h" | 5 #include "base/trace_event/heap_profiler_stack_frame_deduplicator.h" |
| 6 | 6 |
| 7 #include <inttypes.h> | 7 #include <inttypes.h> |
| 8 #include <stddef.h> | 8 #include <stddef.h> |
| 9 | 9 |
| 10 #include <string> | 10 #include <string> |
| 11 #include <utility> | 11 #include <utility> |
| 12 | 12 |
| 13 #include "base/strings/stringprintf.h" | 13 #include "base/strings/stringprintf.h" |
| 14 #include "base/trace_event/trace_event_argument.h" | 14 #include "base/trace_event/trace_event_argument.h" |
| 15 #include "base/trace_event/trace_event_memory_overhead.h" | 15 #include "base/trace_event/trace_event_memory_overhead.h" |
| 16 | 16 |
| 17 namespace base { | 17 namespace base { |
| 18 namespace trace_event { | 18 namespace trace_event { |
| 19 | 19 |
| 20 StackFrameDeduplicator::FrameNode::FrameNode(StackFrame frame, | 20 StackFrameDeduplicator::FrameNode::FrameNode(StackFrame frame, |
| 21 int parent_frame_index) | 21 int parent_frame_index) |
| 22 : frame(frame), parent_frame_index(parent_frame_index) {} | 22 : frame(frame), parent_frame_index(parent_frame_index), indexed(false) {} |
| 23 StackFrameDeduplicator::FrameNode::FrameNode(const FrameNode& other) = default; | 23 StackFrameDeduplicator::FrameNode::FrameNode(const FrameNode& other) = default; |
| 24 StackFrameDeduplicator::FrameNode::~FrameNode() {} | 24 StackFrameDeduplicator::FrameNode::~FrameNode() {} |
| 25 | 25 |
| 26 StackFrameDeduplicator::StackFrameDeduplicator() {} | 26 StackFrameDeduplicator::StackFrameDeduplicator() {} |
| 27 StackFrameDeduplicator::~StackFrameDeduplicator() {} | 27 StackFrameDeduplicator::~StackFrameDeduplicator() {} |
| 28 | 28 |
| 29 int StackFrameDeduplicator::Insert(const StackFrame* beginFrame, | 29 int StackFrameDeduplicator::Insert(const StackFrame* beginFrame, |
| 30 const StackFrame* endFrame) { | 30 const StackFrame* endFrame) { |
| 31 int frame_index = -1; | 31 int frame_index = -1; |
| 32 std::map<StackFrame, int>* nodes = &roots_; | 32 std::map<StackFrame, int>* nodes = &roots_; |
| (...skipping 19 matching lines...) Expand all Loading... |
| 52 // might need to resize, and this invalidates the |nodes| pointer. | 52 // might need to resize, and this invalidates the |nodes| pointer. |
| 53 frames_.push_back(frame_node); | 53 frames_.push_back(frame_node); |
| 54 } else { | 54 } else { |
| 55 // A tree node for this frame exists. Look for the next one. | 55 // A tree node for this frame exists. Look for the next one. |
| 56 frame_index = node->second; | 56 frame_index = node->second; |
| 57 } | 57 } |
| 58 | 58 |
| 59 nodes = &frames_[frame_index].children; | 59 nodes = &frames_[frame_index].children; |
| 60 } | 60 } |
| 61 | 61 |
| 62 if (frame_index != -1) { |
| 63 frames_[frame_index].indexed = true; |
| 64 } |
| 65 |
| 62 return frame_index; | 66 return frame_index; |
| 63 } | 67 } |
| 64 | 68 |
| 65 void StackFrameDeduplicator::AppendAsTraceFormat(std::string* out) const { | 69 void StackFrameDeduplicator::AppendAsTraceFormat(std::string* out) const { |
| 70 #if defined(NEW_TRACE_FORMAT) |
| 71 std::string stringify_buffer; |
| 72 std::unique_ptr<TracedValue> traced_value(new TracedValue); |
| 73 |
| 74 std::map<StackFrame, size_t> unique_frame_indexes; |
| 75 traced_value->BeginDictionary("hierarchy"); |
| 76 { |
| 77 std::function<void(const std::map<StackFrame, int>&)> append_level = |
| 78 [&](const std::map<StackFrame, int>& level) { |
| 79 for (const auto& frame_and_index: level) { |
| 80 int node_index = frame_and_index.second; |
| 81 const FrameNode& node = frames_[node_index]; |
| 82 |
| 83 size_t unique_index = unique_frame_indexes.insert( |
| 84 {node.frame, unique_frame_indexes.size()}).first->second; |
| 85 SStringPrintf(&stringify_buffer, "%zu", unique_index); |
| 86 traced_value->BeginDictionaryWithCopiedName(stringify_buffer); |
| 87 |
| 88 if (node.indexed) { |
| 89 SStringPrintf(&stringify_buffer, "%d", node_index); |
| 90 traced_value->SetString("bt", stringify_buffer); |
| 91 } |
| 92 |
| 93 append_level(node.children); |
| 94 |
| 95 traced_value->EndDictionary(); |
| 96 } |
| 97 }; |
| 98 |
| 99 append_level(roots_); |
| 100 } |
| 101 traced_value->EndDictionary(); |
| 102 |
| 103 traced_value->BeginArray("names"); |
| 104 { |
| 105 std::vector<StackFrame> unique_frames; |
| 106 unique_frames.resize(unique_frame_indexes.size()); |
| 107 for (const auto& frame_and_index: unique_frame_indexes) { |
| 108 DCHECK(frame_and_index.second < unique_frames.size()); |
| 109 unique_frames[frame_and_index.second] = frame_and_index.first; |
| 110 } |
| 111 for (const auto& frame: unique_frames) { |
| 112 switch (frame.type) { |
| 113 case StackFrame::Type::TRACE_EVENT_NAME: |
| 114 traced_value->AppendString(static_cast<const char*>(frame.value)); |
| 115 break; |
| 116 case StackFrame::Type::THREAD_NAME: |
| 117 SStringPrintf(&stringify_buffer, |
| 118 "[Thread: %s]", |
| 119 static_cast<const char*>(frame.value)); |
| 120 traced_value->AppendString(stringify_buffer); |
| 121 break; |
| 122 case StackFrame::Type::PROGRAM_COUNTER: |
| 123 SStringPrintf(&stringify_buffer, |
| 124 "pc:%" PRIxPTR, |
| 125 reinterpret_cast<uintptr_t>(frame.value)); |
| 126 traced_value->AppendString(stringify_buffer); |
| 127 break; |
| 128 } |
| 129 } |
| 130 } |
| 131 traced_value->EndArray(); |
| 132 |
| 133 std::string trace; |
| 134 traced_value->AppendAsTraceFormat(out); |
| 135 |
| 136 #else // !defined(NEW_TRACE_FORMAT) |
| 137 |
| 66 out->append("{"); // Begin the |stackFrames| dictionary. | 138 out->append("{"); // Begin the |stackFrames| dictionary. |
| 67 | 139 |
| 68 int i = 0; | 140 int i = 0; |
| 69 auto frame_node = begin(); | 141 auto frame_node = begin(); |
| 70 auto it_end = end(); | 142 auto it_end = end(); |
| 71 std::string stringify_buffer; | 143 std::string stringify_buffer; |
| 72 | 144 |
| 73 while (frame_node != it_end) { | 145 while (frame_node != it_end) { |
| 74 // The |stackFrames| format is a dictionary, not an array, so the | 146 // The |stackFrames| format is a dictionary, not an array, so the |
| 75 // keys are stringified indices. Write the index manually, then use | 147 // keys are stringified indices. Write the index manually, then use |
| (...skipping 29 matching lines...) Expand all Loading... |
| 105 frame_node_value->AppendAsTraceFormat(out); | 177 frame_node_value->AppendAsTraceFormat(out); |
| 106 | 178 |
| 107 i++; | 179 i++; |
| 108 frame_node++; | 180 frame_node++; |
| 109 | 181 |
| 110 if (frame_node != it_end) | 182 if (frame_node != it_end) |
| 111 out->append(","); | 183 out->append(","); |
| 112 } | 184 } |
| 113 | 185 |
| 114 out->append("}"); // End the |stackFrames| dictionary. | 186 out->append("}"); // End the |stackFrames| dictionary. |
| 187 |
| 188 #endif // defined(NEW_TRACE_FORMAT) |
| 115 } | 189 } |
| 116 | 190 |
| 117 void StackFrameDeduplicator::EstimateTraceMemoryOverhead( | 191 void StackFrameDeduplicator::EstimateTraceMemoryOverhead( |
| 118 TraceEventMemoryOverhead* overhead) { | 192 TraceEventMemoryOverhead* overhead) { |
| 119 // The sizes here are only estimates; they fail to take into account the | 193 // The sizes here are only estimates; they fail to take into account the |
| 120 // overhead of the tree nodes for the map, but as an estimate this should be | 194 // overhead of the tree nodes for the map, but as an estimate this should be |
| 121 // fine. | 195 // fine. |
| 122 size_t maps_size = roots_.size() * sizeof(std::pair<StackFrame, int>); | 196 size_t maps_size = roots_.size() * sizeof(std::pair<StackFrame, int>); |
| 123 size_t frames_allocated = frames_.capacity() * sizeof(FrameNode); | 197 size_t frames_allocated = frames_.capacity() * sizeof(FrameNode); |
| 124 size_t frames_resident = frames_.size() * sizeof(FrameNode); | 198 size_t frames_resident = frames_.size() * sizeof(FrameNode); |
| 125 | 199 |
| 126 for (const FrameNode& node : frames_) | 200 for (const FrameNode& node : frames_) |
| 127 maps_size += node.children.size() * sizeof(std::pair<StackFrame, int>); | 201 maps_size += node.children.size() * sizeof(std::pair<StackFrame, int>); |
| 128 | 202 |
| 129 overhead->Add("StackFrameDeduplicator", | 203 overhead->Add("StackFrameDeduplicator", |
| 130 sizeof(StackFrameDeduplicator) + maps_size + frames_allocated, | 204 sizeof(StackFrameDeduplicator) + maps_size + frames_allocated, |
| 131 sizeof(StackFrameDeduplicator) + maps_size + frames_resident); | 205 sizeof(StackFrameDeduplicator) + maps_size + frames_resident); |
| 132 } | 206 } |
| 133 | 207 |
| 134 } // namespace trace_event | 208 } // namespace trace_event |
| 135 } // namespace base | 209 } // namespace base |
| OLD | NEW |