1 // Copyright 2016 Google Inc. All Rights Reserved. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #ifndef NINJA_STATUS_H_ 16 #define NINJA_STATUS_H_ 17 18 #include <map> 19 #include <string> 20 21 #include "build.h" 22 #include "line_printer.h" 23 24 /// Abstract interface to object that tracks the status of a build: 25 /// completion fraction, printing updates. 26 struct Status { 27 virtual void EdgeAddedToPlan(const Edge* edge) = 0; 28 virtual void EdgeRemovedFromPlan(const Edge* edge) = 0; 29 virtual void BuildEdgeStarted(const Edge* edge, 30 int64_t start_time_millis) = 0; 31 virtual void BuildEdgeFinished(Edge* edge, int64_t start_time_millis, 32 int64_t end_time_millis, bool success, 33 const std::string& output) = 0; 34 virtual void BuildLoadDyndeps() = 0; 35 virtual void BuildStarted() = 0; 36 virtual void BuildFinished() = 0; 37 38 virtual void Info(const char* msg, ...) = 0; 39 virtual void Warning(const char* msg, ...) = 0; 40 virtual void Error(const char* msg, ...) = 0; 41 ~StatusStatus42 virtual ~Status() { } 43 }; 44 45 /// Implementation of the Status interface that prints the status as 46 /// human-readable strings to stdout 47 struct StatusPrinter : Status { 48 explicit StatusPrinter(const BuildConfig& config); 49 50 /// Callbacks for the Plan to notify us about adding/removing Edge's. 51 virtual void EdgeAddedToPlan(const Edge* edge); 52 virtual void EdgeRemovedFromPlan(const Edge* edge); 53 54 virtual void BuildEdgeStarted(const Edge* edge, int64_t start_time_millis); 55 virtual void BuildEdgeFinished(Edge* edge, int64_t start_time_millis, 56 int64_t end_time_millis, bool success, 57 const std::string& output); 58 virtual void BuildLoadDyndeps(); 59 virtual void BuildStarted(); 60 virtual void BuildFinished(); 61 62 virtual void Info(const char* msg, ...); 63 virtual void Warning(const char* msg, ...); 64 virtual void Error(const char* msg, ...); 65 ~StatusPrinterStatusPrinter66 virtual ~StatusPrinter() { } 67 68 /// Format the progress status string by replacing the placeholders. 69 /// See the user manual for more information about the available 70 /// placeholders. 71 /// @param progress_status_format The format of the progress status. 72 /// @param status The status of the edge. 73 std::string FormatProgressStatus(const char* progress_status_format, 74 int64_t time_millis) const; 75 76 private: 77 void PrintStatus(const Edge* edge, int64_t time_millis); 78 79 const BuildConfig& config_; 80 81 int started_edges_, finished_edges_, total_edges_, running_edges_; 82 83 /// How much wall clock elapsed so far? 84 int64_t time_millis_ = 0; 85 86 /// How much cpu clock elapsed so far? 87 int64_t cpu_time_millis_ = 0; 88 89 /// What percentage of predicted total time have elapsed already? 90 double time_predicted_percentage_ = 0.0; 91 92 /// Out of all the edges, for how many do we know previous time? 93 int eta_predictable_edges_total_ = 0; 94 /// And how much time did they all take? 95 int64_t eta_predictable_cpu_time_total_millis_ = 0; 96 97 /// Out of all the non-finished edges, for how many do we know previous time? 98 int eta_predictable_edges_remaining_ = 0; 99 /// And how much time will they all take? 100 int64_t eta_predictable_cpu_time_remaining_millis_ = 0; 101 102 /// For how many edges we don't know the previous run time? 103 int eta_unpredictable_edges_remaining_ = 0; 104 105 void RecalculateProgressPrediction(); 106 107 /// Prints progress output. 108 LinePrinter printer_; 109 110 /// The custom progress status format to use. 111 const char* progress_status_format_; 112 113 template<size_t S> SnprintfRateStatusPrinter114 void SnprintfRate(double rate, char(&buf)[S], const char* format) const { 115 if (rate == -1) 116 snprintf(buf, S, "?"); 117 else 118 snprintf(buf, S, format, rate); 119 } 120 121 struct SlidingRateInfo { SlidingRateInfoStatusPrinter::SlidingRateInfo122 SlidingRateInfo(int n) : rate_(-1), N(n), last_update_(-1) {} 123 rateStatusPrinter::SlidingRateInfo124 double rate() { return rate_; } 125 UpdateRateStatusPrinter::SlidingRateInfo126 void UpdateRate(int update_hint, int64_t time_millis) { 127 if (update_hint == last_update_) 128 return; 129 last_update_ = update_hint; 130 131 if (times_.size() == N) 132 times_.pop(); 133 times_.push(time_millis); 134 if (times_.back() != times_.front()) 135 rate_ = times_.size() / ((times_.back() - times_.front()) / 1e3); 136 } 137 138 private: 139 double rate_; 140 const size_t N; 141 std::queue<double> times_; 142 int last_update_; 143 }; 144 145 mutable SlidingRateInfo current_rate_; 146 }; 147 148 #endif // NINJA_STATUS_H_ 149