Avi Drissman | 8ba1bad | 2022-09-13 19:22:36 | [diff] [blame] | 1 | // Copyright 2017 The Chromium Authors |
brettw | bd8214bf | 2017-06-20 03:47:03 | [diff] [blame] | 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
erikchen | fa983faa | 2018-04-05 18:56:42 | [diff] [blame] | 5 | #include "components/services/heap_profiling/connection_manager.h" |
brettw | bd8214bf | 2017-06-20 03:47:03 | [diff] [blame] | 6 | |
Joe Mason | cf9e0bc | 2023-06-06 18:30:47 | [diff] [blame] | 7 | #include <utility> |
| 8 | |
Avi Drissman | 12be031 | 2023-01-11 09:16:09 | [diff] [blame] | 9 | #include "base/functional/bind.h" |
Joe Mason | cf9e0bc | 2023-06-06 18:30:47 | [diff] [blame] | 10 | #include "base/functional/callback.h" |
Alexei Filippov | e48985e | 2019-02-01 00:27:41 | [diff] [blame] | 11 | #include "base/json/string_escape.h" |
erikchen | e382a10 | 2017-10-20 00:30:13 | [diff] [blame] | 12 | #include "base/metrics/histogram_macros.h" |
erikchen | fa983faa | 2018-04-05 18:56:42 | [diff] [blame] | 13 | #include "components/services/heap_profiling/json_exporter.h" |
Alexei Filippov | 21ec8dc | 2019-04-25 23:10:29 | [diff] [blame] | 14 | #include "components/services/heap_profiling/public/cpp/profiling_client.h" |
brettw | bd8214bf | 2017-06-20 03:47:03 | [diff] [blame] | 15 | |
erikchen | 102fe21 | 2018-04-06 13:02:10 | [diff] [blame] | 16 | namespace heap_profiling { |
brettw | bd8214bf | 2017-06-20 03:47:03 | [diff] [blame] | 17 | |
Erik Chen | e2d06447 | 2017-10-07 03:34:07 | [diff] [blame] | 18 | // Tracking information for DumpProcessForTracing(). This struct is |
| 19 | // refcounted since there will be many background thread calls (one for each |
| 20 | // AllocationTracker) and the callback is only issued when each has |
| 21 | // responded. |
| 22 | // |
| 23 | // This class is not threadsafe, its members must only be accessed on the |
| 24 | // I/O thread. |
erikchen | fa983faa | 2018-04-05 18:56:42 | [diff] [blame] | 25 | struct ConnectionManager::DumpProcessesForTracingTracking |
Alexei Filippov | 77f34eb | 2019-04-19 21:21:15 | [diff] [blame] | 26 | : public base::RefCountedThreadSafe<DumpProcessesForTracingTracking> { |
Erik Chen | e2d06447 | 2017-10-07 03:34:07 | [diff] [blame] | 27 | // Number of processes we're still waiting on responses for. When this gets |
| 28 | // to 0, the callback will be issued. |
| 29 | size_t waiting_responses = 0; |
| 30 | |
| 31 | // Callback to issue when dumps are complete. |
erikchen | 67fff82 | 2018-02-21 18:53:43 | [diff] [blame] | 32 | DumpProcessesForTracingCallback callback; |
Erik Chen | e2d06447 | 2017-10-07 03:34:07 | [diff] [blame] | 33 | |
| 34 | // Info about the request. |
erikchen | 53cddfe6 | 2018-02-14 23:31:29 | [diff] [blame] | 35 | VmRegions vm_regions; |
Erik Chen | e2d06447 | 2017-10-07 03:34:07 | [diff] [blame] | 36 | |
| 37 | // Collects the results. |
Alexei Filippov | da9fb73 | 2019-04-25 22:40:32 | [diff] [blame] | 38 | std::vector<memory_instrumentation::mojom::HeapProfileResultPtr> results; |
Erik Chen | e2d06447 | 2017-10-07 03:34:07 | [diff] [blame] | 39 | |
| 40 | private: |
| 41 | friend class base::RefCountedThreadSafe<DumpProcessesForTracingTracking>; |
| 42 | virtual ~DumpProcessesForTracingTracking() = default; |
| 43 | }; |
| 44 | |
erikchen | fa983faa | 2018-04-05 18:56:42 | [diff] [blame] | 45 | struct ConnectionManager::Connection { |
Alexei Filippov | 1b7b880 | 2019-04-17 22:01:43 | [diff] [blame] | 46 | Connection(CompleteCallback complete_cb, |
Ken Rockot | ced3127 | 2019-08-02 21:12:18 | [diff] [blame] | 47 | mojo::PendingRemote<mojom::ProfilingClient> client, |
erikchen | 8bc20d8 | 2018-02-14 03:21:51 | [diff] [blame] | 48 | mojom::ProcessType process_type, |
erikchen | 53cddfe6 | 2018-02-14 23:31:29 | [diff] [blame] | 49 | uint32_t sampling_rate, |
Takashi Sakamoto | 83d6a18 | 2024-04-26 06:45:08 | [diff] [blame] | 50 | mojom::StackMode stack_mode, |
| 51 | mojom::ProfilingService::AddProfilingClientCallback |
| 52 | started_profiling_callback) |
Alexei Filippov | 1b7b880 | 2019-04-17 22:01:43 | [diff] [blame] | 53 | : client(std::move(client)), |
erikchen | e382a10 | 2017-10-20 00:30:13 | [diff] [blame] | 54 | process_type(process_type), |
erikchen | 53cddfe6 | 2018-02-14 23:31:29 | [diff] [blame] | 55 | stack_mode(stack_mode), |
Takashi Sakamoto | 83d6a18 | 2024-04-26 06:45:08 | [diff] [blame] | 56 | sampling_rate(sampling_rate), |
| 57 | started_profiling_callback(std::move(started_profiling_callback)) { |
Ken Rockot | ced3127 | 2019-08-02 21:12:18 | [diff] [blame] | 58 | this->client.set_disconnect_handler(std::move(complete_cb)); |
Brett Wilson | 79b69b21 | 2017-07-12 22:29:08 | [diff] [blame] | 59 | } |
brettw | bd8214bf | 2017-06-20 03:47:03 | [diff] [blame] | 60 | |
erikchen | 53cddfe6 | 2018-02-14 23:31:29 | [diff] [blame] | 61 | bool HeapDumpNeedsVmRegions() { |
| 62 | return stack_mode == mojom::StackMode::NATIVE_WITHOUT_THREAD_NAMES || |
Sami Kyostila | 57dfe04 | 2021-06-08 21:19:49 | [diff] [blame] | 63 | stack_mode == mojom::StackMode::NATIVE_WITH_THREAD_NAMES; |
erikchen | 53cddfe6 | 2018-02-14 23:31:29 | [diff] [blame] | 64 | } |
| 65 | |
Ken Rockot | ced3127 | 2019-08-02 21:12:18 | [diff] [blame] | 66 | mojo::Remote<mojom::ProfilingClient> client; |
erikchen | e382a10 | 2017-10-20 00:30:13 | [diff] [blame] | 67 | mojom::ProcessType process_type; |
erikchen | 53cddfe6 | 2018-02-14 23:31:29 | [diff] [blame] | 68 | mojom::StackMode stack_mode; |
erikchen | 8bc20d8 | 2018-02-14 03:21:51 | [diff] [blame] | 69 | |
Erik Chen | 7e4cccd6 | 2019-12-05 23:58:58 | [diff] [blame] | 70 | bool started_profiling = false; |
| 71 | |
erikchen | 8bc20d8 | 2018-02-14 03:21:51 | [diff] [blame] | 72 | // When sampling is enabled, allocations are recorded with probability (size / |
| 73 | // sampling_rate) when size < sampling_rate. When size >= sampling_rate, the |
| 74 | // aggregate probability of an allocation being recorded is 1.0, but the math |
| 75 | // and details are tricky. See |
| 76 | // https://bugs.chromium.org/p/chromium/issues/detail?id=810748#c4. |
| 77 | // A |sampling_rate| of 1 is equivalent to recording all allocations. |
| 78 | uint32_t sampling_rate = 1; |
Takashi Sakamoto | 83d6a18 | 2024-04-26 06:45:08 | [diff] [blame] | 79 | |
| 80 | mojom::ProfilingService::AddProfilingClientCallback |
| 81 | started_profiling_callback; |
brettw | bd8214bf | 2017-06-20 03:47:03 | [diff] [blame] | 82 | }; |
| 83 | |
Alexei Filippov | 631529ee | 2019-04-18 16:39:05 | [diff] [blame] | 84 | ConnectionManager::ConnectionManager() { |
Peter Kasting | e5a38ed | 2021-10-02 03:06:35 | [diff] [blame] | 85 | metrics_timer_.Start(FROM_HERE, base::Hours(24), |
Ken Rockot | 36778cfc | 2019-12-18 16:57:05 | [diff] [blame] | 86 | base::BindRepeating(&ConnectionManager::ReportMetrics, |
| 87 | base::Unretained(this))); |
erikchen | e382a10 | 2017-10-20 00:30:13 | [diff] [blame] | 88 | } |
erikchen | fa983faa | 2018-04-05 18:56:42 | [diff] [blame] | 89 | ConnectionManager::~ConnectionManager() = default; |
brettw | bd8214bf | 2017-06-20 03:47:03 | [diff] [blame] | 90 | |
Ken Rockot | ced3127 | 2019-08-02 21:12:18 | [diff] [blame] | 91 | void ConnectionManager::OnNewConnection( |
| 92 | base::ProcessId pid, |
| 93 | mojo::PendingRemote<mojom::ProfilingClient> client, |
| 94 | mojom::ProcessType process_type, |
Joe Mason | cf9e0bc | 2023-06-06 18:30:47 | [diff] [blame] | 95 | mojom::ProfilingParamsPtr params, |
Takashi Sakamoto | 83d6a18 | 2024-04-26 06:45:08 | [diff] [blame] | 96 | mojom::ProfilingService::AddProfilingClientCallback |
| 97 | started_profiling_closure) { |
Etienne Bergeron | 97605fa | 2017-08-21 22:22:31 | [diff] [blame] | 98 | base::AutoLock lock(connections_lock_); |
Brett Wilson | 40a6bb50 | 2017-10-10 20:36:15 | [diff] [blame] | 99 | |
Erik Chen | fe6fbee | 2017-12-06 07:40:09 | [diff] [blame] | 100 | // Attempting to start profiling on an already profiled processs should have |
| 101 | // no effect. |
Takashi Sakamoto | 83d6a18 | 2024-04-26 06:45:08 | [diff] [blame] | 102 | if (connections_.find(pid) != connections_.end()) { |
| 103 | std::move(started_profiling_closure).Run(/*success=*/false); |
Erik Chen | fe6fbee | 2017-12-06 07:40:09 | [diff] [blame] | 104 | return; |
Takashi Sakamoto | 83d6a18 | 2024-04-26 06:45:08 | [diff] [blame] | 105 | } |
Erik Chen | fe6fbee | 2017-12-06 07:40:09 | [diff] [blame] | 106 | |
| 107 | // It's theoretically possible that we started profiling a process, the |
| 108 | // profiling was stopped [e.g. by hitting the 10-s timeout], and then we tried |
| 109 | // to start profiling again. The ProfilingClient will refuse to start again. |
erikchen | fa983faa | 2018-04-05 18:56:42 | [diff] [blame] | 110 | // But the ConnectionManager will not be able to distinguish this |
Erik Chen | fe6fbee | 2017-12-06 07:40:09 | [diff] [blame] | 111 | // never-started ProfilingClient from a brand new ProfilingClient that happens |
| 112 | // to share the same pid. This is a rare condition which should only happen |
| 113 | // when the user is attempting to manually start profiling for processes, so |
| 114 | // we ignore this edge case. |
Brett Wilson | 79b69b21 | 2017-07-12 22:29:08 | [diff] [blame] | 115 | |
Alexei Filippov | 1b7b880 | 2019-04-17 22:01:43 | [diff] [blame] | 116 | CompleteCallback complete_cb = |
| 117 | base::BindOnce(&ConnectionManager::OnConnectionComplete, |
| 118 | weak_factory_.GetWeakPtr(), pid); |
Erik Chen | e2d06447 | 2017-10-07 03:34:07 | [diff] [blame] | 119 | |
Jeremy Roman | 42e81a6 | 2018-03-01 19:08:59 | [diff] [blame] | 120 | auto connection = std::make_unique<Connection>( |
Alexei Filippov | 1b7b880 | 2019-04-17 22:01:43 | [diff] [blame] | 121 | std::move(complete_cb), std::move(client), process_type, |
Takashi Sakamoto | 83d6a18 | 2024-04-26 06:45:08 | [diff] [blame] | 122 | params->sampling_rate, params->stack_mode, |
| 123 | std::move(started_profiling_closure)); |
Erik Chen | 7e4cccd6 | 2019-12-05 23:58:58 | [diff] [blame] | 124 | connection->client->StartProfiling( |
| 125 | std::move(params), base::BindOnce(&ConnectionManager::OnProfilingStarted, |
Takashi Sakamoto | 83d6a18 | 2024-04-26 06:45:08 | [diff] [blame] | 126 | weak_factory_.GetWeakPtr(), pid)); |
Alexei Filippov | 1b7b880 | 2019-04-17 22:01:43 | [diff] [blame] | 127 | connections_[pid] = std::move(connection); |
brettw | bd8214bf | 2017-06-20 03:47:03 | [diff] [blame] | 128 | } |
| 129 | |
erikchen | fa983faa | 2018-04-05 18:56:42 | [diff] [blame] | 130 | std::vector<base::ProcessId> ConnectionManager::GetConnectionPids() { |
Erik Chen | fe6fbee | 2017-12-06 07:40:09 | [diff] [blame] | 131 | base::AutoLock lock(connections_lock_); |
| 132 | std::vector<base::ProcessId> results; |
| 133 | results.reserve(connections_.size()); |
Erik Chen | 7e4cccd6 | 2019-12-05 23:58:58 | [diff] [blame] | 134 | for (const auto& pair : connections_) { |
| 135 | if (pair.second->started_profiling) |
| 136 | results.push_back(pair.first); |
| 137 | } |
Erik Chen | fe6fbee | 2017-12-06 07:40:09 | [diff] [blame] | 138 | return results; |
| 139 | } |
| 140 | |
erikchen | 53cddfe6 | 2018-02-14 23:31:29 | [diff] [blame] | 141 | std::vector<base::ProcessId> |
erikchen | fa983faa | 2018-04-05 18:56:42 | [diff] [blame] | 142 | ConnectionManager::GetConnectionPidsThatNeedVmRegions() { |
erikchen | 53cddfe6 | 2018-02-14 23:31:29 | [diff] [blame] | 143 | base::AutoLock lock(connections_lock_); |
| 144 | std::vector<base::ProcessId> results; |
| 145 | results.reserve(connections_.size()); |
| 146 | for (const auto& pair : connections_) { |
| 147 | if (pair.second->HeapDumpNeedsVmRegions()) |
| 148 | results.push_back(pair.first); |
| 149 | } |
| 150 | return results; |
| 151 | } |
| 152 | |
erikchen | fa983faa | 2018-04-05 18:56:42 | [diff] [blame] | 153 | void ConnectionManager::OnConnectionComplete(base::ProcessId pid) { |
Etienne Bergeron | 97605fa | 2017-08-21 22:22:31 | [diff] [blame] | 154 | base::AutoLock lock(connections_lock_); |
Albert J. Wong | 59d85acb | 2017-08-10 00:50:57 | [diff] [blame] | 155 | auto found = connections_.find(pid); |
brettw | bd8214bf | 2017-06-20 03:47:03 | [diff] [blame] | 156 | CHECK(found != connections_.end()); |
Takashi Sakamoto | 83d6a18 | 2024-04-26 06:45:08 | [diff] [blame] | 157 | if (!found->second->started_profiling_callback.is_null()) { |
| 158 | std::move(found->second->started_profiling_callback).Run(/*success=*/false); |
| 159 | } |
brettw | bd8214bf | 2017-06-20 03:47:03 | [diff] [blame] | 160 | connections_.erase(found); |
brettw | bd8214bf | 2017-06-20 03:47:03 | [diff] [blame] | 161 | } |
| 162 | |
Erik Chen | 7e4cccd6 | 2019-12-05 23:58:58 | [diff] [blame] | 163 | void ConnectionManager::OnProfilingStarted(base::ProcessId pid) { |
| 164 | base::AutoLock lock(connections_lock_); |
| 165 | |
| 166 | // It's possible that the client disconnected in the short time before |
| 167 | // profiling started. |
| 168 | auto found = connections_.find(pid); |
Takashi Sakamoto | 83d6a18 | 2024-04-26 06:45:08 | [diff] [blame] | 169 | if (found != connections_.end()) { |
Erik Chen | 7e4cccd6 | 2019-12-05 23:58:58 | [diff] [blame] | 170 | found->second->started_profiling = true; |
Takashi Sakamoto | 83d6a18 | 2024-04-26 06:45:08 | [diff] [blame] | 171 | std::move(found->second->started_profiling_callback).Run(/*success=*/true); |
| 172 | } |
Erik Chen | 7e4cccd6 | 2019-12-05 23:58:58 | [diff] [blame] | 173 | } |
| 174 | |
erikchen | fa983faa | 2018-04-05 18:56:42 | [diff] [blame] | 175 | void ConnectionManager::ReportMetrics() { |
erikchen | e382a10 | 2017-10-20 00:30:13 | [diff] [blame] | 176 | base::AutoLock lock(connections_lock_); |
| 177 | for (auto& pair : connections_) { |
Alexei Filippov | 29688e1 | 2019-04-29 20:26:18 | [diff] [blame] | 178 | UMA_HISTOGRAM_ENUMERATION("HeapProfiling.ProfiledProcess.Type", |
erikchen | 102fe21 | 2018-04-06 13:02:10 | [diff] [blame] | 179 | pair.second->process_type, |
| 180 | static_cast<int>(mojom::ProcessType::LAST) + 1); |
erikchen | e382a10 | 2017-10-20 00:30:13 | [diff] [blame] | 181 | } |
| 182 | } |
| 183 | |
erikchen | fa983faa | 2018-04-05 18:56:42 | [diff] [blame] | 184 | void ConnectionManager::DumpProcessesForTracing( |
erikchen | d1b8bc5 | 2017-12-21 18:12:42 | [diff] [blame] | 185 | bool strip_path_from_mapped_files, |
ssid | 035cbfb | 2021-07-24 20:35:57 | [diff] [blame] | 186 | bool write_proto, |
erikchen | 67fff82 | 2018-02-21 18:53:43 | [diff] [blame] | 187 | DumpProcessesForTracingCallback callback, |
erikchen | 53cddfe6 | 2018-02-14 23:31:29 | [diff] [blame] | 188 | VmRegions vm_regions) { |
Etienne Bergeron | 97605fa | 2017-08-21 22:22:31 | [diff] [blame] | 189 | base::AutoLock lock(connections_lock_); |
erikchen | 66af016 | 2017-08-02 19:53:19 | [diff] [blame] | 190 | |
Albert J. Wong | bd5bd90 | 2017-11-09 19:56:15 | [diff] [blame] | 191 | // Early out if there are no connections. |
| 192 | if (connections_.empty()) { |
| 193 | std::move(callback).Run( |
Alexei Filippov | da9fb73 | 2019-04-25 22:40:32 | [diff] [blame] | 194 | std::vector<memory_instrumentation::mojom::HeapProfileResultPtr>()); |
Albert J. Wong | bd5bd90 | 2017-11-09 19:56:15 | [diff] [blame] | 195 | return; |
| 196 | } |
| 197 | |
Erik Chen | e2d06447 | 2017-10-07 03:34:07 | [diff] [blame] | 198 | auto tracking = base::MakeRefCounted<DumpProcessesForTracingTracking>(); |
| 199 | tracking->waiting_responses = connections_.size(); |
| 200 | tracking->callback = std::move(callback); |
erikchen | 53cddfe6 | 2018-02-14 23:31:29 | [diff] [blame] | 201 | tracking->vm_regions = std::move(vm_regions); |
Erik Chen | e2d06447 | 2017-10-07 03:34:07 | [diff] [blame] | 202 | tracking->results.reserve(connections_.size()); |
erikchen | 1ca0e5f | 2017-10-06 22:06:14 | [diff] [blame] | 203 | |
Erik Chen | e2d06447 | 2017-10-07 03:34:07 | [diff] [blame] | 204 | for (auto& it : connections_) { |
| 205 | base::ProcessId pid = it.first; |
| 206 | Connection* connection = it.second.get(); |
ssid | 035cbfb | 2021-07-24 20:35:57 | [diff] [blame] | 207 | |
Alexei Filippov | 1b7b880 | 2019-04-17 22:01:43 | [diff] [blame] | 208 | connection->client->RetrieveHeapProfile(base::BindOnce( |
| 209 | &ConnectionManager::HeapProfileRetrieved, weak_factory_.GetWeakPtr(), |
| 210 | tracking, pid, connection->process_type, strip_path_from_mapped_files, |
| 211 | connection->sampling_rate)); |
Erik Chen | e2d06447 | 2017-10-07 03:34:07 | [diff] [blame] | 212 | } |
| 213 | } |
| 214 | |
Alexei Filippov | da9fb73 | 2019-04-25 22:40:32 | [diff] [blame] | 215 | bool ConnectionManager::ConvertProfileToExportParams( |
| 216 | mojom::HeapProfilePtr profile, |
Alexei Filippov | e48985e | 2019-02-01 00:27:41 | [diff] [blame] | 217 | uint32_t sampling_rate, |
Alexei Filippov | da9fb73 | 2019-04-25 22:40:32 | [diff] [blame] | 218 | ExportParams* params) { |
| 219 | AllocationMap allocs; |
Alexei Filippov | 1b7b880 | 2019-04-17 22:01:43 | [diff] [blame] | 220 | ContextMap context_map; |
| 221 | AddressToStringMap string_map; |
Alexei Filippov | e48985e | 2019-02-01 00:27:41 | [diff] [blame] | 222 | |
Alexei Filippov | e48985e | 2019-02-01 00:27:41 | [diff] [blame] | 223 | for (const mojom::HeapProfileSamplePtr& sample : profile->samples) { |
| 224 | int context_id = 0; |
| 225 | if (sample->context_id) { |
| 226 | auto it = profile->strings.find(sample->context_id); |
Alexei Filippov | da9fb73 | 2019-04-25 22:40:32 | [diff] [blame] | 227 | if (it == profile->strings.end()) |
| 228 | return false; |
Alexei Filippov | e48985e | 2019-02-01 00:27:41 | [diff] [blame] | 229 | const std::string& context = it->second; |
| 230 | // Escape the strings early, to simplify exporting a heap dump. |
| 231 | std::string escaped_context; |
| 232 | base::EscapeJSONString(context, false /* put_in_quotes */, |
| 233 | &escaped_context); |
| 234 | context_id = context_map |
| 235 | .emplace(std::move(escaped_context), |
| 236 | static_cast<int>(context_map.size() + 1)) |
| 237 | .first->second; |
| 238 | } |
Alexei Filippov | 0a19454 | 2019-04-22 22:45:46 | [diff] [blame] | 239 | |
Erik Chen | d18561a | 2019-12-09 22:15:56 | [diff] [blame] | 240 | size_t alloc_size = sample->total; |
| 241 | float alloc_count = 1; |
| 242 | if (sample->size != 0) |
| 243 | alloc_count = float(sample->total) / float(sample->size); |
Alexei Filippov | 0a19454 | 2019-04-22 22:45:46 | [diff] [blame] | 244 | |
Alexei Filippov | 77f34eb | 2019-04-19 21:21:15 | [diff] [blame] | 245 | std::vector<Address> stack(sample->stack.begin(), sample->stack.end()); |
Alexei Filippov | 0a19454 | 2019-04-22 22:45:46 | [diff] [blame] | 246 | AllocationMetrics& metrics = |
Alexei Filippov | da9fb73 | 2019-04-25 22:40:32 | [diff] [blame] | 247 | allocs |
Alexei Filippov | 0a19454 | 2019-04-22 22:45:46 | [diff] [blame] | 248 | .emplace(std::piecewise_construct, |
| 249 | std::forward_as_tuple(sample->allocator, std::move(stack), |
| 250 | context_id), |
| 251 | std::forward_as_tuple()) |
| 252 | .first->second; |
| 253 | metrics.size += alloc_size; |
| 254 | metrics.count += alloc_count; |
Alexei Filippov | e48985e | 2019-02-01 00:27:41 | [diff] [blame] | 255 | } |
| 256 | |
| 257 | for (const auto& str : profile->strings) { |
| 258 | std::string quoted_string; |
| 259 | // Escape the strings before saving them, to simplify exporting a heap dump. |
| 260 | base::EscapeJSONString(str.second, false /* put_in_quotes */, |
| 261 | "ed_string); |
| 262 | string_map.emplace(str.first, std::move(quoted_string)); |
| 263 | } |
| 264 | |
Alexei Filippov | da9fb73 | 2019-04-25 22:40:32 | [diff] [blame] | 265 | params->allocs = std::move(allocs); |
| 266 | params->context_map = std::move(context_map); |
| 267 | params->mapped_strings = std::move(string_map); |
| 268 | return true; |
Alexei Filippov | e48985e | 2019-02-01 00:27:41 | [diff] [blame] | 269 | } |
| 270 | |
Alexei Filippov | da9fb73 | 2019-04-25 22:40:32 | [diff] [blame] | 271 | void ConnectionManager::HeapProfileRetrieved( |
Erik Chen | e2d06447 | 2017-10-07 03:34:07 | [diff] [blame] | 272 | scoped_refptr<DumpProcessesForTracingTracking> tracking, |
| 273 | base::ProcessId pid, |
Erik Chen | a610d55 | 2017-10-20 22:29:49 | [diff] [blame] | 274 | mojom::ProcessType process_type, |
erikchen | d1b8bc5 | 2017-12-21 18:12:42 | [diff] [blame] | 275 | bool strip_path_from_mapped_files, |
Alexei Filippov | da9fb73 | 2019-04-25 22:40:32 | [diff] [blame] | 276 | uint32_t sampling_rate, |
| 277 | mojom::HeapProfilePtr profile) { |
Erik Chen | e2d06447 | 2017-10-07 03:34:07 | [diff] [blame] | 278 | // All code paths through here must issue the callback when waiting_responses |
| 279 | // is 0 or the browser will wait forever for the dump. |
| 280 | DCHECK(tracking->waiting_responses > 0); |
erikchen | 66af016 | 2017-08-02 19:53:19 | [diff] [blame] | 281 | |
Alexei Filippov | da9fb73 | 2019-04-25 22:40:32 | [diff] [blame] | 282 | ExportParams params; |
| 283 | bool success = |
| 284 | ConvertProfileToExportParams(std::move(profile), sampling_rate, ¶ms); |
| 285 | if (success) { |
| 286 | params.process_type = process_type; |
| 287 | params.strip_path_from_mapped_files = strip_path_from_mapped_files; |
| 288 | params.next_id = next_id_; |
| 289 | |
| 290 | auto it = tracking->vm_regions.find(pid); |
| 291 | if (it != tracking->vm_regions.end()) |
| 292 | params.maps = std::move(it->second); |
| 293 | |
| 294 | memory_instrumentation::mojom::HeapProfileResultPtr result = |
| 295 | memory_instrumentation::mojom::HeapProfileResult::New(); |
| 296 | result->pid = pid; |
| 297 | result->json = ExportMemoryMapsAndV2StackTraceToJSON(¶ms); |
| 298 | tracking->results.push_back(std::move(result)); |
| 299 | next_id_ = params.next_id; |
Erik Chen | 5eaed0e | 2017-08-26 22:16:49 | [diff] [blame] | 300 | } |
| 301 | |
Alexei Filippov | da9fb73 | 2019-04-25 22:40:32 | [diff] [blame] | 302 | // When all responses complete, issue done callback. |
| 303 | if (--tracking->waiting_responses == 0) |
| 304 | std::move(tracking->callback).Run(std::move(tracking->results)); |
Erik Chen | e2d06447 | 2017-10-07 03:34:07 | [diff] [blame] | 305 | } |
Erik Chen | 22f66c6d | 2017-10-06 23:48:50 | [diff] [blame] | 306 | |
erikchen | 102fe21 | 2018-04-06 13:02:10 | [diff] [blame] | 307 | } // namespace heap_profiling |