timing_logger.h revision 4654322261c8e4d799acdea60a7e227f33c5c2db
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
28namespace art {
29
30namespace base {
31  class TimingLogger;
32}  // namespace base
33
34class CumulativeLogger {
35 public:
36  typedef std::map<std::string, Histogram<uint64_t> *> Histograms;
37  typedef std::map<std::string, Histogram<uint64_t> *>::const_iterator HistogramsIterator;
38
39  explicit CumulativeLogger(const std::string& name);
40  void prepare_stats();
41  ~CumulativeLogger();
42  void Start();
43  void End();
44  void Reset();
45  void Dump(std::ostream& os) LOCKS_EXCLUDED(lock_);
46  uint64_t GetTotalNs() const;
47  // Allow the name to be modified, particularly when the cumulative logger is a field within a
48  // parent class that is unable to determine the "name" of a sub-class.
49  void SetName(const std::string& name);
50  void AddLogger(const base::TimingLogger& logger) LOCKS_EXCLUDED(lock_);
51
52 private:
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
67namespace base {
68
69
70// A timing logger that knows when a split starts for the purposes of logging tools, like systrace.
71class 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 SplitsIterator;
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
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