• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "src/diagnostics/compilation-statistics.h"
6 
7 #include <ostream>
8 #include <vector>
9 
10 #include "src/base/platform/platform.h"
11 
12 namespace v8 {
13 namespace internal {
14 
RecordPhaseStats(const char * phase_kind_name,const char * phase_name,const BasicStats & stats)15 void CompilationStatistics::RecordPhaseStats(const char* phase_kind_name,
16                                              const char* phase_name,
17                                              const BasicStats& stats) {
18   base::MutexGuard guard(&record_mutex_);
19 
20   std::string phase_name_str(phase_name);
21   auto it = phase_map_.find(phase_name_str);
22   if (it == phase_map_.end()) {
23     PhaseStats phase_stats(phase_map_.size(), phase_kind_name);
24     it = phase_map_.insert(std::make_pair(phase_name_str, phase_stats)).first;
25   }
26   it->second.Accumulate(stats);
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::MutexGuard 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_
38              .insert(std::make_pair(phase_kind_name_str, phase_kind_stats))
39              .first;
40   }
41   it->second.Accumulate(stats);
42 }
43 
RecordTotalStats(const BasicStats & stats)44 void CompilationStatistics::RecordTotalStats(const BasicStats& stats) {
45   base::MutexGuard guard(&record_mutex_);
46   total_stats_.Accumulate(stats);
47 }
48 
Accumulate(const BasicStats & stats)49 void CompilationStatistics::BasicStats::Accumulate(const BasicStats& stats) {
50   delta_ += stats.delta_;
51   total_allocated_bytes_ += stats.total_allocated_bytes_;
52   if (stats.absolute_max_allocated_bytes_ > absolute_max_allocated_bytes_) {
53     absolute_max_allocated_bytes_ = stats.absolute_max_allocated_bytes_;
54     max_allocated_bytes_ = stats.max_allocated_bytes_;
55     function_name_ = stats.function_name_;
56   }
57 }
58 
AsJSON()59 std::string CompilationStatistics::BasicStats::AsJSON() {
60 // clang-format off
61 #define DICT(s) "{" << s << "}"
62 #define QUOTE(s) "\"" << s << "\""
63 #define MEMBER(s) QUOTE(s) << ":"
64 
65   DCHECK_EQ(function_name_.find("\""), std::string::npos);
66 
67   std::stringstream stream;
68   stream << DICT(
69     MEMBER("function_name") << QUOTE(function_name_) << ","
70     MEMBER("total_allocated_bytes") << total_allocated_bytes_ << ","
71     MEMBER("max_allocated_bytes") << max_allocated_bytes_ << ","
72     MEMBER("absolute_max_allocated_bytes") << absolute_max_allocated_bytes_);
73 
74   return stream.str();
75 
76 #undef DICT
77 #undef QUOTE
78 #undef MEMBER
79   // clang-format on
80 }
81 
WriteLine(std::ostream & os,bool machine_format,const char * name,const CompilationStatistics::BasicStats & stats,const CompilationStatistics::BasicStats & total_stats)82 static void WriteLine(std::ostream& os, bool machine_format, const char* name,
83                       const CompilationStatistics::BasicStats& stats,
84                       const CompilationStatistics::BasicStats& total_stats) {
85   const size_t kBufferSize = 128;
86   char buffer[kBufferSize];
87 
88   double ms = stats.delta_.InMillisecondsF();
89   double percent = stats.delta_.PercentOf(total_stats.delta_);
90   double size_percent =
91       static_cast<double>(stats.total_allocated_bytes_ * 100) /
92       static_cast<double>(total_stats.total_allocated_bytes_);
93   if (machine_format) {
94     base::OS::SNPrintF(buffer, kBufferSize,
95                        "\"%s_time\"=%.3f\n\"%s_space\"=%zu", name, ms, name,
96                        stats.total_allocated_bytes_);
97     os << buffer;
98   } else {
99     base::OS::SNPrintF(buffer, kBufferSize,
100                        "%34s %10.3f (%5.1f%%)  %10zu (%5.1f%%) %10zu %10zu",
101                        name, ms, percent, stats.total_allocated_bytes_,
102                        size_percent, stats.max_allocated_bytes_,
103                        stats.absolute_max_allocated_bytes_);
104 
105     os << buffer;
106     if (!stats.function_name_.empty()) {
107       os << "   " << stats.function_name_.c_str();
108     }
109     os << std::endl;
110   }
111 }
112 
WriteFullLine(std::ostream & os)113 static void WriteFullLine(std::ostream& os) {
114   os << "-----------------------------------------------------------"
115         "-----------------------------------------------------------\n";
116 }
117 
WriteHeader(std::ostream & os)118 static void WriteHeader(std::ostream& os) {
119   WriteFullLine(os);
120   os << "                Turbofan phase            Time (ms)    "
121      << "                   Space (bytes)             Function\n"
122      << "                                                       "
123      << "          Total          Max.     Abs. max.\n";
124   WriteFullLine(os);
125 }
126 
WritePhaseKindBreak(std::ostream & os)127 static void WritePhaseKindBreak(std::ostream& os) {
128   os << "                                   ------------------------"
129         "-----------------------------------------------------------\n";
130 }
131 
operator <<(std::ostream & os,const AsPrintableStatistics & ps)132 std::ostream& operator<<(std::ostream& os, const AsPrintableStatistics& ps) {
133   // phase_kind_map_ and phase_map_ don't get mutated, so store a bunch of
134   // pointers into them.
135   const CompilationStatistics& s = ps.s;
136 
137   using SortedPhaseKinds =
138       std::vector<CompilationStatistics::PhaseKindMap::const_iterator>;
139   SortedPhaseKinds sorted_phase_kinds(s.phase_kind_map_.size());
140   for (auto it = s.phase_kind_map_.begin(); it != s.phase_kind_map_.end();
141        ++it) {
142     sorted_phase_kinds[it->second.insert_order_] = it;
143   }
144 
145   using SortedPhases =
146       std::vector<CompilationStatistics::PhaseMap::const_iterator>;
147   SortedPhases sorted_phases(s.phase_map_.size());
148   for (auto it = s.phase_map_.begin(); it != s.phase_map_.end(); ++it) {
149     sorted_phases[it->second.insert_order_] = it;
150   }
151 
152   if (!ps.machine_output) WriteHeader(os);
153   for (const auto& phase_kind_it : sorted_phase_kinds) {
154     const auto& phase_kind_name = phase_kind_it->first;
155     if (!ps.machine_output) {
156       for (const auto& phase_it : sorted_phases) {
157         const auto& phase_stats = phase_it->second;
158         if (phase_stats.phase_kind_name_ != phase_kind_name) continue;
159         const auto& phase_name = phase_it->first;
160         WriteLine(os, ps.machine_output, phase_name.c_str(), phase_stats,
161                   s.total_stats_);
162       }
163       WritePhaseKindBreak(os);
164     }
165     const auto& phase_kind_stats = phase_kind_it->second;
166     WriteLine(os, ps.machine_output, phase_kind_name.c_str(), phase_kind_stats,
167               s.total_stats_);
168     os << std::endl;
169   }
170 
171   if (!ps.machine_output) WriteFullLine(os);
172   WriteLine(os, ps.machine_output, "totals", s.total_stats_, s.total_stats_);
173 
174   return os;
175 }
176 
177 }  // namespace internal
178 }  // namespace v8
179