OLD | NEW |
---|---|
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 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/process/process_metrics.h" | 5 #include "base/process/process_metrics.h" |
6 | 6 |
7 #include <dirent.h> | 7 #include <dirent.h> |
8 #include <fcntl.h> | |
9 #include <sys/stat.h> | |
8 #include <sys/time.h> | 10 #include <sys/time.h> |
9 #include <sys/types.h> | 11 #include <sys/types.h> |
10 #include <unistd.h> | 12 #include <unistd.h> |
11 | 13 |
12 #include "base/file_util.h" | 14 #include "base/file_util.h" |
15 #include "base/files/memory_mapped_file.h" | |
13 #include "base/logging.h" | 16 #include "base/logging.h" |
14 #include "base/process/internal_linux.h" | 17 #include "base/process/internal_linux.h" |
15 #include "base/string_util.h" | 18 #include "base/string_util.h" |
16 #include "base/strings/string_number_conversions.h" | 19 #include "base/strings/string_number_conversions.h" |
17 #include "base/strings/string_split.h" | 20 #include "base/strings/string_split.h" |
18 #include "base/strings/string_tokenizer.h" | 21 #include "base/strings/string_tokenizer.h" |
19 #include "base/sys_info.h" | 22 #include "base/sys_info.h" |
20 #include "base/threading/thread_restrictions.h" | 23 #include "base/threading/thread_restrictions.h" |
21 | 24 |
22 namespace base { | 25 namespace base { |
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
149 | 152 |
150 if (private_bytes) | 153 if (private_bytes) |
151 *private_bytes = ws_usage.priv * 1024; | 154 *private_bytes = ws_usage.priv * 1024; |
152 | 155 |
153 if (shared_bytes) | 156 if (shared_bytes) |
154 *shared_bytes = ws_usage.shared * 1024; | 157 *shared_bytes = ws_usage.shared * 1024; |
155 | 158 |
156 return true; | 159 return true; |
157 } | 160 } |
158 | 161 |
159 // Private and Shared working set sizes are obtained from /proc/<pid>/statm. | |
160 bool ProcessMetrics::GetWorkingSetKBytes(WorkingSetKBytes* ws_usage) const { | 162 bool ProcessMetrics::GetWorkingSetKBytes(WorkingSetKBytes* ws_usage) const { |
161 // Use statm instead of smaps because smaps is: | 163 #if defined(OS_CHROMEOS) |
162 // a) Large and slow to parse. | 164 if (GetWorkingSetKBytesTotmaps(ws_usage)) |
163 // b) Unavailable in the SUID sandbox. | 165 return true; |
164 | 166 #endif |
165 // First we need to get the page size, since everything is measured in pages. | 167 return GetWorkingSetKBytesStatm(ws_usage); |
166 // For details, see: man 5 proc. | |
167 const int page_size_kb = getpagesize() / 1024; | |
168 if (page_size_kb <= 0) | |
169 return false; | |
170 | |
171 std::string statm; | |
172 { | |
173 FilePath statm_file = internal::GetProcPidDir(process_).Append("statm"); | |
174 // Synchronously reading files in /proc is safe. | |
175 ThreadRestrictions::ScopedAllowIO allow_io; | |
176 bool ret = file_util::ReadFileToString(statm_file, &statm); | |
177 if (!ret || statm.length() == 0) | |
178 return false; | |
179 } | |
180 | |
181 std::vector<std::string> statm_vec; | |
182 SplitString(statm, ' ', &statm_vec); | |
183 if (statm_vec.size() != 7) | |
184 return false; // Not the format we expect. | |
185 | |
186 int statm_rss, statm_shared; | |
187 StringToInt(statm_vec[1], &statm_rss); | |
188 StringToInt(statm_vec[2], &statm_shared); | |
189 | |
190 ws_usage->priv = (statm_rss - statm_shared) * page_size_kb; | |
191 ws_usage->shared = statm_shared * page_size_kb; | |
192 | |
193 // Sharable is not calculated, as it does not provide interesting data. | |
194 ws_usage->shareable = 0; | |
195 | |
196 return true; | |
197 } | 168 } |
198 | 169 |
199 double ProcessMetrics::GetCPUUsage() { | 170 double ProcessMetrics::GetCPUUsage() { |
200 // This queries the /proc-specific scaling factor which is | 171 // This queries the /proc-specific scaling factor which is |
201 // conceptually the system hertz. To dump this value on another | 172 // conceptually the system hertz. To dump this value on another |
202 // system, try | 173 // system, try |
203 // od -t dL /proc/self/auxv | 174 // od -t dL /proc/self/auxv |
204 // and look for the number after 17 in the output; mine is | 175 // and look for the number after 17 in the output; mine is |
205 // 0000040 17 100 3 134512692 | 176 // 0000040 17 100 3 134512692 |
206 // which means the answer is 100. | 177 // which means the answer is 100. |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
285 } | 256 } |
286 | 257 |
287 ProcessMetrics::ProcessMetrics(ProcessHandle process) | 258 ProcessMetrics::ProcessMetrics(ProcessHandle process) |
288 : process_(process), | 259 : process_(process), |
289 last_time_(0), | 260 last_time_(0), |
290 last_system_time_(0), | 261 last_system_time_(0), |
291 last_cpu_(0) { | 262 last_cpu_(0) { |
292 processor_count_ = base::SysInfo::NumberOfProcessors(); | 263 processor_count_ = base::SysInfo::NumberOfProcessors(); |
293 } | 264 } |
294 | 265 |
266 #if defined(OS_CHROMEOS) | |
267 // Private, Shared and Proportional working set sizes are obtained from | |
268 // /proc/<pid>/totmaps | |
269 bool ProcessMetrics::GetWorkingSetKBytesTotmaps(WorkingSetKBytes *ws_usage) | |
270 const { | |
271 // The format of /proc/<pid>/totmaps is: | |
272 // | |
273 // Rss: 6120 kB | |
274 // Pss: 3335 kB | |
275 // Shared_Clean: 1008 kB | |
276 // Shared_Dirty: 4012 kB | |
277 // Private_Clean: 4 kB | |
278 // Private_Dirty: 1096 kB | |
279 // ... | |
280 const size_t kPssIndex = 4; | |
281 const size_t kPrivate_CleanIndex = 13; | |
282 const size_t kPrivate_DirtyIndex = 16; | |
283 | |
284 std::string totmaps_data; | |
285 { | |
286 FilePath totmaps_file = internal::GetProcPidDir(process_).Append("totmaps"); | |
287 ThreadRestrictions::ScopedAllowIO allow_io; | |
288 bool ret = file_util::ReadFileToString(totmaps_file, &totmaps_data); | |
289 if (!ret || totmaps_data.length() == 0) | |
290 return false; | |
291 } | |
292 | |
293 std::vector<std::string> totmaps_fields; | |
294 SplitStringAlongWhitespace(totmaps_data, &totmaps_fields); | |
295 | |
296 DCHECK_EQ(totmaps_fields[kPssIndex-1], "Pss:"); | |
Lei Zhang
2013/05/28 03:37:41
nit: prefer DCHECK_EQ(expected, actual)
| |
297 DCHECK_EQ(totmaps_fields[kPrivate_CleanIndex-1], "Private_Clean:"); | |
298 DCHECK_EQ(totmaps_fields[kPrivate_DirtyIndex-1], "Private_Dirty:"); | |
299 | |
300 int pss, private_clean, private_dirty; | |
301 base::StringToInt(totmaps_fields[kPssIndex], &pss); | |
Lei Zhang
2013/05/28 03:37:41
nit: already in namespace base, no need for base::
Lei Zhang
2013/05/28 03:37:41
StringToInt() can fail - check return result.
Get
| |
302 base::StringToInt(totmaps_fields[kPrivate_CleanIndex], &private_clean); | |
303 base::StringToInt(totmaps_fields[kPrivate_DirtyIndex], &private_dirty); | |
304 | |
305 ws_usage->priv = private_clean + private_dirty; | |
306 ws_usage->shared = pss; | |
307 ws_usage->shareable = 0; | |
308 | |
309 return true; | |
310 } | |
311 #endif | |
312 | |
313 // Private and Shared working set sizes are obtained from /proc/<pid>/statm. | |
314 bool ProcessMetrics::GetWorkingSetKBytesStatm(WorkingSetKBytes* ws_usage) | |
315 const { | |
316 // Use statm instead of smaps because smaps is: | |
317 // a) Large and slow to parse. | |
318 // b) Unavailable in the SUID sandbox. | |
319 | |
320 // First we need to get the page size, since everything is measured in pages. | |
321 // For details, see: man 5 proc. | |
322 const int page_size_kb = getpagesize() / 1024; | |
323 if (page_size_kb <= 0) | |
324 return false; | |
325 | |
326 std::string statm; | |
327 { | |
328 FilePath statm_file = internal::GetProcPidDir(process_).Append("statm"); | |
329 // Synchronously reading files in /proc is safe. | |
330 ThreadRestrictions::ScopedAllowIO allow_io; | |
331 bool ret = file_util::ReadFileToString(statm_file, &statm); | |
332 if (!ret || statm.length() == 0) | |
333 return false; | |
334 } | |
335 | |
336 std::vector<std::string> statm_vec; | |
337 SplitString(statm, ' ', &statm_vec); | |
338 if (statm_vec.size() != 7) | |
339 return false; // Not the format we expect. | |
340 | |
341 int statm_rss, statm_shared; | |
342 StringToInt(statm_vec[1], &statm_rss); | |
343 StringToInt(statm_vec[2], &statm_shared); | |
344 | |
345 ws_usage->priv = (statm_rss - statm_shared) * page_size_kb; | |
346 ws_usage->shared = statm_shared * page_size_kb; | |
347 | |
348 // Sharable is not calculated, as it does not provide interesting data. | |
349 ws_usage->shareable = 0; | |
350 | |
351 return true; | |
352 } | |
353 | |
295 size_t GetSystemCommitCharge() { | 354 size_t GetSystemCommitCharge() { |
296 SystemMemoryInfoKB meminfo; | 355 SystemMemoryInfoKB meminfo; |
297 if (!GetSystemMemoryInfo(&meminfo)) | 356 if (!GetSystemMemoryInfo(&meminfo)) |
298 return 0; | 357 return 0; |
299 return meminfo.total - meminfo.free - meminfo.buffers - meminfo.cached; | 358 return meminfo.total - meminfo.free - meminfo.buffers - meminfo.cached; |
300 } | 359 } |
301 | 360 |
302 // Exposed for testing. | 361 // Exposed for testing. |
303 int ParseProcStatCPU(const std::string& input) { | 362 int ParseProcStatCPU(const std::string& input) { |
304 std::vector<std::string> proc_stats; | 363 std::vector<std::string> proc_stats; |
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
430 if (num_res == 1) | 489 if (num_res == 1) |
431 meminfo->gem_size += mali_size; | 490 meminfo->gem_size += mali_size; |
432 } | 491 } |
433 #endif // defined(ARCH_CPU_ARM_FAMILY) | 492 #endif // defined(ARCH_CPU_ARM_FAMILY) |
434 #endif // defined(OS_CHROMEOS) | 493 #endif // defined(OS_CHROMEOS) |
435 | 494 |
436 return true; | 495 return true; |
437 } | 496 } |
438 | 497 |
439 } // namespace base | 498 } // namespace base |
OLD | NEW |