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 14 namespace { 15 16 std::string ResultsToString(const std::string& measurement, 17 const std::string& modifier, 18 const std::string& trace, 19 const std::string& values, 20 const std::string& prefix, 21 const std::string& suffix, 22 const std::string& units, 23 bool important) { 24 // <*>RESULT <graph_name>: <trace_name>= <value> <units> 25 // <*>RESULT <graph_name>: <trace_name>= {<mean>, <std deviation>} <units> 26 // <*>RESULT <graph_name>: <trace_name>= [<value>,value,value,...,] <units> 27 return base::StringPrintf("%sRESULT %s%s: %s= %s%s%s %s\n", 28 important ? "*" : "", measurement.c_str(), modifier.c_str(), 29 trace.c_str(), prefix.c_str(), values.c_str(), suffix.c_str(), 30 units.c_str()); 31 } 32 33 void PrintResultsImpl(const std::string& measurement, 34 const std::string& modifier, 35 const std::string& trace, 36 const std::string& values, 37 const std::string& prefix, 38 const std::string& suffix, 39 const std::string& units, 40 bool important) { 41 fflush(stdout); 42 printf("%s", ResultsToString(measurement, modifier, trace, values, 43 prefix, suffix, units, important).c_str()); 44 fflush(stdout); 45 } 46 47 } // namespace 48 49 namespace perf_test { 50 51 void PrintResult(const std::string& measurement, 52 const std::string& modifier, 53 const std::string& trace, 54 size_t value, 55 const std::string& units, 56 bool important) { 57 PrintResultsImpl(measurement, 58 modifier, 59 trace, 60 base::UintToString(value), 61 std::string(), 62 std::string(), 63 units, 64 important); 65 } 66 67 void AppendResult(std::string& output, 68 const std::string& measurement, 69 const std::string& modifier, 70 const std::string& trace, 71 size_t value, 72 const std::string& units, 73 bool important) { 74 output += ResultsToString(measurement, 75 modifier, 76 trace, 77 base::UintToString(value), 78 std::string(), 79 std::string(), 80 units, 81 important); 82 } 83 84 void PrintResult(const std::string& measurement, 85 const std::string& modifier, 86 const std::string& trace, 87 const std::string& value, 88 const std::string& units, 89 bool important) { 90 PrintResultsImpl(measurement, 91 modifier, 92 trace, 93 value, 94 std::string(), 95 std::string(), 96 units, 97 important); 98 } 99 100 void AppendResult(std::string& output, 101 const std::string& measurement, 102 const std::string& modifier, 103 const std::string& trace, 104 const std::string& value, 105 const std::string& units, 106 bool important) { 107 output += ResultsToString(measurement, 108 modifier, 109 trace, 110 value, 111 std::string(), 112 std::string(), 113 units, 114 important); 115 } 116 117 void PrintResultMeanAndError(const std::string& measurement, 118 const std::string& modifier, 119 const std::string& trace, 120 const std::string& mean_and_error, 121 const std::string& units, 122 bool important) { 123 PrintResultsImpl(measurement, modifier, trace, mean_and_error, 124 "{", "}", units, important); 125 } 126 127 void AppendResultMeanAndError(std::string& output, 128 const std::string& measurement, 129 const std::string& modifier, 130 const std::string& trace, 131 const std::string& mean_and_error, 132 const std::string& units, 133 bool important) { 134 output += ResultsToString(measurement, modifier, trace, mean_and_error, 135 "{", "}", units, important); 136 } 137 138 void PrintResultList(const std::string& measurement, 139 const std::string& modifier, 140 const std::string& trace, 141 const std::string& values, 142 const std::string& units, 143 bool important) { 144 PrintResultsImpl(measurement, modifier, trace, values, 145 "[", "]", units, important); 146 } 147 148 void AppendResultList(std::string& output, 149 const std::string& measurement, 150 const std::string& modifier, 151 const std::string& trace, 152 const std::string& values, 153 const std::string& units, 154 bool important) { 155 output += ResultsToString(measurement, modifier, trace, values, 156 "[", "]", units, important); 157 } 158 159 void PrintIOPerfInfo(const std::string& test_name, 160 const ChromeProcessList& chrome_processes, 161 base::ProcessId browser_pid) { 162 PrintIOPerfInfo(stdout, test_name, chrome_processes, browser_pid); 163 } 164 165 void PrintIOPerfInfo(FILE* target, 166 const std::string& test_name, 167 const ChromeProcessList& chrome_processes, 168 base::ProcessId browser_pid) { 169 fprintf(target, "%s", IOPerfInfoToString(test_name, chrome_processes, 170 browser_pid).c_str()); 171 } 172 173 std::string IOPerfInfoToString(const std::string& test_name, 174 const ChromeProcessList& chrome_processes, 175 base::ProcessId browser_pid) { 176 size_t read_op_b = 0; 177 size_t read_op_r = 0; 178 size_t write_op_b = 0; 179 size_t write_op_r = 0; 180 size_t other_op_b = 0; 181 size_t other_op_r = 0; 182 size_t total_op_b = 0; 183 size_t total_op_r = 0; 184 185 size_t read_byte_b = 0; 186 size_t read_byte_r = 0; 187 size_t write_byte_b = 0; 188 size_t write_byte_r = 0; 189 size_t other_byte_b = 0; 190 size_t other_byte_r = 0; 191 size_t total_byte_b = 0; 192 size_t total_byte_r = 0; 193 194 std::string output; 195 ChromeProcessList::const_iterator it; 196 for (it = chrome_processes.begin(); it != chrome_processes.end(); ++it) { 197 base::ProcessHandle process_handle; 198 if (!base::OpenProcessHandle(*it, &process_handle)) { 199 NOTREACHED(); 200 return output; 201 } 202 203 // TODO(sgk): if/when base::ProcessMetrics returns real stats on mac: 204 // scoped_ptr<base::ProcessMetrics> process_metrics( 205 // base::ProcessMetrics::CreateProcessMetrics(process_handle)); 206 scoped_ptr<ChromeTestProcessMetrics> process_metrics( 207 ChromeTestProcessMetrics::CreateProcessMetrics(process_handle)); 208 base::IoCounters io_counters; 209 memset(&io_counters, 0, sizeof(io_counters)); 210 211 if (process_metrics.get()->GetIOCounters(&io_counters)) { 212 // Print out IO performance. We assume that the values can be 213 // converted to size_t (they're reported as ULONGLONG, 64-bit numbers). 214 std::string chrome_name = (*it == browser_pid) ? "_b" : "_r"; 215 216 size_t read_op = static_cast<size_t>(io_counters.ReadOperationCount); 217 size_t write_op = static_cast<size_t>(io_counters.WriteOperationCount); 218 size_t other_op = static_cast<size_t>(io_counters.OtherOperationCount); 219 size_t total_op = static_cast<size_t>(io_counters.ReadOperationCount + 220 io_counters.WriteOperationCount + 221 io_counters.OtherOperationCount); 222 223 size_t read_byte = static_cast<size_t>(io_counters.ReadTransferCount 224 / 1024); 225 size_t write_byte = static_cast<size_t>(io_counters.WriteTransferCount 226 / 1024); 227 size_t other_byte = static_cast<size_t>(io_counters.OtherTransferCount 228 / 1024); 229 size_t total_byte = static_cast<size_t>((io_counters.ReadTransferCount + 230 io_counters.WriteTransferCount + 231 io_counters.OtherTransferCount) 232 / 1024); 233 234 if (*it == browser_pid) { 235 read_op_b = read_op; 236 write_op_b = write_op; 237 other_op_b = other_op; 238 total_op_b = total_op; 239 read_byte_b = read_byte; 240 write_byte_b = write_byte; 241 other_byte_b = other_byte; 242 total_byte_b = total_byte; 243 } else { 244 read_op_r += read_op; 245 write_op_r += write_op; 246 other_op_r += other_op; 247 total_op_r += total_op; 248 read_byte_r += read_byte; 249 write_byte_r += write_byte; 250 other_byte_r += other_byte; 251 total_byte_r += total_byte; 252 } 253 } 254 255 base::CloseProcessHandle(process_handle); 256 } 257 258 std::string t_name(test_name); 259 AppendResult(output, 260 "read_op_b", 261 std::string(), 262 "r_op_b" + t_name, 263 read_op_b, 264 "ops", 265 false); 266 AppendResult(output, 267 "write_op_b", 268 std::string(), 269 "w_op_b" + t_name, 270 write_op_b, 271 "ops", 272 false); 273 AppendResult(output, 274 "other_op_b", 275 std::string(), 276 "o_op_b" + t_name, 277 other_op_b, 278 "ops", 279 false); 280 AppendResult(output, 281 "total_op_b", 282 std::string(), 283 "IO_op_b" + t_name, 284 total_op_b, 285 "ops", 286 false); 287 288 AppendResult(output, 289 "read_byte_b", 290 std::string(), 291 "r_b" + t_name, 292 read_byte_b, 293 "kb", 294 false); 295 AppendResult(output, 296 "write_byte_b", 297 std::string(), 298 "w_b" + t_name, 299 write_byte_b, 300 "kb", 301 false); 302 AppendResult(output, 303 "other_byte_b", 304 std::string(), 305 "o_b" + t_name, 306 other_byte_b, 307 "kb", 308 false); 309 AppendResult(output, 310 "total_byte_b", 311 std::string(), 312 "IO_b" + t_name, 313 total_byte_b, 314 "kb", 315 false); 316 317 AppendResult(output, 318 "read_op_r", 319 std::string(), 320 "r_op_r" + t_name, 321 read_op_r, 322 "ops", 323 false); 324 AppendResult(output, 325 "write_op_r", 326 std::string(), 327 "w_op_r" + t_name, 328 write_op_r, 329 "ops", 330 false); 331 AppendResult(output, 332 "other_op_r", 333 std::string(), 334 "o_op_r" + t_name, 335 other_op_r, 336 "ops", 337 false); 338 AppendResult(output, 339 "total_op_r", 340 std::string(), 341 "IO_op_r" + t_name, 342 total_op_r, 343 "ops", 344 false); 345 346 AppendResult(output, 347 "read_byte_r", 348 std::string(), 349 "r_r" + t_name, 350 read_byte_r, 351 "kb", 352 false); 353 AppendResult(output, 354 "write_byte_r", 355 std::string(), 356 "w_r" + t_name, 357 write_byte_r, 358 "kb", 359 false); 360 AppendResult(output, 361 "other_byte_r", 362 std::string(), 363 "o_r" + t_name, 364 other_byte_r, 365 "kb", 366 false); 367 AppendResult(output, 368 "total_byte_r", 369 std::string(), 370 "IO_r" + t_name, 371 total_byte_r, 372 "kb", 373 false); 374 375 return output; 376 } 377 378 void PrintMemoryUsageInfo(const std::string& test_name, 379 const ChromeProcessList& chrome_processes, 380 base::ProcessId browser_pid) { 381 PrintMemoryUsageInfo(stdout, test_name, chrome_processes, browser_pid); 382 } 383 384 void PrintMemoryUsageInfo(FILE* target, 385 const std::string& test_name, 386 const ChromeProcessList& chrome_processes, 387 base::ProcessId browser_pid) { 388 fprintf(target, "%s", MemoryUsageInfoToString(test_name, chrome_processes, 389 browser_pid).c_str()); 390 } 391 392 std::string MemoryUsageInfoToString(const std::string& test_name, 393 const ChromeProcessList& chrome_processes, 394 base::ProcessId browser_pid) { 395 size_t browser_virtual_size = 0; 396 size_t browser_working_set_size = 0; 397 size_t renderer_virtual_size = 0; 398 size_t renderer_working_set_size = 0; 399 size_t total_virtual_size = 0; 400 size_t total_working_set_size = 0; 401 #if defined(OS_WIN) 402 size_t browser_peak_virtual_size = 0; 403 size_t browser_peak_working_set_size = 0; 404 size_t renderer_total_peak_virtual_size = 0; 405 size_t renderer_total_peak_working_set_size = 0; 406 size_t renderer_single_peak_virtual_size = 0; 407 size_t renderer_single_peak_working_set_size = 0; 408 #endif 409 410 std::string output; 411 ChromeProcessList::const_iterator it; 412 for (it = chrome_processes.begin(); it != chrome_processes.end(); ++it) { 413 base::ProcessHandle process_handle; 414 if (!base::OpenProcessHandle(*it, &process_handle)) { 415 NOTREACHED(); 416 return output; 417 } 418 419 // TODO(sgk): if/when base::ProcessMetrics returns real stats on mac: 420 // scoped_ptr<base::ProcessMetrics> process_metrics( 421 // base::ProcessMetrics::CreateProcessMetrics(process_handle)); 422 scoped_ptr<ChromeTestProcessMetrics> process_metrics( 423 ChromeTestProcessMetrics::CreateProcessMetrics(process_handle)); 424 425 size_t current_virtual_size = process_metrics->GetPagefileUsage(); 426 size_t current_working_set_size = process_metrics->GetWorkingSetSize(); 427 428 if (*it == browser_pid) { 429 browser_virtual_size = current_virtual_size; 430 browser_working_set_size = current_working_set_size; 431 } else { 432 renderer_virtual_size += current_virtual_size; 433 renderer_working_set_size += current_working_set_size; 434 } 435 total_virtual_size += current_virtual_size; 436 total_working_set_size += current_working_set_size; 437 438 #if defined(OS_WIN) 439 size_t peak_virtual_size = process_metrics->GetPeakPagefileUsage(); 440 size_t peak_working_set_size = process_metrics->GetPeakWorkingSetSize(); 441 if (*it == browser_pid) { 442 browser_peak_virtual_size = peak_virtual_size; 443 browser_peak_working_set_size = peak_working_set_size; 444 } else { 445 if (peak_virtual_size > renderer_single_peak_virtual_size) { 446 renderer_single_peak_virtual_size = peak_virtual_size; 447 } 448 if (peak_working_set_size > renderer_single_peak_working_set_size) { 449 renderer_single_peak_working_set_size = peak_working_set_size; 450 } 451 renderer_total_peak_virtual_size += peak_virtual_size; 452 renderer_total_peak_working_set_size += peak_working_set_size; 453 } 454 #endif 455 456 base::CloseProcessHandle(process_handle); 457 } 458 459 std::string trace_name(test_name); 460 #if defined(OS_WIN) 461 AppendResult(output, "vm_peak_b", "", "vm_pk_b" + trace_name, 462 browser_peak_virtual_size, "bytes", 463 false /* not important */); 464 AppendResult(output, "ws_peak_b", "", "ws_pk_b" + trace_name, 465 browser_peak_working_set_size, "bytes", 466 false /* not important */); 467 AppendResult(output, "vm_peak_r", "", "vm_pk_r" + trace_name, 468 renderer_total_peak_virtual_size, "bytes", 469 false /* not important */); 470 AppendResult(output, "ws_peak_r", "", "ws_pk_r" + trace_name, 471 renderer_total_peak_working_set_size, "bytes", 472 false /* not important */); 473 AppendResult(output, "vm_single_peak_r", "", "vm_spk_r" + trace_name, 474 renderer_single_peak_virtual_size, "bytes", 475 false /* not important */); 476 AppendResult(output, "ws_single_peak_r", "", "ws_spk_r" + trace_name, 477 renderer_single_peak_working_set_size, "bytes", 478 false /* important */); 479 AppendResult(output, "vm_final_b", "", "vm_f_b" + trace_name, 480 browser_virtual_size, "bytes", 481 false /* not important */); 482 AppendResult(output, "ws_final_b", "", "ws_f_b" + trace_name, 483 browser_working_set_size, "bytes", 484 false /* not important */); 485 AppendResult(output, "vm_final_r", "", "vm_f_r" + trace_name, 486 renderer_virtual_size, "bytes", 487 false /* not important */); 488 AppendResult(output, "ws_final_r", "", "ws_f_r" + trace_name, 489 renderer_working_set_size, "bytes", 490 false /* not important */); 491 AppendResult(output, "vm_final_t", "", "vm_f_t" + trace_name, 492 total_virtual_size, "bytes", 493 false /* not important */); 494 AppendResult(output, "ws_final_t", "", "ws_f_t" + trace_name, 495 total_working_set_size, "bytes", 496 false /* not important */); 497 #elif defined(OS_LINUX) || defined(OS_MACOSX) || defined(OS_ANDROID) 498 AppendResult(output, 499 "vm_size_final_b", 500 std::string(), 501 "vm_size_f_b" + trace_name, 502 browser_virtual_size, 503 "bytes", 504 false /* not important */); 505 AppendResult(output, 506 "vm_rss_final_b", 507 std::string(), 508 "vm_rss_f_b" + trace_name, 509 browser_working_set_size, 510 "bytes", 511 false /* not important */); 512 AppendResult(output, 513 "vm_size_final_r", 514 std::string(), 515 "vm_size_f_r" + trace_name, 516 renderer_virtual_size, 517 "bytes", 518 false /* not important */); 519 AppendResult(output, 520 "vm_rss_final_r", 521 std::string(), 522 "vm_rss_f_r" + trace_name, 523 renderer_working_set_size, 524 "bytes", 525 false /* not important */); 526 AppendResult(output, 527 "vm_size_final_t", 528 std::string(), 529 "vm_size_f_t" + trace_name, 530 total_virtual_size, 531 "bytes", 532 false /* not important */); 533 AppendResult(output, 534 "vm_rss_final_t", 535 std::string(), 536 "vm_rss_f_t" + trace_name, 537 total_working_set_size, 538 "bytes", 539 false /* not important */); 540 #else 541 NOTIMPLEMENTED(); 542 #endif 543 AppendResult(output, 544 "processes", 545 std::string(), 546 "proc_" + trace_name, 547 chrome_processes.size(), 548 "count", 549 false /* not important */); 550 551 return output; 552 } 553 554 void PrintSystemCommitCharge(const std::string& test_name, 555 size_t charge, 556 bool important) { 557 PrintSystemCommitCharge(stdout, test_name, charge, important); 558 } 559 560 void PrintSystemCommitCharge(FILE* target, 561 const std::string& test_name, 562 size_t charge, 563 bool important) { 564 fprintf(target, "%s", SystemCommitChargeToString(test_name, charge, 565 important).c_str()); 566 } 567 568 std::string SystemCommitChargeToString(const std::string& test_name, 569 size_t charge, 570 bool important) { 571 std::string trace_name(test_name); 572 std::string output; 573 AppendResult(output, 574 "commit_charge", 575 std::string(), 576 "cc" + trace_name, 577 charge, 578 "kb", 579 important); 580 return output; 581 } 582 583 } // namespace perf_test 584