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

Side by Side Diff: base/process_util_mac.mm

Issue 500118: Fix cpu/memory measurements on OS X. (Closed)
Patch Set: foobar Created 11 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 (c) 2008 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2008 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 5
6 #include "base/process_util.h" 6 #include "base/process_util.h"
7 7
8 #import <Cocoa/Cocoa.h> 8 #import <Cocoa/Cocoa.h>
9 #include <crt_externs.h> 9 #include <crt_externs.h>
10 #include <mach/mach.h> 10 #include <mach/mach.h>
(...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after
175 // Don't need to check the name, we did that w/in CheckForNextProcess. 175 // Don't need to check the name, we did that w/in CheckForNextProcess.
176 if (!filter_) 176 if (!filter_)
177 return true; 177 return true;
178 return filter_->Includes(entry_.pid, entry_.ppid); 178 return filter_->Includes(entry_.pid, entry_.ppid);
179 } 179 }
180 180
181 181
182 // ------------------------------------------------------------------------ 182 // ------------------------------------------------------------------------
183 // NOTE: about ProcessMetrics 183 // NOTE: about ProcessMetrics
184 // 184 //
185 // Mac doesn't have /proc, and getting a mach task from a pid for another 185 // Getting a mach task from a pid for another process requires permissions in
186 // process requires permissions, so there doesn't really seem to be a way 186 // general, so there doesn't really seem to be a way to do these (and spinning
Mark Mentovai 2009/12/18 22:18:24 Revise this. The parenthetical never ends.
Nico 2009/12/18 22:46:52 Done.
187 // to do these (and spinning up ps to fetch each stats seems dangerous to 187 // up ps to fetch each stats seems dangerous to put in a base api for anyone to
188 // put in a base api for anyone to call. 188 // call. Child processes ipc their port, so return something if available, else
Mark Mentovai 2009/12/18 22:18:24 When speaking English, "otherwise" is friendlier t
Nico 2009/12/18 22:46:52 Done.
kexinli365 2016/05/08 01:09:31 Acknowledged.
189 // return 0.
189 // 190 //
190 bool ProcessMetrics::GetIOCounters(IoCounters* io_counters) const { 191 bool ProcessMetrics::GetIOCounters(IoCounters* io_counters) const {
191 return false; 192 return false;
192 } 193 }
194
193 size_t ProcessMetrics::GetPagefileUsage() const { 195 size_t ProcessMetrics::GetPagefileUsage() const {
194 return 0; 196 mach_port_t task = TaskForPid(process_);
Mark Mentovai 2009/12/18 22:18:24 D'ya need to check if task exists? You do that ch
Nico 2009/12/18 22:46:52 Done.
197 task_basic_info_64 task_info_data;
198 mach_msg_type_number_t count = TASK_BASIC_INFO_64_COUNT;
199 kern_return_t kr = task_info(task,
200 TASK_BASIC_INFO_64,
201 (task_info_t)&task_info_data,
Mark Mentovai 2009/12/18 22:18:24 Prefer C++<style>(casts) unless you need to chain
Nico 2009/12/18 22:46:52 Done.
202 &count);
203 if (kr != KERN_SUCCESS) {
204 // Most likely cause: |task| is a zombie.
205 return 0;
206 }
207 return task_info_data.virtual_size;
195 } 208 }
209
196 size_t ProcessMetrics::GetPeakPagefileUsage() const { 210 size_t ProcessMetrics::GetPeakPagefileUsage() const {
197 return 0; 211 return 0;
198 } 212 }
213
199 size_t ProcessMetrics::GetWorkingSetSize() const { 214 size_t ProcessMetrics::GetWorkingSetSize() const {
200 return 0; 215 mach_port_t task = TaskForPid(process_);
216 task_basic_info_64 task_info_data;
217 mach_msg_type_number_t count = TASK_BASIC_INFO_64_COUNT;
218 kern_return_t kr = task_info(task,
Mark Mentovai 2009/12/18 22:18:24 Refactor into a common function to populate a task
Nico 2009/12/18 22:46:52 Done.
kexinli365 2016/05/08 01:09:31 Done.
219 TASK_BASIC_INFO_64,
220 (task_info_t)&task_info_data,
221 &count);
222 if (kr != KERN_SUCCESS) {
223 // Most likely cause: |task| is a zombie.
224 return 0;
225 }
226 return task_info_data.resident_size;
201 } 227 }
228
202 size_t ProcessMetrics::GetPeakWorkingSetSize() const { 229 size_t ProcessMetrics::GetPeakWorkingSetSize() const {
203 return 0; 230 return 0;
204 } 231 }
205 232
206 size_t ProcessMetrics::GetPrivateBytes() const { 233 size_t ProcessMetrics::GetPrivateBytes() const {
207 return 0; 234 return 0;
208 } 235 }
209 236
210 void ProcessMetrics::GetCommittedKBytes(CommittedKBytes* usage) const { 237 void ProcessMetrics::GetCommittedKBytes(CommittedKBytes* usage) const {
211 } 238 }
212 239
213 bool ProcessMetrics::GetWorkingSetKBytes(WorkingSetKBytes* ws_usage) const { 240 bool ProcessMetrics::GetWorkingSetKBytes(WorkingSetKBytes* ws_usage) const {
214 return false; 241 size_t priv = GetWorkingSetSize();
242 if (!priv)
243 return false;
244 ws_usage->priv = priv / 1024;
245 ws_usage->shareable = 0;
246 ws_usage->shared = 0;
247 return true;
248 }
249
250 #define TIME_VALUE_TO_TIMEVAL(a, r) do { \
251 (r)->tv_sec = (a)->seconds; \
252 (r)->tv_usec = (a)->microseconds; \
253 } while (0)
254
255 int ProcessMetrics::GetCPUUsage() {
256 mach_port_t task = TaskForPid(process_);
257 if (!task) {
258 // Most likely cause: |task| is a zombie.
259 return 0;
260 }
261
262 kern_return_t kr;
263
264 // TODO(thakis): Libtop doesn't use thread info. How can they get away
265 // without it?
266 task_thread_times_info thread_info_data;
267 mach_msg_type_number_t thread_info_count = TASK_THREAD_TIMES_INFO_COUNT;
268 kr = task_info(task,
269 TASK_THREAD_TIMES_INFO,
270 (task_info_t)&thread_info_data,
Mark Mentovai 2009/12/18 22:18:24 C++-style cast again.
Nico 2009/12/18 22:46:52 Done.
271 &thread_info_count);
272 if (kr != KERN_SUCCESS) {
273 LOG(ERROR) << "Failed to get thread info for task" << task;
Mark Mentovai 2009/12/18 22:18:24 You need a space at the end of your string literal
Nico 2009/12/18 22:46:52 Done.
274 return 0;
275 }
276
277 task_basic_info_64 task_info_data;
278 mach_msg_type_number_t task_basic_info_count = TASK_BASIC_INFO_64_COUNT;
279 kr = task_info(task,
280 TASK_BASIC_INFO_64,
281 (task_info_t)&task_info_data,
282 &task_basic_info_count);
283 if (kr != KERN_SUCCESS) {
284 LOG(ERROR) << "Failed to get task info for task" << task;
285 return 0;
286 }
287
288 /* Set total_time. */
289 // thread info contains live time...
290 struct timeval user_timeval, system_timeval, task_timeval;
291 TIME_VALUE_TO_TIMEVAL(&thread_info_data.user_time, &user_timeval);
292 TIME_VALUE_TO_TIMEVAL(&thread_info_data.system_time, &system_timeval);
293 timeradd(&user_timeval, &system_timeval, &task_timeval);
294
295 // ... task info contains terminated time.
296 TIME_VALUE_TO_TIMEVAL(&task_info_data.user_time, &user_timeval);
297 TIME_VALUE_TO_TIMEVAL(&task_info_data.system_time, &system_timeval);
298 timeradd(&user_timeval, &task_timeval, &task_timeval);
299 timeradd(&system_timeval, &task_timeval, &task_timeval);
300
301 struct timeval now;
302 int retval = gettimeofday(&now, NULL);
303 if (retval)
304 return 0;
305
306 int64 time = TimeValToMicroseconds(now);
307 int64 task_time = TimeValToMicroseconds(task_timeval);
308
309 if ((last_system_time_ == 0) || (last_time_ == 0)) {
310 // First call, just set the last values.
311 last_system_time_ = task_time;
312 last_time_ = time;
313 return 0;
314 }
315
316 int64 system_time_delta = task_time - last_system_time_;
317 int64 time_delta = time - last_time_;
318 DCHECK(time_delta != 0);
319 if (time_delta == 0)
320 return 0;
321
322 // We add time_delta / 2 so the result is rounded.
323 int cpu = static_cast<int>((system_time_delta * 100 + time_delta / 2) /
324 (time_delta));
325
326 last_system_time_ = task_time;
327 last_time_ = time;
328
329 return cpu;
330 }
331
332 mach_port_t ProcessMetrics::TaskForPid(ProcessHandle process) const {
333 mach_port_t task = 0;
334 if (port_provider_)
335 task = port_provider_->TaskForPid(process_);
336 if (!task && process_ == getpid())
337 task = mach_task_self();
338 return task;
215 } 339 }
216 340
217 // ------------------------------------------------------------------------ 341 // ------------------------------------------------------------------------
218 342
219 // Bytes committed by the system. 343 // Bytes committed by the system.
220 size_t GetSystemCommitCharge() { 344 size_t GetSystemCommitCharge() {
221 host_name_port_t host = mach_host_self(); 345 host_name_port_t host = mach_host_self();
222 mach_msg_type_number_t count = HOST_VM_INFO_COUNT; 346 mach_msg_type_number_t count = HOST_VM_INFO_COUNT;
223 vm_statistics_data_t data; 347 vm_statistics_data_t data;
224 kern_return_t kr = host_statistics(host, HOST_VM_INFO, 348 kern_return_t kr = host_statistics(host, HOST_VM_INFO,
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
321 CHECK(g_old_malloc && g_old_calloc && g_old_valloc && g_old_realloc) 445 CHECK(g_old_malloc && g_old_calloc && g_old_valloc && g_old_realloc)
322 << "Failed to get system allocation functions."; 446 << "Failed to get system allocation functions.";
323 447
324 default_zone->malloc = oom_killer_malloc; 448 default_zone->malloc = oom_killer_malloc;
325 default_zone->calloc = oom_killer_calloc; 449 default_zone->calloc = oom_killer_calloc;
326 default_zone->valloc = oom_killer_valloc; 450 default_zone->valloc = oom_killer_valloc;
327 default_zone->realloc = oom_killer_realloc; 451 default_zone->realloc = oom_killer_realloc;
328 } 452 }
329 453
330 } // namespace base 454 } // namespace base
OLDNEW
« base/process_util.h ('K') | « base/process_util.h ('k') | base/process_util_posix.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698