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_UTILS_H_
16 #define TENSORFLOW_CORE_PROFILER_UTILS_XPLANE_UTILS_H_
17
18 #include <vector>
19
20 #include "absl/container/flat_hash_map.h"
21 #include "absl/container/flat_hash_set.h"
22 #include "absl/strings/string_view.h"
23 #include "tensorflow/core/platform/types.h"
24 #include "tensorflow/core/profiler/protobuf/xplane.pb.h"
25 #include "tensorflow/core/profiler/utils/timespan.h"
26 #include "tensorflow/core/profiler/utils/trace_utils.h"
27
28 namespace tensorflow {
29 namespace profiler {
30
31 // Returns a Timespan from an XEvent.
32 // WARNING: This should only be used when comparing events from the same XLine.
XEventTimespan(const XEvent & event)33 inline Timespan XEventTimespan(const XEvent& event) {
34 return Timespan(event.offset_ps(), event.duration_ps());
35 }
36
37 // Returns the plane with the given name or nullptr if not found.
38 const XPlane* FindPlaneWithName(const XSpace& space, absl::string_view name);
39 XPlane* FindMutablePlaneWithName(XSpace* space, absl::string_view name);
40
41 // Returns the planes with the given names, if found.
42 std::vector<const XPlane*> FindPlanesWithNames(
43 const XSpace& space, const std::vector<absl::string_view>& names);
44
45 // Returns the plane with the given name in the container. If necessary, adds a
46 // new plane to the container.
47 XPlane* FindOrAddMutablePlaneWithName(XSpace* space, absl::string_view name);
48
49 // Returns all the planes with a given prefix.
50 std::vector<const XPlane*> FindPlanesWithPrefix(const XSpace& space,
51 absl::string_view prefix);
52 std::vector<XPlane*> FindMutablePlanesWithPrefix(XSpace* space,
53 absl::string_view prefix);
54
55 // Returns the plane with the given id or nullptr if not found.
56 const XLine* FindLineWithId(const XPlane& plane, int64 id);
57
58 XStat* FindOrAddMutableStat(const XStatMetadata& stat_metadata, XEvent* event);
59
60 void RemovePlane(XSpace* space, const XPlane* plane);
61 void RemovePlanes(XSpace* space, const std::vector<const XPlane*>& planes);
62 void RemoveLine(XPlane* plane, const XLine* line);
63 void RemoveEvents(XLine* line,
64 const absl::flat_hash_set<const XEvent*>& events);
65
66 void RemoveEmptyPlanes(XSpace* space);
67 void RemoveEmptyLines(XPlane* plane);
68
69 // Sort lines in plane with a provided comparator.
70 template <class Compare>
SortXLinesBy(XPlane * plane,Compare comp)71 void SortXLinesBy(XPlane* plane, Compare comp) {
72 std::sort(plane->mutable_lines()->pointer_begin(),
73 plane->mutable_lines()->pointer_end(), comp);
74 }
75
76 class XLinesComparatorByName {
77 public:
operator()78 bool operator()(const XLine* a, const XLine* b) const {
79 auto& line_a = a->display_name().empty() ? a->name() : a->display_name();
80 auto& line_b = b->display_name().empty() ? b->name() : b->display_name();
81 return line_a < line_b;
82 }
83 };
84
85 // Sorts each XLine's XEvents by offset_ps (ascending) and duration_ps
86 // (descending) so nested events are sorted from outer to innermost.
87 void SortXPlane(XPlane* plane);
88 // Sorts each plane of the XSpace.
89 void SortXSpace(XSpace* space);
90
91 // Functor that compares XEvents for sorting by timespan.
92 struct XEventsComparator {
93 bool operator()(const XEvent* a, const XEvent* b) const;
94 };
95
96 // Returns a sorted vector of all XEvents in the given XPlane.
97 template <class Compare>
98 std::vector<XEvent*> GetSortedEvents(XPlane* plane, Compare comp,
99 bool include_derived_events = false) {
100 std::vector<XEvent*> events;
101 for (XLine& line : *plane->mutable_lines()) {
102 if (!include_derived_events && IsDerivedThreadId(line.id())) continue;
103 for (XEvent& event : *line.mutable_events()) {
104 events.push_back(&event);
105 }
106 }
107 absl::c_sort(events, XEventsComparator());
108 return events;
109 }
110
111 // Normalize timestamps by time-shifting to start_time_ns_ as origin.
112 void NormalizeTimestamps(XPlane* plane, uint64 start_time_ns);
113 void NormalizeTimestamps(XSpace* space, uint64 start_time_ns);
114
115 // Merges src_plane into dst_plane. Both plane level stats, lines, events and
116 // event level stats are merged. If src_plane and dst_plane both have the same
117 // line, which have different start timestamps, we will normalize the events
118 // offset timestamp correspondingly.
119 void MergePlanes(const XPlane& src_plane, XPlane* dst_plane);
120
121 // Merges each plane with a src_planes, into the dst_plane.
122 void MergePlanes(const std::vector<const XPlane*>& src_planes,
123 XPlane* dst_plane);
124
125 // Plane's start timestamp is defined as the minimum of all lines' start
126 // timestamps. If zero line exists, return 0;
127 uint64 GetStartTimestampNs(const XPlane& plane);
128
129 // Returns true if there are no XEvents.
130 bool IsEmpty(const XSpace& space);
131
132 } // namespace profiler
133 } // namespace tensorflow
134
135 #endif // TENSORFLOW_CORE_PROFILER_UTILS_XPLANE_UTILS_H_
136