1 /* 2 * Copyright (C) 2011 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef ART_RUNTIME_BASE_TIMING_LOGGER_H_ 18 #define ART_RUNTIME_BASE_TIMING_LOGGER_H_ 19 20 #include "base/histogram.h" 21 #include "base/macros.h" 22 #include "base/mutex.h" 23 24 #include <string> 25 #include <vector> 26 #include <map> 27 28 namespace art { 29 30 namespace base { 31 class TimingLogger; 32 } // namespace base 33 34 class CumulativeLogger { 35 public: 36 explicit CumulativeLogger(const std::string& name); 37 void prepare_stats(); 38 ~CumulativeLogger(); 39 void Start(); 40 void End(); 41 void Reset(); 42 void Dump(std::ostream& os) LOCKS_EXCLUDED(lock_); 43 uint64_t GetTotalNs() const; 44 // Allow the name to be modified, particularly when the cumulative logger is a field within a 45 // parent class that is unable to determine the "name" of a sub-class. 46 void SetName(const std::string& name); 47 void AddLogger(const base::TimingLogger& logger) LOCKS_EXCLUDED(lock_); 48 49 private: 50 typedef std::map<std::string, Histogram<uint64_t> *> Histograms; 51 typedef std::map<std::string, Histogram<uint64_t> *>::const_iterator HistogramsIterator; 52 53 void AddPair(const std::string &label, uint64_t delta_time) 54 EXCLUSIVE_LOCKS_REQUIRED(lock_); 55 void DumpHistogram(std::ostream &os) EXCLUSIVE_LOCKS_REQUIRED(lock_); 56 uint64_t GetTotalTime() const; 57 static const uint64_t kAdjust = 1000; 58 Histograms histograms_ GUARDED_BY(lock_); 59 std::string name_; 60 const std::string lock_name_; 61 mutable Mutex lock_ DEFAULT_MUTEX_ACQUIRED_AFTER; 62 size_t iterations_ GUARDED_BY(lock_); 63 64 DISALLOW_COPY_AND_ASSIGN(CumulativeLogger); 65 }; 66 67 namespace base { 68 69 70 // A timing logger that knows when a split starts for the purposes of logging tools, like systrace. 71 class TimingLogger { 72 public: 73 // Splits are nanosecond times and split names. 74 typedef std::pair<uint64_t, const char*> SplitTiming; 75 typedef std::vector<SplitTiming> SplitTimings; 76 typedef std::vector<SplitTiming>::const_iterator SplitTimingsIterator; 77 78 explicit TimingLogger(const char* name, bool precise, bool verbose); 79 80 // Clears current splits and labels. 81 void Reset(); 82 83 // Starts a split 84 void StartSplit(const char* new_split_label); 85 86 // Ends the current split and starts the one given by the label. 87 void NewSplit(const char* new_split_label); 88 89 // Ends the current split and records the end time. 90 void EndSplit(); 91 92 uint64_t GetTotalNs() const; 93 94 void Dump(std::ostream& os) const; 95 96 // Scoped timing splits that can be nested and composed with the explicit split 97 // starts and ends. 98 class ScopedSplit { 99 public: 100 explicit ScopedSplit(const char* label, TimingLogger* timing_logger); 101 102 ~ScopedSplit(); 103 104 friend class TimingLogger; 105 106 private: 107 // Pauses timing of the split, usually due to nesting of another split. 108 void Pause(); 109 110 // Resumes timing of the split, usually because a nested split has ended. 111 void Resume(); 112 113 // Used by new split to swap splits in place in a ScopedSplit instance. 114 void TailInsertSplit(const char* label); 115 116 // The scoped split immediately enclosing this split. Essentially, we get a 117 // stack of nested splits through this field. 118 ScopedSplit* enclosing_split_; 119 120 // Was this created via TimingLogger's StartSplit? 121 bool explicit_; 122 123 // The split's name. 124 const char* label_; 125 126 // The current split's latest start time. (It may have been paused and restarted.) 127 uint64_t start_ns_; 128 129 // The running time, outside of pauses. 130 uint64_t running_ns_; 131 132 // The timing logger holding this split. 133 TimingLogger* timing_logger_; 134 135 DISALLOW_COPY_AND_ASSIGN(ScopedSplit); 136 }; 137 GetSplits()138 const SplitTimings& GetSplits() const { 139 return splits_; 140 } 141 142 friend class ScopedSplit; 143 protected: 144 // The name of the timing logger. 145 const char* name_; 146 147 // Do we want to print the exactly recorded split (true) or round down to the time unit being 148 // used (false). 149 const bool precise_; 150 151 // Verbose logging. 152 const bool verbose_; 153 154 // The current scoped split is also the 'top' of the stack of splits in progress. 155 ScopedSplit* current_split_; 156 157 // Splits that have ended. 158 SplitTimings splits_; 159 160 private: 161 DISALLOW_COPY_AND_ASSIGN(TimingLogger); 162 }; 163 164 } // namespace base 165 } // namespace art 166 167 #endif // ART_RUNTIME_BASE_TIMING_LOGGER_H_ 168