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_type_name_deduplicator.h" | 5 #include "base/trace_event/heap_profiler_type_name_deduplicator.h" |
6 | 6 |
7 #include <stddef.h> | 7 #include <stddef.h> |
8 #include <stdlib.h> | 8 #include <stdlib.h> |
9 #include <string> | 9 #include <string> |
10 #include <utility> | 10 #include <utility> |
11 | 11 |
12 #include "base/json/string_escape.h" | |
13 #include "base/strings/string_split.h" | 12 #include "base/strings/string_split.h" |
14 #include "base/strings/stringprintf.h" | |
15 #include "base/trace_event/memory_usage_estimator.h" | 13 #include "base/trace_event/memory_usage_estimator.h" |
16 #include "base/trace_event/trace_event.h" | 14 #include "base/trace_event/trace_event.h" |
| 15 #include "base/trace_event/trace_event_argument.h" |
17 #include "base/trace_event/trace_event_memory_overhead.h" | 16 #include "base/trace_event/trace_event_memory_overhead.h" |
18 | 17 |
19 namespace base { | 18 namespace base { |
20 namespace trace_event { | 19 namespace trace_event { |
21 | 20 |
22 namespace { | 21 namespace { |
23 | 22 |
24 // If |type_name| is file name then extract directory name. Or if |type_name| is | 23 // If |type_name| is file name then extract directory name. Or if |type_name| is |
25 // category name, then disambiguate multple categories and remove | 24 // category name, then disambiguate multple categories and remove |
26 // "disabled-by-default" prefix if present. | 25 // "disabled-by-default" prefix if present. |
(...skipping 22 matching lines...) Expand all Loading... |
49 while (result.starts_with(kParentDirectory)) { | 48 while (result.starts_with(kParentDirectory)) { |
50 result.remove_prefix(kParentDirectoryLength); | 49 result.remove_prefix(kParentDirectoryLength); |
51 } | 50 } |
52 return result; | 51 return result; |
53 } | 52 } |
54 | 53 |
55 } // namespace | 54 } // namespace |
56 | 55 |
57 TypeNameDeduplicator::TypeNameDeduplicator() { | 56 TypeNameDeduplicator::TypeNameDeduplicator() { |
58 // A null pointer has type ID 0 ("unknown type"); | 57 // A null pointer has type ID 0 ("unknown type"); |
59 type_ids_.insert(std::make_pair(nullptr, 0)); | 58 Insert(nullptr); |
60 } | 59 } |
61 | 60 |
62 TypeNameDeduplicator::~TypeNameDeduplicator() {} | 61 TypeNameDeduplicator::~TypeNameDeduplicator() {} |
63 | 62 |
64 int TypeNameDeduplicator::Insert(const char* type_name) { | 63 int TypeNameDeduplicator::Insert(const char* type_name) { |
65 auto result = type_ids_.insert(std::make_pair(type_name, 0)); | 64 auto result = type_ids_.insert(std::make_pair(type_name, 0)); |
66 auto& elem = result.first; | 65 auto& elem = result.first; |
67 bool did_not_exist_before = result.second; | 66 bool did_not_exist_before = result.second; |
68 | 67 |
69 if (did_not_exist_before) { | 68 if (did_not_exist_before) { |
70 // The type IDs are assigned sequentially and they are zero-based, so | 69 // The type IDs are assigned sequentially and they are zero-based, so |
71 // |size() - 1| is the ID of the new element. | 70 // |size() - 1| is the ID of the new element. |
72 elem->second = static_cast<int>(type_ids_.size() - 1); | 71 elem->second = static_cast<int>(type_ids_.size() - 1); |
| 72 new_type_ids_.push_back(result.first); |
73 } | 73 } |
74 | 74 |
75 return elem->second; | 75 return elem->second; |
76 } | 76 } |
77 | 77 |
78 void TypeNameDeduplicator::AppendAsTraceFormat(std::string* out) const { | 78 void TypeNameDeduplicator::AppendIncrementally(TracedValue* traced_value) { |
79 out->append("{"); // Begin the type names dictionary. | 79 for (const auto& name_and_id : new_type_ids_) { |
| 80 traced_value->BeginDictionary(); |
80 | 81 |
81 auto it = type_ids_.begin(); | 82 traced_value->SetInteger("id", name_and_id->second); |
82 std::string buffer; | |
83 | |
84 // Write the first entry manually; the null pointer must not be dereferenced. | |
85 // (The first entry is the null pointer because a |std::map| is ordered.) | |
86 it++; | |
87 out->append("\"0\":\"[unknown]\""); | |
88 | |
89 for (; it != type_ids_.end(); it++) { | |
90 // Type IDs in the trace are strings, write them as stringified keys of | |
91 // a dictionary. | |
92 SStringPrintf(&buffer, ",\"%d\":", it->second); | |
93 | 83 |
94 // TODO(ssid): crbug.com/594803 the type name is misused for file name in | 84 // TODO(ssid): crbug.com/594803 the type name is misused for file name in |
95 // some cases. | 85 // some cases. |
96 StringPiece type_info = ExtractCategoryFromTypeName(it->first); | 86 traced_value->SetString("type", |
| 87 ExtractCategoryFromTypeName(name_and_id->first)); |
97 | 88 |
98 // |EscapeJSONString| appends, it does not overwrite |buffer|. | 89 traced_value->EndDictionary(); |
99 bool put_in_quotes = true; | |
100 EscapeJSONString(type_info, put_in_quotes, &buffer); | |
101 out->append(buffer); | |
102 } | 90 } |
103 | 91 new_type_ids_.clear(); |
104 out->append("}"); // End the type names dictionary. | |
105 } | 92 } |
106 | 93 |
107 void TypeNameDeduplicator::EstimateTraceMemoryOverhead( | 94 void TypeNameDeduplicator::EstimateTraceMemoryOverhead( |
108 TraceEventMemoryOverhead* overhead) { | 95 TraceEventMemoryOverhead* overhead) { |
109 size_t memory_usage = EstimateMemoryUsage(type_ids_); | 96 size_t memory_usage = EstimateMemoryUsage(type_ids_); |
110 overhead->Add("TypeNameDeduplicator", | 97 overhead->Add("TypeNameDeduplicator", |
111 sizeof(TypeNameDeduplicator) + memory_usage); | 98 sizeof(TypeNameDeduplicator) + memory_usage); |
112 } | 99 } |
113 | 100 |
114 } // namespace trace_event | 101 } // namespace trace_event |
115 } // namespace base | 102 } // namespace base |
OLD | NEW |