Home | History | Annotate | Download | only in src
      1 // Copyright 2014 the V8 project 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 <ostream>  // NOLINT(readability/streams)
      6 #include <vector>
      7 
      8 #include "src/base/platform/platform.h"
      9 #include "src/compilation-statistics.h"
     10 
     11 namespace v8 {
     12 namespace internal {
     13 
     14 void CompilationStatistics::RecordPhaseStats(const char* phase_kind_name,
     15                                              const char* phase_name,
     16                                              const BasicStats& stats) {
     17   base::LockGuard<base::Mutex> guard(&record_mutex_);
     18 
     19   std::string phase_name_str(phase_name);
     20   auto it = phase_map_.find(phase_name_str);
     21   if (it == phase_map_.end()) {
     22     PhaseStats phase_stats(phase_map_.size(), phase_kind_name);
     23     it = phase_map_.insert(std::make_pair(phase_name_str, phase_stats)).first;
     24   }
     25   it->second.Accumulate(stats);
     26 }
     27 
     28 
     29 void CompilationStatistics::RecordPhaseKindStats(const char* phase_kind_name,
     30                                                  const BasicStats& stats) {
     31   base::LockGuard<base::Mutex> guard(&record_mutex_);
     32 
     33   std::string phase_kind_name_str(phase_kind_name);
     34   auto it = phase_kind_map_.find(phase_kind_name_str);
     35   if (it == phase_kind_map_.end()) {
     36     PhaseKindStats phase_kind_stats(phase_kind_map_.size());
     37     it = phase_kind_map_.insert(std::make_pair(phase_kind_name_str,
     38                                                phase_kind_stats)).first;
     39   }
     40   it->second.Accumulate(stats);
     41 }
     42 
     43 
     44 void CompilationStatistics::RecordTotalStats(size_t source_size,
     45                                              const BasicStats& stats) {
     46   base::LockGuard<base::Mutex> guard(&record_mutex_);
     47 
     48   source_size += source_size;
     49   total_stats_.Accumulate(stats);
     50 }
     51 
     52 
     53 void CompilationStatistics::BasicStats::Accumulate(const BasicStats& stats) {
     54   delta_ += stats.delta_;
     55   total_allocated_bytes_ += stats.total_allocated_bytes_;
     56   if (stats.absolute_max_allocated_bytes_ > absolute_max_allocated_bytes_) {
     57     absolute_max_allocated_bytes_ = stats.absolute_max_allocated_bytes_;
     58     max_allocated_bytes_ = stats.max_allocated_bytes_;
     59     function_name_ = stats.function_name_;
     60   }
     61 }
     62 
     63 static void WriteLine(std::ostream& os, bool machine_format, const char* name,
     64                       const CompilationStatistics::BasicStats& stats,
     65                       const CompilationStatistics::BasicStats& total_stats) {
     66   const size_t kBufferSize = 128;
     67   char buffer[kBufferSize];
     68 
     69   double ms = stats.delta_.InMillisecondsF();
     70   double percent = stats.delta_.PercentOf(total_stats.delta_);
     71   double size_percent =
     72       static_cast<double>(stats.total_allocated_bytes_ * 100) /
     73       static_cast<double>(total_stats.total_allocated_bytes_);
     74   if (machine_format) {
     75     base::OS::SNPrintF(buffer, kBufferSize,
     76                        "\"%s_time\"=%.3f\n\"%s_space\"=%" PRIuS, name, ms, name,
     77                        stats.total_allocated_bytes_);
     78     os << buffer;
     79   } else {
     80     base::OS::SNPrintF(buffer, kBufferSize, "%28s %10.3f (%5.1f%%)  %10" PRIuS
     81                                             " (%5.1f%%) %10" PRIuS " %10" PRIuS,
     82                        name, ms, percent, stats.total_allocated_bytes_,
     83                        size_percent, stats.max_allocated_bytes_,
     84                        stats.absolute_max_allocated_bytes_);
     85 
     86     os << buffer;
     87     if (stats.function_name_.size() > 0) {
     88       os << "   " << stats.function_name_.c_str();
     89     }
     90     os << std::endl;
     91   }
     92 }
     93 
     94 
     95 static void WriteFullLine(std::ostream& os) {
     96   os << "--------------------------------------------------------"
     97         "--------------------------------------------------------\n";
     98 }
     99 
    100 
    101 static void WriteHeader(std::ostream& os) {
    102   WriteFullLine(os);
    103   os << "             Turbonfan phase        Time (ms)             "
    104      << "          Space (bytes)             Function\n"
    105      << "                                                         "
    106      << "  Total          Max.     Abs. max.\n";
    107   WriteFullLine(os);
    108 }
    109 
    110 
    111 static void WritePhaseKindBreak(std::ostream& os) {
    112   os << "                             ---------------------------"
    113         "--------------------------------------------------------\n";
    114 }
    115 
    116 std::ostream& operator<<(std::ostream& os, const AsPrintableStatistics& ps) {
    117   // phase_kind_map_ and phase_map_ don't get mutated, so store a bunch of
    118   // pointers into them.
    119   const CompilationStatistics& s = ps.s;
    120 
    121   typedef std::vector<CompilationStatistics::PhaseKindMap::const_iterator>
    122       SortedPhaseKinds;
    123   SortedPhaseKinds sorted_phase_kinds(s.phase_kind_map_.size());
    124   for (auto it = s.phase_kind_map_.begin(); it != s.phase_kind_map_.end();
    125        ++it) {
    126     sorted_phase_kinds[it->second.insert_order_] = it;
    127   }
    128 
    129   typedef std::vector<CompilationStatistics::PhaseMap::const_iterator>
    130       SortedPhases;
    131   SortedPhases sorted_phases(s.phase_map_.size());
    132   for (auto it = s.phase_map_.begin(); it != s.phase_map_.end(); ++it) {
    133     sorted_phases[it->second.insert_order_] = it;
    134   }
    135 
    136   if (!ps.machine_output) WriteHeader(os);
    137   for (const auto& phase_kind_it : sorted_phase_kinds) {
    138     const auto& phase_kind_name = phase_kind_it->first;
    139     if (!ps.machine_output) {
    140       for (const auto& phase_it : sorted_phases) {
    141         const auto& phase_stats = phase_it->second;
    142         if (phase_stats.phase_kind_name_ != phase_kind_name) continue;
    143         const auto& phase_name = phase_it->first;
    144         WriteLine(os, ps.machine_output, phase_name.c_str(), phase_stats,
    145                   s.total_stats_);
    146       }
    147       WritePhaseKindBreak(os);
    148     }
    149     const auto& phase_kind_stats = phase_kind_it->second;
    150     WriteLine(os, ps.machine_output, phase_kind_name.c_str(), phase_kind_stats,
    151               s.total_stats_);
    152     os << std::endl;
    153   }
    154 
    155   if (!ps.machine_output) WriteFullLine(os);
    156   WriteLine(os, ps.machine_output, "totals", s.total_stats_, s.total_stats_);
    157 
    158   return os;
    159 }
    160 
    161 }  // namespace internal
    162 }  // namespace v8
    163