Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(39)

Side by Side Diff: base/trace_event/heap_profiler_heap_dump_writer.cc

Issue 1467453003: [Tracing] Make heap profiler type info a string (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebase Created 5 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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_heap_dump_writer.h" 5 #include "base/trace_event/heap_profiler_heap_dump_writer.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <iterator> 8 #include <iterator>
9 #include <utility> 9 #include <utility>
10 #include <vector> 10 #include <vector>
11 11
12 #include "base/format_macros.h" 12 #include "base/format_macros.h"
13 #include "base/strings/stringprintf.h" 13 #include "base/strings/stringprintf.h"
14 #include "base/trace_event/heap_profiler_stack_frame_deduplicator.h" 14 #include "base/trace_event/heap_profiler_stack_frame_deduplicator.h"
15 #include "base/trace_event/heap_profiler_type_name_deduplicator.h"
15 #include "base/trace_event/trace_event_argument.h" 16 #include "base/trace_event/trace_event_argument.h"
16 17
17 namespace base { 18 namespace base {
18 namespace trace_event { 19 namespace trace_event {
19 20
20 using TypeId = AllocationContext::TypeId;
21
22 namespace { 21 namespace {
23 22
24 template <typename T> 23 template <typename T>
25 bool PairSizeGt(const std::pair<T, size_t>& lhs, 24 bool PairSizeGt(const std::pair<T, size_t>& lhs,
26 const std::pair<T, size_t>& rhs) { 25 const std::pair<T, size_t>& rhs) {
27 return lhs.second > rhs.second; 26 return lhs.second > rhs.second;
28 } 27 }
29 28
30 // Converts a |hash_map<T, size_t>| into a vector of (T, size_t) pairs that is 29 // Converts a |hash_map<T, size_t>| into a vector of (T, size_t) pairs that is
31 // ordered from high |size_t| to low |size_t|. 30 // ordered from high |size_t| to low |size_t|.
32 template <typename T> 31 template <typename T>
33 std::vector<std::pair<T, size_t>> SortBySizeDescending( 32 std::vector<std::pair<T, size_t>> SortBySizeDescending(
34 const hash_map<T, size_t>& grouped) { 33 const hash_map<T, size_t>& grouped) {
35 std::vector<std::pair<T, size_t>> sorted; 34 std::vector<std::pair<T, size_t>> sorted;
36 sorted.reserve(grouped.size()); 35 sorted.reserve(grouped.size());
37 std::copy(grouped.begin(), grouped.end(), std::back_inserter(sorted)); 36 std::copy(grouped.begin(), grouped.end(), std::back_inserter(sorted));
38 std::sort(sorted.begin(), sorted.end(), PairSizeGt<T>); 37 std::sort(sorted.begin(), sorted.end(), PairSizeGt<T>);
39 return sorted; 38 return sorted;
40 } 39 }
41 40
42 } // namespace 41 } // namespace
43 42
44 HeapDumpWriter::HeapDumpWriter(StackFrameDeduplicator* stack_frame_deduplicator) 43 HeapDumpWriter::HeapDumpWriter(StackFrameDeduplicator* stack_frame_deduplicator,
44 TypeNameDeduplicator* type_name_deduplicator)
45 : traced_value_(new TracedValue()), 45 : traced_value_(new TracedValue()),
46 stack_frame_deduplicator_(stack_frame_deduplicator) {} 46 stack_frame_deduplicator_(stack_frame_deduplicator),
47 type_name_deduplicator_(type_name_deduplicator) {}
47 48
48 HeapDumpWriter::~HeapDumpWriter() {} 49 HeapDumpWriter::~HeapDumpWriter() {}
49 50
50 void HeapDumpWriter::InsertAllocation(const AllocationContext& context, 51 void HeapDumpWriter::InsertAllocation(const AllocationContext& context,
51 size_t size) { 52 size_t size) {
52 bytes_by_context_[context] += size; 53 bytes_by_context_[context] += size;
53 } 54 }
54 55
55 scoped_refptr<TracedValue> HeapDumpWriter::WriteHeapDump() { 56 scoped_refptr<TracedValue> HeapDumpWriter::WriteHeapDump() {
56 // Group by backtrace and by type ID, and compute the total heap size while 57 // Group by backtrace and by type ID, and compute the total heap size while
57 // iterating anyway. 58 // iterating anyway.
58 size_t total_size = 0; 59 size_t total_size = 0;
59 hash_map<Backtrace, size_t> bytes_by_backtrace; 60 hash_map<Backtrace, size_t> bytes_by_backtrace;
60 hash_map<TypeId, size_t> bytes_by_type; 61 hash_map<const char*, size_t> bytes_by_type;
61 62
62 for (auto context_size : bytes_by_context_) { 63 for (auto context_size : bytes_by_context_) {
63 total_size += context_size.second; 64 total_size += context_size.second;
64 bytes_by_backtrace[context_size.first.backtrace] += context_size.second; 65 bytes_by_backtrace[context_size.first.backtrace] += context_size.second;
65 bytes_by_type[context_size.first.type_id] += context_size.second; 66 bytes_by_type[context_size.first.type_name] += context_size.second;
66 } 67 }
67 68
68 auto sorted_bytes_by_backtrace = SortBySizeDescending(bytes_by_backtrace); 69 auto sorted_bytes_by_backtrace = SortBySizeDescending(bytes_by_backtrace);
69 auto sorted_bytes_by_type = SortBySizeDescending(bytes_by_type); 70 auto sorted_bytes_by_type = SortBySizeDescending(bytes_by_type);
70 71
71 traced_value_->BeginArray("entries"); 72 traced_value_->BeginArray("entries");
72 73
73 // The global size, no column specified. 74 // The global size, no column specified.
74 { 75 {
75 traced_value_->BeginDictionary(); 76 traced_value_->BeginDictionary();
76 WriteSize(total_size); 77 WriteSize(total_size);
77 traced_value_->EndDictionary(); 78 traced_value_->EndDictionary();
78 } 79 }
79 80
80 // Entries with the size per backtrace. 81 // Entries with the size per backtrace.
81 for (const auto& entry : sorted_bytes_by_backtrace) { 82 for (const auto& entry : sorted_bytes_by_backtrace) {
82 traced_value_->BeginDictionary(); 83 traced_value_->BeginDictionary();
83 // Insert a forward reference to the backtrace that will be written to the 84 // Insert a forward reference to the backtrace that will be written to the
84 // |stackFrames| dictionary later on. 85 // |stackFrames| dictionary later on.
85 WriteStackFrameIndex(stack_frame_deduplicator_->Insert(entry.first)); 86 WriteStackFrameIndex(stack_frame_deduplicator_->Insert(entry.first));
86 WriteSize(entry.second); 87 WriteSize(entry.second);
87 traced_value_->EndDictionary(); 88 traced_value_->EndDictionary();
88 } 89 }
89 90
90 // Entries with the size per type. 91 // Entries with the size per type.
91 for (const auto& entry : sorted_bytes_by_type) { 92 for (const auto& entry : sorted_bytes_by_type) {
92 traced_value_->BeginDictionary(); 93 traced_value_->BeginDictionary();
93 WriteTypeId(entry.first); 94 // Insert a forward reference to the type name that will be written to the
95 // trace when it is flushed.
96 WriteTypeId(type_name_deduplicator_->Insert(entry.first));
94 WriteSize(entry.second); 97 WriteSize(entry.second);
95 traced_value_->EndDictionary(); 98 traced_value_->EndDictionary();
96 } 99 }
97 100
98 traced_value_->EndArray(); // "entries" 101 traced_value_->EndArray(); // "entries"
99 102
100 return traced_value_; 103 return traced_value_;
101 } 104 }
102 105
103 void HeapDumpWriter::WriteStackFrameIndex(int index) { 106 void HeapDumpWriter::WriteStackFrameIndex(int index) {
104 if (index == -1) { 107 if (index == -1) {
105 // An empty backtrace (which will have index -1) is represented by the empty 108 // An empty backtrace (which will have index -1) is represented by the empty
106 // string, because there is no leaf frame to reference in |stackFrames|. 109 // string, because there is no leaf frame to reference in |stackFrames|.
107 traced_value_->SetString("bt", ""); 110 traced_value_->SetString("bt", "");
108 } else { 111 } else {
109 // Format index of the leaf frame as a string, because |stackFrames| is a 112 // Format index of the leaf frame as a string, because |stackFrames| is a
110 // dictionary, not an array. 113 // dictionary, not an array.
111 SStringPrintf(&buffer_, "%i", index); 114 SStringPrintf(&buffer_, "%i", index);
112 traced_value_->SetString("bt", buffer_); 115 traced_value_->SetString("bt", buffer_);
113 } 116 }
114 } 117 }
115 118
116 void HeapDumpWriter::WriteTypeId(TypeId type_id) { 119 void HeapDumpWriter::WriteTypeId(int type_id) {
117 if (type_id == 0) { 120 // Format the type ID as a string.
118 // Type ID 0 represents "unknown type". Instead of writing it as "0" which 121 SStringPrintf(&buffer_, "%i", type_id);
119 // could be mistaken for an actual type ID, an unknown type is represented 122 traced_value_->SetString("type", buffer_);
120 // by the empty string.
121 traced_value_->SetString("type", "");
122 } else {
123 // Format the type ID as a string.
124 SStringPrintf(&buffer_, "%" PRIu16, type_id);
125 traced_value_->SetString("type", buffer_);
126 }
127 } 123 }
128 124
129 void HeapDumpWriter::WriteSize(size_t size) { 125 void HeapDumpWriter::WriteSize(size_t size) {
130 // Format size as hexadecimal string into |buffer_|. 126 // Format size as hexadecimal string into |buffer_|.
131 SStringPrintf(&buffer_, "%" PRIx64, static_cast<uint64_t>(size)); 127 SStringPrintf(&buffer_, "%" PRIx64, static_cast<uint64_t>(size));
132 traced_value_->SetString("size", buffer_); 128 traced_value_->SetString("size", buffer_);
133 } 129 }
134 130
135 } // namespace trace_event 131 } // namespace trace_event
136 } // namespace base 132 } // namespace base
OLDNEW
« no previous file with comments | « base/trace_event/heap_profiler_heap_dump_writer.h ('k') | base/trace_event/heap_profiler_heap_dump_writer_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698