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
11namespace v8 {
12namespace internal {
13
14void 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
27void 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
40void CompilationStatistics::RecordTotalStats(size_t source_size,
41                                             const BasicStats& stats) {
42  source_size += source_size;
43  total_stats_.Accumulate(stats);
44}
45
46
47void 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
57static 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
89static void WriteFullLine(std::ostream& os) {
90  os << "--------------------------------------------------------"
91        "--------------------------------------------------------\n";
92}
93
94
95static 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
105static void WritePhaseKindBreak(std::ostream& os) {
106  os << "                             ---------------------------"
107        "--------------------------------------------------------\n";
108}
109
110std::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