1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "chrome/test/perf/perf_test.h" 6 7 #include <stdio.h> 8 9 #include "base/logging.h" 10 #include "base/strings/string_number_conversions.h" 11 #include "base/strings/stringprintf.h" 12 #include "chrome/test/base/chrome_process_util.h" 13 #include "testing/perf/perf_test.h" 14 15 namespace perf_test { 16 17 void PrintIOPerfInfo(const std::string& test_name, 18 const ChromeProcessList& chrome_processes, 19 base::ProcessId browser_pid) { 20 PrintIOPerfInfo(stdout, test_name, chrome_processes, browser_pid); 21 } 22 23 void PrintIOPerfInfo(FILE* target, 24 const std::string& test_name, 25 const ChromeProcessList& chrome_processes, 26 base::ProcessId browser_pid) { 27 fprintf(target, "%s", IOPerfInfoToString(test_name, chrome_processes, 28 browser_pid).c_str()); 29 } 30 31 std::string IOPerfInfoToString(const std::string& test_name, 32 const ChromeProcessList& chrome_processes, 33 base::ProcessId browser_pid) { 34 size_t read_op_b = 0; 35 size_t read_op_r = 0; 36 size_t write_op_b = 0; 37 size_t write_op_r = 0; 38 size_t other_op_b = 0; 39 size_t other_op_r = 0; 40 size_t total_op_b = 0; 41 size_t total_op_r = 0; 42 43 size_t read_byte_b = 0; 44 size_t read_byte_r = 0; 45 size_t write_byte_b = 0; 46 size_t write_byte_r = 0; 47 size_t other_byte_b = 0; 48 size_t other_byte_r = 0; 49 size_t total_byte_b = 0; 50 size_t total_byte_r = 0; 51 52 std::string output; 53 ChromeProcessList::const_iterator it; 54 for (it = chrome_processes.begin(); it != chrome_processes.end(); ++it) { 55 base::ProcessHandle process_handle; 56 if (!base::OpenProcessHandle(*it, &process_handle)) { 57 NOTREACHED(); 58 return output; 59 } 60 61 // TODO(sgk): if/when base::ProcessMetrics returns real stats on mac: 62 // scoped_ptr<base::ProcessMetrics> process_metrics( 63 // base::ProcessMetrics::CreateProcessMetrics(process_handle)); 64 scoped_ptr<ChromeTestProcessMetrics> process_metrics( 65 ChromeTestProcessMetrics::CreateProcessMetrics(process_handle)); 66 base::IoCounters io_counters; 67 memset(&io_counters, 0, sizeof(io_counters)); 68 69 if (process_metrics.get()->GetIOCounters(&io_counters)) { 70 // Print out IO performance. We assume that the values can be 71 // converted to size_t (they're reported as ULONGLONG, 64-bit numbers). 72 std::string chrome_name = (*it == browser_pid) ? "_b" : "_r"; 73 74 size_t read_op = static_cast<size_t>(io_counters.ReadOperationCount); 75 size_t write_op = static_cast<size_t>(io_counters.WriteOperationCount); 76 size_t other_op = static_cast<size_t>(io_counters.OtherOperationCount); 77 size_t total_op = static_cast<size_t>(io_counters.ReadOperationCount + 78 io_counters.WriteOperationCount + 79 io_counters.OtherOperationCount); 80 81 size_t read_byte = static_cast<size_t>(io_counters.ReadTransferCount 82 / 1024); 83 size_t write_byte = static_cast<size_t>(io_counters.WriteTransferCount 84 / 1024); 85 size_t other_byte = static_cast<size_t>(io_counters.OtherTransferCount 86 / 1024); 87 size_t total_byte = static_cast<size_t>((io_counters.ReadTransferCount + 88 io_counters.WriteTransferCount + 89 io_counters.OtherTransferCount) 90 / 1024); 91 92 if (*it == browser_pid) { 93 read_op_b = read_op; 94 write_op_b = write_op; 95 other_op_b = other_op; 96 total_op_b = total_op; 97 read_byte_b = read_byte; 98 write_byte_b = write_byte; 99 other_byte_b = other_byte; 100 total_byte_b = total_byte; 101 } else { 102 read_op_r += read_op; 103 write_op_r += write_op; 104 other_op_r += other_op; 105 total_op_r += total_op; 106 read_byte_r += read_byte; 107 write_byte_r += write_byte; 108 other_byte_r += other_byte; 109 total_byte_r += total_byte; 110 } 111 } 112 113 base::CloseProcessHandle(process_handle); 114 } 115 116 std::string t_name(test_name); 117 AppendResult(output, 118 "read_op_b", 119 std::string(), 120 "r_op_b" + t_name, 121 read_op_b, 122 "ops", 123 false); 124 AppendResult(output, 125 "write_op_b", 126 std::string(), 127 "w_op_b" + t_name, 128 write_op_b, 129 "ops", 130 false); 131 AppendResult(output, 132 "other_op_b", 133 std::string(), 134 "o_op_b" + t_name, 135 other_op_b, 136 "ops", 137 false); 138 AppendResult(output, 139 "total_op_b", 140 std::string(), 141 "IO_op_b" + t_name, 142 total_op_b, 143 "ops", 144 false); 145 146 AppendResult(output, 147 "read_byte_b", 148 std::string(), 149 "r_b" + t_name, 150 read_byte_b, 151 "kb", 152 false); 153 AppendResult(output, 154 "write_byte_b", 155 std::string(), 156 "w_b" + t_name, 157 write_byte_b, 158 "kb", 159 false); 160 AppendResult(output, 161 "other_byte_b", 162 std::string(), 163 "o_b" + t_name, 164 other_byte_b, 165 "kb", 166 false); 167 AppendResult(output, 168 "total_byte_b", 169 std::string(), 170 "IO_b" + t_name, 171 total_byte_b, 172 "kb", 173 false); 174 175 AppendResult(output, 176 "read_op_r", 177 std::string(), 178 "r_op_r" + t_name, 179 read_op_r, 180 "ops", 181 false); 182 AppendResult(output, 183 "write_op_r", 184 std::string(), 185 "w_op_r" + t_name, 186 write_op_r, 187 "ops", 188 false); 189 AppendResult(output, 190 "other_op_r", 191 std::string(), 192 "o_op_r" + t_name, 193 other_op_r, 194 "ops", 195 false); 196 AppendResult(output, 197 "total_op_r", 198 std::string(), 199 "IO_op_r" + t_name, 200 total_op_r, 201 "ops", 202 false); 203 204 AppendResult(output, 205 "read_byte_r", 206 std::string(), 207 "r_r" + t_name, 208 read_byte_r, 209 "kb", 210 false); 211 AppendResult(output, 212 "write_byte_r", 213 std::string(), 214 "w_r" + t_name, 215 write_byte_r, 216 "kb", 217 false); 218 AppendResult(output, 219 "other_byte_r", 220 std::string(), 221 "o_r" + t_name, 222 other_byte_r, 223 "kb", 224 false); 225 AppendResult(output, 226 "total_byte_r", 227 std::string(), 228 "IO_r" + t_name, 229 total_byte_r, 230 "kb", 231 false); 232 233 return output; 234 } 235 236 void PrintMemoryUsageInfo(const std::string& test_name, 237 const ChromeProcessList& chrome_processes, 238 base::ProcessId browser_pid) { 239 PrintMemoryUsageInfo(stdout, test_name, chrome_processes, browser_pid); 240 } 241 242 void PrintMemoryUsageInfo(FILE* target, 243 const std::string& test_name, 244 const ChromeProcessList& chrome_processes, 245 base::ProcessId browser_pid) { 246 fprintf(target, "%s", MemoryUsageInfoToString(test_name, chrome_processes, 247 browser_pid).c_str()); 248 } 249 250 std::string MemoryUsageInfoToString(const std::string& test_name, 251 const ChromeProcessList& chrome_processes, 252 base::ProcessId browser_pid) { 253 size_t browser_virtual_size = 0; 254 size_t browser_working_set_size = 0; 255 size_t renderer_virtual_size = 0; 256 size_t renderer_working_set_size = 0; 257 size_t total_virtual_size = 0; 258 size_t total_working_set_size = 0; 259 #if defined(OS_WIN) 260 size_t browser_peak_virtual_size = 0; 261 size_t browser_peak_working_set_size = 0; 262 size_t renderer_total_peak_virtual_size = 0; 263 size_t renderer_total_peak_working_set_size = 0; 264 size_t renderer_single_peak_virtual_size = 0; 265 size_t renderer_single_peak_working_set_size = 0; 266 #endif 267 268 std::string output; 269 ChromeProcessList::const_iterator it; 270 for (it = chrome_processes.begin(); it != chrome_processes.end(); ++it) { 271 base::ProcessHandle process_handle; 272 if (!base::OpenProcessHandle(*it, &process_handle)) { 273 NOTREACHED(); 274 return output; 275 } 276 277 // TODO(sgk): if/when base::ProcessMetrics returns real stats on mac: 278 // scoped_ptr<base::ProcessMetrics> process_metrics( 279 // base::ProcessMetrics::CreateProcessMetrics(process_handle)); 280 scoped_ptr<ChromeTestProcessMetrics> process_metrics( 281 ChromeTestProcessMetrics::CreateProcessMetrics(process_handle)); 282 283 size_t current_virtual_size = process_metrics->GetPagefileUsage(); 284 size_t current_working_set_size = process_metrics->GetWorkingSetSize(); 285 286 if (*it == browser_pid) { 287 browser_virtual_size = current_virtual_size; 288 browser_working_set_size = current_working_set_size; 289 } else { 290 renderer_virtual_size += current_virtual_size; 291 renderer_working_set_size += current_working_set_size; 292 } 293 total_virtual_size += current_virtual_size; 294 total_working_set_size += current_working_set_size; 295 296 #if defined(OS_WIN) 297 size_t peak_virtual_size = process_metrics->GetPeakPagefileUsage(); 298 size_t peak_working_set_size = process_metrics->GetPeakWorkingSetSize(); 299 if (*it == browser_pid) { 300 browser_peak_virtual_size = peak_virtual_size; 301 browser_peak_working_set_size = peak_working_set_size; 302 } else { 303 if (peak_virtual_size > renderer_single_peak_virtual_size) { 304 renderer_single_peak_virtual_size = peak_virtual_size; 305 } 306 if (peak_working_set_size > renderer_single_peak_working_set_size) { 307 renderer_single_peak_working_set_size = peak_working_set_size; 308 } 309 renderer_total_peak_virtual_size += peak_virtual_size; 310 renderer_total_peak_working_set_size += peak_working_set_size; 311 } 312 #endif 313 314 base::CloseProcessHandle(process_handle); 315 } 316 317 std::string trace_name(test_name); 318 #if defined(OS_WIN) 319 AppendResult(output, "vm_peak_b", "", "vm_pk_b" + trace_name, 320 browser_peak_virtual_size, "bytes", 321 false /* not important */); 322 AppendResult(output, "ws_peak_b", "", "ws_pk_b" + trace_name, 323 browser_peak_working_set_size, "bytes", 324 false /* not important */); 325 AppendResult(output, "vm_peak_r", "", "vm_pk_r" + trace_name, 326 renderer_total_peak_virtual_size, "bytes", 327 false /* not important */); 328 AppendResult(output, "ws_peak_r", "", "ws_pk_r" + trace_name, 329 renderer_total_peak_working_set_size, "bytes", 330 false /* not important */); 331 AppendResult(output, "vm_single_peak_r", "", "vm_spk_r" + trace_name, 332 renderer_single_peak_virtual_size, "bytes", 333 false /* not important */); 334 AppendResult(output, "ws_single_peak_r", "", "ws_spk_r" + trace_name, 335 renderer_single_peak_working_set_size, "bytes", 336 false /* important */); 337 AppendResult(output, "vm_final_b", "", "vm_f_b" + trace_name, 338 browser_virtual_size, "bytes", 339 false /* not important */); 340 AppendResult(output, "ws_final_b", "", "ws_f_b" + trace_name, 341 browser_working_set_size, "bytes", 342 false /* not important */); 343 AppendResult(output, "vm_final_r", "", "vm_f_r" + trace_name, 344 renderer_virtual_size, "bytes", 345 false /* not important */); 346 AppendResult(output, "ws_final_r", "", "ws_f_r" + trace_name, 347 renderer_working_set_size, "bytes", 348 false /* not important */); 349 AppendResult(output, "vm_final_t", "", "vm_f_t" + trace_name, 350 total_virtual_size, "bytes", 351 false /* not important */); 352 AppendResult(output, "ws_final_t", "", "ws_f_t" + trace_name, 353 total_working_set_size, "bytes", 354 false /* not important */); 355 #elif defined(OS_LINUX) || defined(OS_MACOSX) || defined(OS_ANDROID) 356 AppendResult(output, 357 "vm_size_final_b", 358 std::string(), 359 "vm_size_f_b" + trace_name, 360 browser_virtual_size, 361 "bytes", 362 false /* not important */); 363 AppendResult(output, 364 "vm_rss_final_b", 365 std::string(), 366 "vm_rss_f_b" + trace_name, 367 browser_working_set_size, 368 "bytes", 369 false /* not important */); 370 AppendResult(output, 371 "vm_size_final_r", 372 std::string(), 373 "vm_size_f_r" + trace_name, 374 renderer_virtual_size, 375 "bytes", 376 false /* not important */); 377 AppendResult(output, 378 "vm_rss_final_r", 379 std::string(), 380 "vm_rss_f_r" + trace_name, 381 renderer_working_set_size, 382 "bytes", 383 false /* not important */); 384 AppendResult(output, 385 "vm_size_final_t", 386 std::string(), 387 "vm_size_f_t" + trace_name, 388 total_virtual_size, 389 "bytes", 390 false /* not important */); 391 AppendResult(output, 392 "vm_rss_final_t", 393 std::string(), 394 "vm_rss_f_t" + trace_name, 395 total_working_set_size, 396 "bytes", 397 false /* not important */); 398 #else 399 NOTIMPLEMENTED(); 400 #endif 401 AppendResult(output, 402 "processes", 403 std::string(), 404 "proc_" + trace_name, 405 chrome_processes.size(), 406 "count", 407 false /* not important */); 408 409 return output; 410 } 411 412 } // namespace perf_test 413