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