• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Copyright 2019 The TensorFlow Authors. All Rights Reserved.
2 
3 Licensed under the Apache License, Version 2.0 (the "License");
4 you may not use this file except in compliance with the License.
5 You may obtain a copy of the License at
6 
7     http://www.apache.org/licenses/LICENSE-2.0
8 
9 Unless required by applicable law or agreed to in writing, software
10 distributed under the License is distributed on an "AS IS" BASIS,
11 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 See the License for the specific language governing permissions and
13 limitations under the License.
14 ==============================================================================*/
15 #ifndef TENSORFLOW_CORE_PROFILER_UTILS_XPLANE_BUILDER_H_
16 #define TENSORFLOW_CORE_PROFILER_UTILS_XPLANE_BUILDER_H_
17 
18 #include <stddef.h>
19 
20 #include <string>
21 #include <utility>
22 
23 #include "absl/container/flat_hash_map.h"
24 #include "absl/strings/numbers.h"
25 #include "absl/strings/string_view.h"
26 #include "absl/types/optional.h"
27 #include "tensorflow/core/platform/macros.h"
28 #include "tensorflow/core/platform/protobuf.h"
29 #include "tensorflow/core/platform/types.h"
30 #include "tensorflow/core/profiler/protobuf/xplane.pb.h"
31 #include "tensorflow/core/profiler/utils/time_utils.h"
32 #include "tensorflow/core/profiler/utils/timespan.h"
33 
34 namespace tensorflow {
35 namespace profiler {
36 
37 class XPlaneBuilder;
38 
39 template <typename T>
40 class XStatsBuilder {
41  public:
XStatsBuilder(T * stats_owner,XPlaneBuilder * stats_metadata_owner)42   explicit XStatsBuilder(T* stats_owner, XPlaneBuilder* stats_metadata_owner)
43       : stats_owner_(stats_owner),
44         stats_metadata_owner_(stats_metadata_owner) {}
45 
46   // NOTE: A stat shouldn't have existed for the given metadata.
47   // Adds a stat for the given metadata and sets its value.
48   template <typename ValueT>
AddStatValue(const XStatMetadata & metadata,ValueT value)49   void AddStatValue(const XStatMetadata& metadata, ValueT value) {
50     SetStatValue(value, AddStat(metadata));
51   }
52 
53   // Adds or finds a stat for the given metadata and sets its value.
54   template <typename ValueT>
SetOrAddStatValue(const XStatMetadata & metadata,ValueT value)55   void SetOrAddStatValue(const XStatMetadata& metadata, ValueT value) {
56     SetStatValue(value, FindOrAddStat(metadata));
57   }
58 
59   // Adds a stat by copying a stat from another XPlane. Does not check if a stat
60   // with the same metadata already exists in the event. To avoid duplicated
61   // stats, use the variant below.
AddStat(const XStatMetadata & metadata,const XStat & src_stat,const XPlane & src_plane)62   void AddStat(const XStatMetadata& metadata, const XStat& src_stat,
63                const XPlane& src_plane) {
64     CopyStatValue(src_stat, src_plane, AddStat(metadata));
65   }
66   // Same as above but overrides an existing stat with the same metadata.
SetOrAddStat(const XStatMetadata & metadata,const XStat & src_stat,const XPlane & src_plane)67   void SetOrAddStat(const XStatMetadata& metadata, const XStat& src_stat,
68                     const XPlane& src_plane) {
69     CopyStatValue(src_stat, src_plane, FindOrAddStat(metadata));
70   }
71 
ParseAndAddStatValue(const XStatMetadata & metadata,absl::string_view value)72   void ParseAndAddStatValue(const XStatMetadata& metadata,
73                             absl::string_view value) {
74     int64_t int_value;
75     uint64 uint_value;
76     double double_value;
77     if (absl::SimpleAtoi(value, &int_value)) {
78       AddStatValue(metadata, int_value);
79     } else if (absl::SimpleAtoi(value, &uint_value)) {
80       AddStatValue(metadata, uint_value);
81     } else if (absl::SimpleAtod(value, &double_value)) {
82       AddStatValue(metadata, double_value);
83     } else {
84       AddStatValue(metadata, GetOrCreateStatMetadata(value));
85     }
86   }
87 
ReserveStats(size_t num_stats)88   void ReserveStats(size_t num_stats) {
89     stats_owner_->mutable_stats()->Reserve(num_stats);
90   }
91 
92   template <typename ForEachStatFunc>
ForEachStat(ForEachStatFunc && for_each_stat)93   void ForEachStat(ForEachStatFunc&& for_each_stat) {
94     for (XStat& stat : *stats_owner_->mutable_stats()) {
95       for_each_stat(&stat);
96     }
97   }
98 
99  private:
AddStat(const XStatMetadata & metadata)100   XStat* AddStat(const XStatMetadata& metadata) {
101     XStat* stat = stats_owner_->add_stats();
102     stat->set_metadata_id(metadata.id());
103     return stat;
104   }
105 
FindOrAddStat(const XStatMetadata & metadata)106   XStat* FindOrAddStat(const XStatMetadata& metadata) {
107     for (auto& stat : *stats_owner_->mutable_stats()) {
108       if (stat.metadata_id() == metadata.id()) {
109         return &stat;
110       }
111     }
112     return AddStat(metadata);
113   }
114 
SetStatValue(uint32 value,XStat * stat)115   static void SetStatValue(uint32 value, XStat* stat) {
116     stat->set_uint64_value(value);
117   }
SetStatValue(unsigned long value,XStat * stat)118   static void SetStatValue(unsigned long value, XStat* stat) {  // NOLINT
119     stat->set_uint64_value(value);
120   }
SetStatValue(unsigned long long value,XStat * stat)121   static void SetStatValue(unsigned long long value, XStat* stat) {  // NOLINT
122     stat->set_uint64_value(value);
123   }
SetStatValue(int32_t value,XStat * stat)124   static void SetStatValue(int32_t value, XStat* stat) {
125     stat->set_int64_value(value);
126   }
SetStatValue(long value,XStat * stat)127   static void SetStatValue(long value, XStat* stat) {  // NOLINT
128     stat->set_int64_value(value);
129   }
SetStatValue(long long value,XStat * stat)130   static void SetStatValue(long long value, XStat* stat) {  // NOLINT
131     stat->set_int64_value(value);
132   }
SetStatValue(double value,XStat * stat)133   static void SetStatValue(double value, XStat* stat) {
134     stat->set_double_value(value);
135   }
SetStatValue(absl::string_view value,XStat * stat)136   static void SetStatValue(absl::string_view value, XStat* stat) {
137     stat->set_str_value(std::string(value));
138   }
SetStatValue(std::string && value,XStat * stat)139   static void SetStatValue(std::string&& value, XStat* stat) {
140     stat->set_str_value(std::move(value));
141   }
SetStatValue(const XStatMetadata & value,XStat * stat)142   static void SetStatValue(const XStatMetadata& value, XStat* stat) {
143     stat->set_ref_value(value.id());
144   }
SetStatValue(const protobuf::MessageLite & proto,XStat * stat)145   static void SetStatValue(const protobuf::MessageLite& proto, XStat* stat) {
146     auto* bytes = stat->mutable_bytes_value();
147     proto.SerializeToString(bytes);
148   }
149 
CopyStatValue(const XStat & src_stat,const XPlane & src_plane,XStat * dst_stat)150   void CopyStatValue(const XStat& src_stat, const XPlane& src_plane,
151                      XStat* dst_stat) {
152     switch (src_stat.value_case()) {
153       case XStat::VALUE_NOT_SET:
154         break;
155       case XStat::kInt64Value:
156         dst_stat->set_int64_value(src_stat.int64_value());
157         break;
158       case XStat::kUint64Value:
159         dst_stat->set_uint64_value(src_stat.uint64_value());
160         break;
161       case XStat::kDoubleValue:
162         dst_stat->set_double_value(src_stat.double_value());
163         break;
164       case XStat::kStrValue:
165         dst_stat->set_str_value(src_stat.str_value());
166         break;
167       case XStat::kRefValue: {
168         const auto& stat_metadata_by_id = src_plane.stat_metadata();
169         const auto it = stat_metadata_by_id.find(src_stat.ref_value());
170         if (TF_PREDICT_TRUE(it != stat_metadata_by_id.end())) {
171           absl::string_view value = it->second.name();
172           dst_stat->set_ref_value(GetOrCreateStatMetadata(value).id());
173         }
174         break;
175       }
176       case XStat::kBytesValue:
177         dst_stat->set_bytes_value(src_stat.bytes_value());
178         break;
179     }
180   }
181 
182   const XStatMetadata& GetOrCreateStatMetadata(absl::string_view value);
183 
184   T* stats_owner_;
185   XPlaneBuilder* stats_metadata_owner_;
186 };
187 
188 class XEventBuilder : public XStatsBuilder<XEvent> {
189  public:
XEventBuilder(const XLine * line,XPlaneBuilder * plane,XEvent * event)190   XEventBuilder(const XLine* line, XPlaneBuilder* plane, XEvent* event)
191       : XStatsBuilder<XEvent>(event, plane), line_(line), event_(event) {}
192 
OffsetPs()193   int64 OffsetPs() const { return event_->offset_ps(); }
MetadataId()194   int64 MetadataId() const { return event_->metadata_id(); }
195 
SetOffsetPs(int64_t offset_ps)196   void SetOffsetPs(int64_t offset_ps) { event_->set_offset_ps(offset_ps); }
197 
SetOffsetNs(int64_t offset_ns)198   void SetOffsetNs(int64_t offset_ns) { SetOffsetPs(NanosToPicos(offset_ns)); }
199 
SetTimestampNs(int64_t timestamp_ns)200   void SetTimestampNs(int64_t timestamp_ns) {
201     SetOffsetPs(NanosToPicos(timestamp_ns - line_->timestamp_ns()));
202   }
203 
SetNumOccurrences(int64_t num_occurrences)204   void SetNumOccurrences(int64_t num_occurrences) {
205     event_->set_num_occurrences(num_occurrences);
206   }
207 
SetDurationPs(int64_t duration_ps)208   void SetDurationPs(int64_t duration_ps) {
209     event_->set_duration_ps(duration_ps);
210   }
SetDurationNs(int64_t duration_ns)211   void SetDurationNs(int64_t duration_ns) {
212     SetDurationPs(NanosToPicos(duration_ns));
213   }
214 
SetEndTimestampPs(int64_t end_timestamp_ps)215   void SetEndTimestampPs(int64_t end_timestamp_ps) {
216     SetDurationPs(end_timestamp_ps - PicosToNanos(line_->timestamp_ns()) -
217                   event_->offset_ps());
218   }
SetEndTimestampNs(int64_t end_timestamp_ns)219   void SetEndTimestampNs(int64_t end_timestamp_ns) {
220     SetDurationPs(NanosToPicos(end_timestamp_ns - line_->timestamp_ns()) -
221                   event_->offset_ps());
222   }
223 
GetTimespan()224   Timespan GetTimespan() const {
225     return Timespan(NanosToPicos(line_->timestamp_ns()) + event_->offset_ps(),
226                     event_->duration_ps());
227   }
228 
229  private:
230   const XLine* line_;
231   XEvent* event_;
232 };
233 
234 class XLineBuilder {
235  public:
XLineBuilder(XLine * line,XPlaneBuilder * plane)236   explicit XLineBuilder(XLine* line, XPlaneBuilder* plane)
237       : line_(line), plane_(plane) {}
238 
239   // Returns the owner plane.
Plane()240   XPlaneBuilder* Plane() const { return plane_; }
241 
Id()242   int64 Id() const { return line_->id(); }
SetId(int64_t id)243   void SetId(int64_t id) { line_->set_id(id); }
244 
NumEvents()245   int64 NumEvents() const { return line_->events_size(); }
246 
Name()247   absl::string_view Name() const { return line_->name(); }
SetName(absl::string_view name)248   void SetName(absl::string_view name) { line_->set_name(std::string(name)); }
249 
SetNameIfEmpty(absl::string_view name)250   void SetNameIfEmpty(absl::string_view name) {
251     if (line_->name().empty()) SetName(name);
252   }
253 
TimestampNs()254   int64 TimestampNs() const { return line_->timestamp_ns(); }
255   // This will set the line start timestamp.
256   // WARNING: The offset_ps of existing events will not be altered.
SetTimestampNs(int64_t timestamp_ns)257   void SetTimestampNs(int64_t timestamp_ns) {
258     line_->set_timestamp_ns(timestamp_ns);
259   }
260   // This will set the line start timestamp to specific time, and adjust
261   // the offset_ps of all existing events.
262   void SetTimestampNsAndAdjustEventOffsets(int64_t timestamp_ns);
263 
SetDurationPs(int64_t duration_ps)264   void SetDurationPs(int64_t duration_ps) {
265     line_->set_duration_ps(duration_ps);
266   }
267 
ReserveEvents(size_t num_events)268   void ReserveEvents(size_t num_events) {
269     line_->mutable_events()->Reserve(num_events);
270   }
271 
SetDisplayNameIfEmpty(absl::string_view display_name)272   void SetDisplayNameIfEmpty(absl::string_view display_name) {
273     if (line_->display_name().empty()) {
274       line_->set_display_name(std::string(display_name));
275     }
276   }
277 
278   XEventBuilder AddEvent(const XEventMetadata& metadata);
279   XEventBuilder AddEvent(const XEvent& event);
280 
281   template <typename ForEachEventFunc>
ForEachEvent(ForEachEventFunc && for_each_event)282   void ForEachEvent(ForEachEventFunc&& for_each_event) {
283     for (XEvent& event : *line_->mutable_events()) {
284       for_each_event(XEventBuilder(line_, plane_, &event));
285     }
286   }
287 
288  private:
289   XLine* line_;
290   XPlaneBuilder* plane_;
291 };
292 
293 // Provides methods to build an XPlane.
294 // NOTE: avoid to use two builders to wrap the same XPlane.
295 class XPlaneBuilder : public XStatsBuilder<XPlane> {
296  public:
297   explicit XPlaneBuilder(XPlane* plane);
298 
Id()299   int64 Id() const { return plane_->id(); }
SetId(int64_t id)300   void SetId(int64_t id) { plane_->set_id(id); }
301 
Name()302   absl::string_view Name() const { return plane_->name(); }
SetName(absl::string_view name)303   void SetName(absl::string_view name) { plane_->set_name(std::string(name)); }
304 
ReserveLines(size_t num_lines)305   void ReserveLines(size_t num_lines) {
306     plane_->mutable_lines()->Reserve(num_lines);
307   }
308 
309   template <typename ForEachLineFunc>
ForEachLine(ForEachLineFunc && for_each_line)310   void ForEachLine(ForEachLineFunc&& for_each_line) {
311     for (XLine& line : *plane_->mutable_lines()) {
312       for_each_line(XLineBuilder(&line, this));
313     }
314   }
315 
316   // Returns a builder for the line with the given id. Creates a new line if the
317   // id was unused, otherwise the builder will add events to an existing line.
318   XLineBuilder GetOrCreateLine(int64_t line_id);
319 
320   // Returns a new event metadata with an automatically generated metadata_id.
321   // WARNING: If calling this function, don't call GetOrCreateEventMetadata.
322   XEventMetadata* CreateEventMetadata();
323 
324   // Returns event metadata with the given id. Creates a new metadata if the id
325   // was unused.
326   // WARNING: If calling this function, don't call the string overloads below
327   // on the same instance.
328   XEventMetadata* GetOrCreateEventMetadata(int64_t metadata_id);
329 
330   // Returns event metadata with the given name. The id is internally assigned.
331   // Creates a new metadata if the name was unused.
332   // Using these overloads guarantees names are unique.
333   // WARNING: If calling any of these overloads, do not call the integer one
334   // above on the same instance.
335   XEventMetadata* GetOrCreateEventMetadata(absl::string_view name);
336   XEventMetadata* GetOrCreateEventMetadata(std::string&& name);
GetOrCreateEventMetadata(const char * name)337   XEventMetadata* GetOrCreateEventMetadata(const char* name) {
338     return GetOrCreateEventMetadata(absl::string_view(name));
339   }
340 
341   // Returns event metadata with the given name. Returns nullptr if not found.
342   XEventMetadata* GetEventMetadata(absl::string_view name) const;
343 
344   // Returns stat metadata with the given name. Returns nullptr if not found.
345   XStatMetadata* GetStatMetadata(absl::string_view name) const;
346 
347   // Returns a new stat metadata with an automatically generated metadata_id.
348   // WARNING: If calling this function, don't call GetOrCreateEventMetadata.
349   XStatMetadata* CreateStatMetadata();
350 
351   // Returns stat metadata with the given id. Creates a new metadata if the id
352   // was unused.
353   // WARNING: If calling this function, don't call the string overloads below
354   // on the same instance.
355   XStatMetadata* GetOrCreateStatMetadata(int64_t metadata_id);
356 
357   // Returns stat metadata with the given name. The id is internally assigned.
358   // Creates a new metadata if the name was unused.
359   // Using these overloads guarantees names are unique.
360   // WARNING: If calling any of these overloads, do not call the integer one
361   // above on the same instance.
362   XStatMetadata* GetOrCreateStatMetadata(absl::string_view name);
363   XStatMetadata* GetOrCreateStatMetadata(std::string&& name);
GetOrCreateStatMetadata(const char * name)364   XStatMetadata* GetOrCreateStatMetadata(const char* name) {
365     return GetOrCreateStatMetadata(absl::string_view(name));
366   }
367 
368  private:
369   XPlane* plane_;
370 
371   // Artifacts to accelerate the builders.
372   int64 last_event_metadata_id_ = 0LL;
373   int64 last_stat_metadata_id_ = 0LL;
374   absl::flat_hash_map<std::string, XEventMetadata*> event_metadata_by_name_;
375   absl::flat_hash_map<std::string, XStatMetadata*> stat_metadata_by_name_;
376   absl::flat_hash_map<int64, XLine*> lines_by_id_;
377 };
378 
379 template <typename T>
GetOrCreateStatMetadata(absl::string_view value)380 const XStatMetadata& XStatsBuilder<T>::GetOrCreateStatMetadata(
381     absl::string_view value) {
382   return *stats_metadata_owner_->GetOrCreateStatMetadata(value);
383 }
384 
385 }  // namespace profiler
386 }  // namespace tensorflow
387 
388 #endif  // TENSORFLOW_CORE_PROFILER_UTILS_XPLANE_BUILDER_H_
389