Home | History | Annotate | Download | only in perf
      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