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
RecordPhaseStats(const char * phase_kind_name,const char * phase_name,const BasicStats & stats)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
RecordPhaseKindStats(const char * phase_kind_name,const BasicStats & stats)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
RecordTotalStats(size_t source_size,const BasicStats & stats)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
Accumulate(const BasicStats & stats)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
WriteLine(std::ostream & os,bool machine_format,const char * name,const CompilationStatistics::BasicStats & stats,const CompilationStatistics::BasicStats & total_stats)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
WriteFullLine(std::ostream & os)95 static void WriteFullLine(std::ostream& os) {
96 os << "--------------------------------------------------------"
97 "--------------------------------------------------------\n";
98 }
99
100
WriteHeader(std::ostream & os)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
WritePhaseKindBreak(std::ostream & os)111 static void WritePhaseKindBreak(std::ostream& os) {
112 os << " ---------------------------"
113 "--------------------------------------------------------\n";
114 }
115
operator <<(std::ostream & os,const AsPrintableStatistics & ps)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