Home | History | Annotate | Download | only in base
      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 
    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