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

Side by Side Diff: components/tracing/common/process_metrics_memory_dump_provider.cc

Issue 2568313004: [memory-infra] Implement PollFastMemoryTotal in ProcessMetricsMemoryDumpProvider. (Closed)
Patch Set: nits. Created 4 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 "components/tracing/common/process_metrics_memory_dump_provider.h" 5 #include "components/tracing/common/process_metrics_memory_dump_provider.h"
6 6
7 #include <fcntl.h> 7 #include <fcntl.h>
8 #include <stdint.h> 8 #include <stdint.h>
9 9
10 #include <map> 10 #include <map>
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after
148 if (should_add_current_region) { 148 if (should_add_current_region) {
149 pmm->AddVMRegion(region); 149 pmm->AddVMRegion(region);
150 ++num_valid_regions; 150 ++num_valid_regions;
151 should_add_current_region = false; 151 should_add_current_region = false;
152 } 152 }
153 } 153 }
154 } 154 }
155 } 155 }
156 return num_valid_regions; 156 return num_valid_regions;
157 } 157 }
158
159 bool GetResidentSizeFromStatmFile(int fd, uint64_t* resident_pages) {
160 lseek(fd, 0, SEEK_SET);
161 char line[kMaxLineSize];
162 int res = read(fd, line, kMaxLineSize - 1);
163 if (res <= 0)
164 return false;
165 line[res] = '\0';
166 int num_scanned = sscanf(line, "%*s %" SCNu64, resident_pages);
167 return num_scanned == 1;
168 }
169
158 #endif // defined(OS_LINUX) || defined(OS_ANDROID) 170 #endif // defined(OS_LINUX) || defined(OS_ANDROID)
159 171
160 std::unique_ptr<base::ProcessMetrics> CreateProcessMetrics( 172 std::unique_ptr<base::ProcessMetrics> CreateProcessMetrics(
161 base::ProcessId process) { 173 base::ProcessId process) {
162 if (process == base::kNullProcessId) 174 if (process == base::kNullProcessId)
163 return base::ProcessMetrics::CreateCurrentProcessMetrics(); 175 return base::ProcessMetrics::CreateCurrentProcessMetrics();
164 #if defined(OS_LINUX) || defined(OS_ANDROID) 176 #if defined(OS_LINUX) || defined(OS_ANDROID)
165 // Just pass ProcessId instead of handle since they are the same in linux and 177 // Just pass ProcessId instead of handle since they are the same in linux and
166 // android. 178 // android.
167 return base::ProcessMetrics::CreateProcessMetrics(process); 179 return base::ProcessMetrics::CreateProcessMetrics(process);
168 #else 180 #else
169 // Creating process metrics for child processes in mac or windows requires 181 // Creating process metrics for child processes in mac or windows requires
170 // additional information like ProcessHandle or port provider. 182 // additional information like ProcessHandle or port provider.
171 NOTREACHED(); 183 NOTREACHED();
172 return std::unique_ptr<base::ProcessMetrics>(); 184 return std::unique_ptr<base::ProcessMetrics>();
173 #endif // defined(OS_LINUX) || defined(OS_ANDROID) 185 #endif // defined(OS_LINUX) || defined(OS_ANDROID)
174 } 186 }
175 187
176 } // namespace 188 } // namespace
177 189
178 // static 190 // static
179 uint64_t ProcessMetricsMemoryDumpProvider::rss_bytes_for_testing = 0; 191 uint64_t ProcessMetricsMemoryDumpProvider::rss_bytes_for_testing = 0;
180 192
181 #if defined(OS_LINUX) || defined(OS_ANDROID) 193 #if defined(OS_LINUX) || defined(OS_ANDROID)
182 194
183 // static 195 // static
184 FILE* ProcessMetricsMemoryDumpProvider::proc_smaps_for_testing = nullptr; 196 FILE* ProcessMetricsMemoryDumpProvider::proc_smaps_for_testing = nullptr;
185 197
198 // static
199 int ProcessMetricsMemoryDumpProvider::fast_polling_statm_fd_for_testing = -1;
200
186 bool ProcessMetricsMemoryDumpProvider::DumpProcessMemoryMaps( 201 bool ProcessMetricsMemoryDumpProvider::DumpProcessMemoryMaps(
187 const base::trace_event::MemoryDumpArgs& args, 202 const base::trace_event::MemoryDumpArgs& args,
188 base::trace_event::ProcessMemoryDump* pmd) { 203 base::trace_event::ProcessMemoryDump* pmd) {
189 uint32_t res = 0; 204 uint32_t res = 0;
190 if (proc_smaps_for_testing) { 205 if (proc_smaps_for_testing) {
191 res = ReadLinuxProcSmapsFile(proc_smaps_for_testing, pmd->process_mmaps()); 206 res = ReadLinuxProcSmapsFile(proc_smaps_for_testing, pmd->process_mmaps());
192 } else { 207 } else {
193 std::string file_name = "/proc/" + (process_ == base::kNullProcessId 208 std::string file_name = "/proc/" + (process_ == base::kNullProcessId
194 ? "self" 209 ? "self"
195 : base::IntToString(process_)) + 210 : base::IntToString(process_)) +
196 "/smaps"; 211 "/smaps";
197 base::ScopedFILE smaps_file(fopen(file_name.c_str(), "r")); 212 base::ScopedFILE smaps_file(fopen(file_name.c_str(), "r"));
198 res = ReadLinuxProcSmapsFile(smaps_file.get(), pmd->process_mmaps()); 213 res = ReadLinuxProcSmapsFile(smaps_file.get(), pmd->process_mmaps());
199 } 214 }
200 215
201 if (res) 216 if (res)
202 pmd->set_has_process_mmaps(); 217 pmd->set_has_process_mmaps();
203 return res; 218 return res;
204 } 219 }
205 #endif // defined(OS_LINUX) || defined(OS_ANDROID) 220 #endif // defined(OS_LINUX) || defined(OS_ANDROID)
206 221
207 // static 222 // static
208 void ProcessMetricsMemoryDumpProvider::RegisterForProcess( 223 void ProcessMetricsMemoryDumpProvider::RegisterForProcess(
209 base::ProcessId process) { 224 base::ProcessId process) {
210 std::unique_ptr<ProcessMetricsMemoryDumpProvider> metrics_provider( 225 std::unique_ptr<ProcessMetricsMemoryDumpProvider> metrics_provider(
211 new ProcessMetricsMemoryDumpProvider(process)); 226 new ProcessMetricsMemoryDumpProvider(process));
212 base::trace_event::MemoryDumpProvider::Options options; 227 base::trace_event::MemoryDumpProvider::Options options;
213 options.target_pid = process; 228 options.target_pid = process;
229 options.is_fast_polling_supported = true;
214 base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider( 230 base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider(
215 metrics_provider.get(), "ProcessMemoryMetrics", nullptr, options); 231 metrics_provider.get(), "ProcessMemoryMetrics", nullptr, options);
216 bool did_insert = 232 bool did_insert =
217 g_dump_providers_map.Get() 233 g_dump_providers_map.Get()
218 .insert(std::make_pair(process, std::move(metrics_provider))) 234 .insert(std::make_pair(process, std::move(metrics_provider)))
219 .second; 235 .second;
220 if (!did_insert) { 236 if (!did_insert) {
221 DLOG(ERROR) << "ProcessMetricsMemoryDumpProvider already registered for " 237 DLOG(ERROR) << "ProcessMetricsMemoryDumpProvider already registered for "
222 << (process == base::kNullProcessId 238 << (process == base::kNullProcessId
223 ? "current process" 239 ? "current process"
224 : "process id " + base::IntToString(process)); 240 : "process id " + base::IntToString(process));
225 } 241 }
226 } 242 }
227 243
228 // static 244 // static
229 void ProcessMetricsMemoryDumpProvider::UnregisterForProcess( 245 void ProcessMetricsMemoryDumpProvider::UnregisterForProcess(
230 base::ProcessId process) { 246 base::ProcessId process) {
231 auto iter = g_dump_providers_map.Get().find(process); 247 auto iter = g_dump_providers_map.Get().find(process);
232 if (iter == g_dump_providers_map.Get().end()) { 248 if (iter == g_dump_providers_map.Get().end())
233 return; 249 return;
234 }
235 base::trace_event::MemoryDumpManager::GetInstance() 250 base::trace_event::MemoryDumpManager::GetInstance()
236 ->UnregisterAndDeleteDumpProviderSoon(std::move(iter->second)); 251 ->UnregisterAndDeleteDumpProviderSoon(std::move(iter->second));
237 g_dump_providers_map.Get().erase(iter); 252 g_dump_providers_map.Get().erase(iter);
238 } 253 }
239 254
240 ProcessMetricsMemoryDumpProvider::ProcessMetricsMemoryDumpProvider( 255 ProcessMetricsMemoryDumpProvider::ProcessMetricsMemoryDumpProvider(
241 base::ProcessId process) 256 base::ProcessId process)
242 : process_(process), 257 : process_(process),
243 process_metrics_(CreateProcessMetrics(process)), 258 process_metrics_(CreateProcessMetrics(process)),
244 is_rss_peak_resettable_(true) {} 259 is_rss_peak_resettable_(true) {}
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
315 #endif // !defined(OS_IOS) 330 #endif // !defined(OS_IOS)
316 331
317 pmd->process_totals()->set_resident_set_bytes(rss_bytes); 332 pmd->process_totals()->set_resident_set_bytes(rss_bytes);
318 pmd->set_has_process_totals(); 333 pmd->set_has_process_totals();
319 pmd->process_totals()->set_peak_resident_set_bytes(peak_rss_bytes); 334 pmd->process_totals()->set_peak_resident_set_bytes(peak_rss_bytes);
320 335
321 // Returns true even if other metrics failed, since rss is reported. 336 // Returns true even if other metrics failed, since rss is reported.
322 return true; 337 return true;
323 } 338 }
324 339
340 void ProcessMetricsMemoryDumpProvider::PollFastMemoryTotal(
341 uint64_t* memory_total) {
342 *memory_total = 0;
343 #if defined(OS_LINUX) || defined(OS_ANDROID)
344 int statm_fd = fast_polling_statm_fd_for_testing;
345 if (statm_fd == -1) {
346 if (!fast_polling_statm_fd_.is_valid()) {
347 std::string name = "/proc/" + (process_ == base::kNullProcessId
348 ? "self"
349 : base::IntToString(process_)) +
350 "/statm";
351 fast_polling_statm_fd_.reset(open(name.c_str(), O_RDONLY));
352 DCHECK(fast_polling_statm_fd_.is_valid());
353 }
354 statm_fd = fast_polling_statm_fd_.get();
355 }
356 if (statm_fd == -1)
357 return;
358
359 uint64_t rss_pages = 0;
360 if (!GetResidentSizeFromStatmFile(statm_fd, &rss_pages))
361 return;
362
363 static size_t page_size = base::GetPageSize();
364 *memory_total = rss_pages * page_size;
365 #else
366 *memory_total = process_metrics_->GetWorkingSetSize();
367 #endif
368 }
369
370 void ProcessMetricsMemoryDumpProvider::SuspendFastMemoryPolling() {
371 #if defined(OS_LINUX) || defined(OS_ANDROID)
372 fast_polling_statm_fd_.reset();
373 #endif
374 }
375
325 } // namespace tracing 376 } // namespace tracing
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698