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