• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright 2019 Huawei Technologies Co., Ltd
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 MINDSPORE_CORE_UTILS_PROFILE_H_
18 #define MINDSPORE_CORE_UTILS_PROFILE_H_
19 
20 #include <map>
21 #include <string>
22 #include <fstream>
23 #include <iomanip>
24 #include <sstream>
25 #include "utils/log_adapter.h"
26 
27 namespace mindspore {
28 struct TimeInfo;
29 using TimeInfoMap = std::map<std::string, const TimeInfo *>;
30 
31 extern double GetTime();
32 
33 class ProfileBase;
34 
35 struct TimeInfo {
time_TimeInfo36   explicit TimeInfo(double time = -1.0) : time_(time), dict_(nullptr), actionNum_(0) {}
37   TimeInfo(const TimeInfo &) = delete;
38   ~TimeInfo();
39 
40   double time_;
41   TimeInfoMap *dict_;
42   size_t actionNum_;
43 };
44 
45 // Utility class for Profile.
46 class ProfContext {
47   friend class Profile;
48   friend class ProfileBase;
49   friend class ProfTransaction;
50 
51  public:
52   ProfContext(const std::string &name, ProfileBase *prof);
53   ~ProfContext();
54 
55   ProfContext(const ProfContext &) = delete;
56   ProfContext &operator=(const ProfContext &) = delete;
57 
58   void SetTime(double time) noexcept;
59   void Insert(const std::string &name, const TimeInfo *time) noexcept;
60   bool IsTopContext() const noexcept;
61 
62  private:
63   std::string name_;
64   ProfileBase *prof_;
65   ProfContext *parent_;
66   TimeInfo *time_info_;
67 };
68 
69 class ProfileBase {
70   friend class ProfContext;
71   friend class ProfTransaction;
72 
73  public:
74   ProfileBase();
75   virtual ~ProfileBase();
76 
Print(void)77   virtual void Print(void) {}
Step(const std::string &)78   virtual ProfContext *Step(const std::string &) { return nullptr; }
Lap(int)79   virtual ProfContext *Lap(int) { return nullptr; }
Pop(void)80   virtual void Pop(void) noexcept {}
81 
82   // top level profile context
83   ProfContext context_;
84   // profile context pointer, act as a stack pointer
85   ProfContext *ctx_ptr_ = nullptr;
86 };
87 
88 class Profile : public ProfileBase {
89  public:
90   Profile() = default;
91   ~Profile() override = default;
92   Profile(const Profile &) = delete;
93   Profile &operator=(const Profile &) = delete;
94 
95   void Print(void) override;
96   ProfContext *Step(const std::string &name) override;
97   ProfContext *Lap(int count) override;
98   void Pop(void) noexcept override;
99 };
100 
101 class ProfTransaction {
102  public:
103   explicit ProfTransaction(const ProfileBase *prof);
ProfTransaction(ProfContext * const ctx)104   explicit ProfTransaction(ProfContext *const ctx) : ctx_(ctx) {}
105   ProfTransaction(const ProfTransaction &) = delete;
106   ~ProfTransaction();
107 
108   template <class Function>
109   void operator-(const Function &func) {
110     double start_time = GetTime();
111     func();
112     double end_time = GetTime();
113     if (ctx_ != nullptr) {
114       ctx_->SetTime(end_time - start_time);
115     }
116   }
117 
118  private:
119   ProfContext *ctx_ = nullptr;
120 };
121 
122 class NoProfTransaction {
123  public:
NoProfTransaction(ProfileBase * prof)124   explicit NoProfTransaction(ProfileBase *prof) {}
NoProfTransaction(ProfContext * ctx)125   explicit NoProfTransaction(ProfContext *ctx) {}
126   ~NoProfTransaction() = default;
127 
128   template <class Function>
129   void operator-(const Function &func) {
130     func();
131   }
132 };
133 
134 class DumpTime {
135  public:
~DumpTime()136   ~DumpTime() {
137     try {
138       Save();
139     } catch (const std::exception &e) {
140       MS_LOG(ERROR) << "Cannot save file by profile::DumpTime::save";
141     } catch (...) {
142       MS_LOG(ERROR) << "Uncaught exception";
143     }
144   }
145   DumpTime(const DumpTime &) = delete;
146   DumpTime &operator=(const DumpTime &) = delete;
GetInstance()147   static DumpTime &GetInstance() {
148     static DumpTime instance;
149     return instance;
150   }
set_file_path(const std::string & save_path)151   void set_file_path(const std::string &save_path) { file_path_ = save_path; }
152   void Record(const std::string &name, const double time, const bool is_start);
153   void Save();
154 
155  private:
156   DumpTime() = default;
157   std::stringstream file_ss_;
158   std::ofstream file_out_;
159   std::string file_path_ = "./timeline.json";
160 };
161 
162 struct TimeStat {
TimeStatTimeStat163   TimeStat() {
164     time_ = 0.0;
165     count_ = 0;
166   }
167   ~TimeStat() = default;
168 
169   void operator+=(double t) {
170     time_ += t;
171     count_ += 1;
172   }
173 
174   TimeStat operator+(double t) {
175     TimeStat ts = *this;
176     ts += t;
177     return ts;
178   }
179 
180   double time_;
181   int count_;
182 };
183 
184 class MsProfile {
185  public:
~MsProfile()186   ~MsProfile() { Clear(); }
187 
Reset()188   static void Reset() { GetSingleton().Clear(); }
189 
GetProfile()190   static ProfileBase *GetProfile() {
191     MsProfile &ms_prof = GetSingleton();
192     if (ms_prof.profile_ == nullptr) {
193 #ifdef ENABLE_PROFILE
194       ms_prof.profile_ = new Profile();
195 #else
196       ms_prof.profile_ = new ProfileBase();
197 #endif
198     }
199     return ms_prof.profile_;
200   }
StatTime(const std::string & id,double time)201   static void StatTime(const std::string &id, double time) { GetSingleton().time_stat_[id] += time; }
202 
203   static void Print();
204 
205  private:
206   MsProfile() = default;
207 
GetSingleton()208   static MsProfile &GetSingleton() {
209     static MsProfile profile;
210     return profile;
211   }
212 
Clear()213   void Clear() {
214     time_stat_.clear();
215     if (profile_ != nullptr) {
216       delete profile_;
217       profile_ = nullptr;
218     }
219   }
220 
221   std::map<std::string, TimeStat> time_stat_;  // record time and count info from some activity
222   ProfileBase *profile_ = nullptr;             // record hierarchical profile info
223 };
224 }  // namespace mindspore
225 
226 #ifdef ENABLE_PROFILE
227 #define WITH(x) ProfTransaction(x) -
228 #else
229 #define WITH(x) NoProfTransaction(x) -
230 #endif
231 
232 #endif  // MINDSPORE_CORE_UTILS_PROFILE_H_
233