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 58 static void WriteLine(std::ostream& os, const char* name, 59 const CompilationStatistics::BasicStats& stats, 60 const CompilationStatistics::BasicStats& total_stats) { 61 const size_t kBufferSize = 128; 62 char buffer[kBufferSize]; 63 64 double ms = stats.delta_.InMillisecondsF(); 65 double percent = stats.delta_.PercentOf(total_stats.delta_); 66 double size_percent = 67 static_cast<double>(stats.total_allocated_bytes_ * 100) / 68 static_cast<double>(total_stats.total_allocated_bytes_); 69 base::OS::SNPrintF(buffer, kBufferSize, 70 "%28s %10.3f (%5.1f%%) " 71 "%10u (%5.1f%%) %10u %10u", 72 name, ms, percent, stats.total_allocated_bytes_, 73 size_percent, stats.max_allocated_bytes_, 74 stats.absolute_max_allocated_bytes_); 75 76 os << buffer; 77 if (stats.function_name_.size() > 0) { 78 os << " " << stats.function_name_.c_str(); 79 } 80 os << std::endl; 81 } 82 83 84 static void WriteFullLine(std::ostream& os) { 85 os << "--------------------------------------------------------" 86 "--------------------------------------------------------\n"; 87 } 88 89 90 static void WriteHeader(std::ostream& os) { 91 WriteFullLine(os); 92 os << " Turbonfan phase Time (ms) " 93 << " Space (bytes) Function\n" 94 << " " 95 << " Total Max. Abs. max.\n"; 96 WriteFullLine(os); 97 } 98 99 100 static void WritePhaseKindBreak(std::ostream& os) { 101 os << " ---------------------------" 102 "--------------------------------------------------------\n"; 103 } 104 105 106 std::ostream& operator<<(std::ostream& os, const CompilationStatistics& s) { 107 // phase_kind_map_ and phase_map_ don't get mutated, so store a bunch of 108 // pointers into them. 109 110 typedef std::vector<CompilationStatistics::PhaseKindMap::const_iterator> 111 SortedPhaseKinds; 112 SortedPhaseKinds sorted_phase_kinds(s.phase_kind_map_.size()); 113 for (auto it = s.phase_kind_map_.begin(); it != s.phase_kind_map_.end(); 114 ++it) { 115 sorted_phase_kinds[it->second.insert_order_] = it; 116 } 117 118 typedef std::vector<CompilationStatistics::PhaseMap::const_iterator> 119 SortedPhases; 120 SortedPhases sorted_phases(s.phase_map_.size()); 121 for (auto it = s.phase_map_.begin(); it != s.phase_map_.end(); ++it) { 122 sorted_phases[it->second.insert_order_] = it; 123 } 124 125 WriteHeader(os); 126 for (auto phase_kind_it : sorted_phase_kinds) { 127 const auto& phase_kind_name = phase_kind_it->first; 128 for (auto phase_it : sorted_phases) { 129 const auto& phase_stats = phase_it->second; 130 if (phase_stats.phase_kind_name_ != phase_kind_name) continue; 131 const auto& phase_name = phase_it->first; 132 WriteLine(os, phase_name.c_str(), phase_stats, s.total_stats_); 133 } 134 WritePhaseKindBreak(os); 135 const auto& phase_kind_stats = phase_kind_it->second; 136 WriteLine(os, phase_kind_name.c_str(), phase_kind_stats, s.total_stats_); 137 os << std::endl; 138 } 139 WriteFullLine(os); 140 WriteLine(os, "totals", s.total_stats_, s.total_stats_); 141 142 return os; 143 } 144 145 } // namespace internal 146 } // namespace v8 147