1 /* Copyright 2020 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_LIB_TRACEME_ENCODE_H_
16 #define TENSORFLOW_CORE_PROFILER_LIB_TRACEME_ENCODE_H_
17
18 #include <string.h>
19
20 #include <initializer_list>
21 #include <string>
22
23 #include "absl/strings/match.h"
24 #include "absl/strings/str_cat.h"
25 #include "absl/strings/string_view.h"
26 #include "tensorflow/core/platform/logging.h"
27 #include "tensorflow/core/platform/macros.h"
28
29 namespace tensorflow {
30 namespace profiler {
31
32 // An argument passed to TraceMeEncode.
33 struct TraceMeArg {
34 // This constructor is required because absl::AlphaNum is non-copyable.
35 template <typename Value>
TraceMeArgTraceMeArg36 TraceMeArg(absl::string_view k, Value v) : key(k), value(v) {}
37
38 TF_DISALLOW_COPY_AND_ASSIGN(TraceMeArg);
39
40 absl::string_view key;
41 absl::AlphaNum value;
42 };
43
44 namespace traceme_internal {
45
46 // Copies the contents of str to the address pointed by out.
47 // Returns the address after the copy.
48 // REQUIRED: The address range [out, out + str.size()] must have been allocated.
Append(char * out,absl::string_view str)49 TF_ATTRIBUTE_ALWAYS_INLINE inline char* Append(char* out,
50 absl::string_view str) {
51 DCHECK(!absl::StrContains(str, "#"))
52 << "'#' is not a valid character in TraceMeEncode";
53 const size_t str_size = str.size();
54 if (TF_PREDICT_TRUE(str_size > 0)) {
55 memcpy(out, str.data(), str_size);
56 out += str_size;
57 }
58 return out;
59 }
60
61 // Appends args encoded as TraceMe metadata to name.
AppendArgs(std::string name,std::initializer_list<TraceMeArg> args)62 TF_ATTRIBUTE_ALWAYS_INLINE inline std::string AppendArgs(
63 std::string name, std::initializer_list<TraceMeArg> args) {
64 if (TF_PREDICT_TRUE(args.size() > 0)) {
65 const auto old_size = name.size();
66 auto new_size = old_size + args.size() * 2 + 1;
67 for (const auto& arg : args) {
68 new_size += arg.key.size() + arg.value.size();
69 }
70 name.resize(new_size);
71 char* const begin = &name[0];
72 char* out = begin + old_size;
73 *out++ = '#';
74 for (const auto& arg : args) {
75 out = Append(out, arg.key);
76 *out++ = '=';
77 out = Append(out, arg.value.Piece());
78 *out++ = ',';
79 }
80 *(out - 1) = '#';
81 DCHECK_EQ(out, begin + new_size);
82 }
83 return name;
84 }
85
86 // Appends new_metadata to the metadata part of name.
AppendMetadata(std::string * name,absl::string_view new_metadata)87 TF_ATTRIBUTE_ALWAYS_INLINE inline void AppendMetadata(
88 std::string* name, absl::string_view new_metadata) {
89 if (!TF_PREDICT_FALSE(new_metadata.empty())) {
90 if (!name->empty() && name->back() == '#') { // name already has metadata
91 name->back() = ',';
92 if (TF_PREDICT_TRUE(new_metadata.front() == '#')) {
93 new_metadata.remove_prefix(1);
94 }
95 }
96 name->append(new_metadata.data(), new_metadata.size());
97 }
98 }
99
100 } // namespace traceme_internal
101
102 // Encodes an event name and arguments into TraceMe metadata.
103 // Use within a lambda to avoid expensive operations when tracing is disabled.
104 // Example Usage:
105 // TraceMe trace_me([value1]() {
106 // return TraceMeEncode("my_trace", {{"key1", value1}, {"key2", 42}});
107 // });
TraceMeEncode(std::string name,std::initializer_list<TraceMeArg> args)108 TF_ATTRIBUTE_ALWAYS_INLINE inline std::string TraceMeEncode(
109 std::string name, std::initializer_list<TraceMeArg> args) {
110 return traceme_internal::AppendArgs(std::move(name), args);
111 }
TraceMeEncode(absl::string_view name,std::initializer_list<TraceMeArg> args)112 TF_ATTRIBUTE_ALWAYS_INLINE inline std::string TraceMeEncode(
113 absl::string_view name, std::initializer_list<TraceMeArg> args) {
114 return traceme_internal::AppendArgs(std::string(name), args);
115 }
TraceMeEncode(const char * name,std::initializer_list<TraceMeArg> args)116 TF_ATTRIBUTE_ALWAYS_INLINE inline std::string TraceMeEncode(
117 const char* name, std::initializer_list<TraceMeArg> args) {
118 return traceme_internal::AppendArgs(std::string(name), args);
119 }
120
121 // Encodes arguments into TraceMe metadata.
122 // Use within a lambda to avoid expensive operations when tracing is disabled.
123 // Example Usage:
124 // TraceMe trace_me("my_trace");
125 // ...
126 // trace_me.AppendMetadata([value1]() {
127 // return TraceMeEncode({{"key1", value1}, {"key2", 42}});
128 // });
TraceMeEncode(std::initializer_list<TraceMeArg> args)129 TF_ATTRIBUTE_ALWAYS_INLINE inline std::string TraceMeEncode(
130 std::initializer_list<TraceMeArg> args) {
131 return traceme_internal::AppendArgs(std::string(), args);
132 }
133
134 // Concatenates op_name and op_type.
TraceMeOp(absl::string_view op_name,absl::string_view op_type)135 TF_ATTRIBUTE_ALWAYS_INLINE inline std::string TraceMeOp(
136 absl::string_view op_name, absl::string_view op_type) {
137 return absl::StrCat(op_name, ":", op_type);
138 }
139
TraceMeOp(const char * op_name,const char * op_type)140 TF_ATTRIBUTE_ALWAYS_INLINE inline std::string TraceMeOp(const char* op_name,
141 const char* op_type) {
142 return absl::StrCat(op_name, ":", op_type);
143 }
144
TraceMeOp(std::string && op_name,absl::string_view op_type)145 TF_ATTRIBUTE_ALWAYS_INLINE inline std::string TraceMeOp(
146 std::string&& op_name, absl::string_view op_type) {
147 absl::StrAppend(&op_name, ":", op_type);
148 return op_name;
149 }
150
151 // Concatenates op_name and op_type.
TraceMeOpOverride(absl::string_view op_name,absl::string_view op_type)152 TF_ATTRIBUTE_ALWAYS_INLINE inline std::string TraceMeOpOverride(
153 absl::string_view op_name, absl::string_view op_type) {
154 return absl::StrCat("#tf_op=", op_name, ":", op_type, "#");
155 }
156
TraceMeOpOverride(const char * op_name,const char * op_type)157 TF_ATTRIBUTE_ALWAYS_INLINE inline std::string TraceMeOpOverride(
158 const char* op_name, const char* op_type) {
159 return absl::StrCat("#tf_op=", op_name, ":", op_type, "#");
160 }
161
162 } // namespace profiler
163 } // namespace tensorflow
164
165 #endif // TENSORFLOW_CORE_PROFILER_LIB_TRACEME_ENCODE_H_
166