• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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