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