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