timemory  3.2.1
Modular C++ Toolkit for Performance Analysis and Logging. Profiling API and Tools for C, C++, CUDA, Fortran, and Python. The C++ template API is essentially a framework to creating tools: it is designed to provide a unifying interface for recording various performance measurements alongside data logging and interfaces to other tools.
macros.hpp
Go to the documentation of this file.
1 // MIT License
2 //
3 // Copyright (c) 2020, The Regents of the University of California,
4 // through Lawrence Berkeley National Laboratory (subject to receipt of any
5 // required approvals from the U.S. Dept. of Energy). All rights reserved.
6 //
7 // Permission is hereby granted, free of charge, to any person obtaining a copy
8 // of this software and associated documentation files (the "Software"), to
9 // deal in the Software without restriction, including without limitation the
10 // rights to use, copy, modify, merge, publish, distribute, sublicense, and
11 // copies of the Software, and to permit persons to whom the Software is
12 // furnished to do so, subject to the following conditions:
13 //
14 // The above copyright notice and this permission notice shall be included in
15 // all copies or substantial portions of the Software.
16 //
17 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
23 // IN THE SOFTWARE.
24 //
25 
26 #pragma once
27 
29 
30 #include <cstdint>
31 #include <cstdio>
32 #include <iosfwd>
33 #include <string>
34 #include <utility>
35 
36 #if defined(TIMEMORY_CORE_SOURCE)
37 # define TIMEMORY_UTILITY_SOURCE
38 #elif defined(TIMEMORY_USE_CORE_EXTERN)
39 # define TIMEMORY_USE_UTILITY_EXTERN
40 #endif
41 //
42 #if defined(TIMEMORY_USE_EXTERN) && !defined(TIMEMORY_USE_UTILITY_EXTERN)
43 # define TIMEMORY_USE_UTILITY_EXTERN
44 #endif
45 
46 //======================================================================================//
47 //
48 // Quick way to create a globally accessible setting
49 //
50 //======================================================================================//
51 
52 #if !defined(CREATE_STATIC_VARIABLE_ACCESSOR)
53 # define CREATE_STATIC_VARIABLE_ACCESSOR(TYPE, FUNC_NAME, VARIABLE) \
54  static TYPE& FUNC_NAME() \
55  { \
56  static TYPE _instance = Type::VARIABLE; \
57  return _instance; \
58  }
59 #endif
60 
61 //--------------------------------------------------------------------------------------//
62 
63 #if !defined(CREATE_STATIC_FUNCTION_ACCESSOR)
64 # define CREATE_STATIC_FUNCTION_ACCESSOR(TYPE, FUNC_NAME, VARIABLE) \
65  static TYPE& FUNC_NAME() \
66  { \
67  static TYPE _instance = Type::VARIABLE(); \
68  return _instance; \
69  }
70 #endif
71 
72 //======================================================================================//
73 //
74 // DEBUG
75 //
76 //======================================================================================//
77 
78 // stringify some macro -- uses TIMEMORY_STRINGIZE2 which does the actual
79 // "stringify-ing" after the macro has been substituted by it's result
80 #if !defined(TIMEMORY_STRINGIZE)
81 # define TIMEMORY_STRINGIZE(X) TIMEMORY_STRINGIZE2(X)
82 #endif
83 
84 // actual stringifying
85 #if !defined(TIMEMORY_STRINGIZE2)
86 # define TIMEMORY_STRINGIZE2(X) # X
87 #endif
88 
89 #if !defined(TIMEMORY_TRUNCATED_FILE_STRING)
90 # define TIMEMORY_TRUNCATED_FILE_STRING(FILE) \
91  []() { \
92  std::string _f{ FILE }; \
93  auto _pos = _f.find("/timemory/"); \
94  if(_pos != std::string::npos) \
95  { \
96  return _f.substr(_pos + 1); \
97  } \
98  return _f; \
99  }()
100 #endif
101 
102 #if !defined(TIMEMORY_FILE_LINE_FUNC_STRING)
103 # define TIMEMORY_FILE_LINE_FUNC_STRING \
104  std::string \
105  { \
106  std::string{ "[" } + TIMEMORY_TRUNCATED_FILE_STRING(__FILE__) + ":" + \
107  std::to_string(__LINE__) + "@'" + __FUNCTION__ + "']" \
108  }
109 #endif
110 
111 #if !defined(TIMEMORY_PID_TID_STRING)
112 # define TIMEMORY_PID_TID_STRING \
113  std::string \
114  { \
115  std::string{ "[pid=" } + std::to_string(::tim::process::get_id()) + \
116  std::string{ "][tid=" } + std::to_string(::tim::threading::get_id()) + \
117  "]" \
118  }
119 #endif
120 
121 template <typename Arg>
122 TIMEMORY_NOINLINE auto
123 timemory_proxy_value(Arg&& arg, int) -> decltype(arg.proxy_value())
124 {
125  return arg.proxy_value();
126 }
127 
128 template <typename Arg>
129 TIMEMORY_NOINLINE auto
130 timemory_proxy_value(Arg&& arg, long)
131 {
132  return std::forward<Arg>(arg);
133 }
134 
135 template <typename... Args>
136 TIMEMORY_NOINLINE void
137 timemory_print_here(const char* _pid_tid, const char* _file, int _line, const char* _func,
138  Args&&... args)
139 {
140  fprintf(stderr, "%s[%s:%i@'%s']> ", _pid_tid, _file, _line, _func);
141  fprintf(stderr, timemory_proxy_value(std::forward<Args>(args), 0)...);
142  fprintf(stderr, "...\n");
143  fflush(stderr);
144 }
145 
146 #if !defined(PRINT_HERE)
147 # define PRINT_HERE(...) \
148  timemory_print_here(TIMEMORY_PID_TID_STRING.c_str(), \
149  TIMEMORY_TRUNCATED_FILE_STRING(__FILE__).c_str(), __LINE__, \
150  __FUNCTION__, __VA_ARGS__)
151 #endif
152 
153 #if !defined(DEBUG_PRINT_HERE)
154 # if defined(DEBUG)
155 # define DEBUG_PRINT_HERE(...) \
156  if(::tim::settings::debug()) \
157  { \
158  timemory_print_here(TIMEMORY_PID_TID_STRING.c_str(), \
159  TIMEMORY_TRUNCATED_FILE_STRING(__FILE__).c_str(), \
160  __LINE__, __FUNCTION__, __VA_ARGS__); \
161  }
162 # else
163 # define DEBUG_PRINT_HERE(...)
164 # endif
165 #endif
166 
167 #if !defined(VERBOSE_PRINT_HERE)
168 # define VERBOSE_PRINT_HERE(VERBOSE_LEVEL, ...) \
169  if(::tim::settings::verbose() >= VERBOSE_LEVEL) \
170  { \
171  timemory_print_here(TIMEMORY_PID_TID_STRING.c_str(), \
172  TIMEMORY_TRUNCATED_FILE_STRING(__FILE__).c_str(), \
173  __LINE__, __FUNCTION__, __VA_ARGS__); \
174  }
175 #endif
176 
177 #if !defined(CONDITIONAL_PRINT_HERE)
178 # define CONDITIONAL_PRINT_HERE(CONDITION, ...) \
179  if(CONDITION) \
180  { \
181  timemory_print_here(TIMEMORY_PID_TID_STRING.c_str(), \
182  TIMEMORY_TRUNCATED_FILE_STRING(__FILE__).c_str(), \
183  __LINE__, __FUNCTION__, __VA_ARGS__); \
184  }
185 #endif
186 
187 #if !defined(TIMEMORY_CONDITIONAL_BACKTRACE)
188 # define TIMEMORY_CONDITIONAL_BACKTRACE(CONDITION, DEPTH) \
189  if(CONDITION) \
190  { \
191  ::tim::print_backtrace<DEPTH>(std::cerr, TIMEMORY_PID_TID_STRING, \
192  TIMEMORY_FILE_LINE_FUNC_STRING); \
193  }
194 #endif
195 
196 #if !defined(TIMEMORY_CONDITIONAL_DEMANGLED_BACKTRACE)
197 # define TIMEMORY_CONDITIONAL_DEMANGLED_BACKTRACE(CONDITION, DEPTH) \
198  if(CONDITION) \
199  { \
200  ::tim::print_demangled_backtrace<DEPTH>(std::cerr, TIMEMORY_PID_TID_STRING, \
201  TIMEMORY_FILE_LINE_FUNC_STRING); \
202  }
203 #endif
204 
205 #if !defined(PRETTY_PRINT_HERE)
206 # if defined(_TIMEMORY_GNU) || defined(_TIMEMORY_CLANG)
207 # define PRETTY_PRINT_HERE(...) \
208  timemory_print_here(TIMEMORY_PID_TID_STRING.c_str(), \
209  TIMEMORY_TRUNCATED_FILE_STRING(__FILE__).c_str(), \
210  __LINE__, __PRETTY_FUNCTION__, __VA_ARGS__)
211 # else
212 # define PRETTY_PRINT_HERE(...) \
213  timemory_print_here(TIMEMORY_PID_TID_STRING.c_str(), \
214  TIMEMORY_TRUNCATED_FILE_STRING(__FILE__).c_str(), \
215  __LINE__, __FUNCTION__, __VA_ARGS__)
216 # endif
217 #endif
218 
219 #if !defined(TIMEMORY_CONDITIONAL_BACKTRACE)
220 # define TIMEMORY_CONDITIONAL_BACKTRACE(CONDITION, DEPTH) \
221  if(CONDITION) \
222  { \
223  ::tim::print_backtrace<DEPTH>(std::cerr, TIMEMORY_PID_TID_STRING); \
224  }
225 #endif
226 
227 #if !defined(TIMEMORY_CONDITIONAL_DEMANGLED_BACKTRACE)
228 # define TIMEMORY_CONDITIONAL_DEMANGLED_BACKTRACE(CONDITION, DEPTH) \
229  if(CONDITION) \
230  { \
231  ::tim::print_demangled_backtrace<DEPTH>(std::cerr, TIMEMORY_PID_TID_STRING); \
232  }
233 #endif
234 
235 #if defined(DEBUG)
236 
237 template <typename... Args>
238 inline void
239 __LOG(std::string file, int line, const char* msg, Args&&... args)
240 {
241  auto _pos = file.find("/timemory/");
242  if(_pos == std::string::npos)
243  _pos = file.find_last_of('/');
244  if(_pos != std::string::npos)
245  file = file.substr(_pos);
246  fprintf(stderr, "[Log @ %s:%i]> ", file.c_str(), line);
247  fprintf(stderr, msg, std::forward<Args>(args)...);
248  fprintf(stderr, "\n");
249 }
250 
251 //--------------------------------------------------------------------------------------//
252 
253 inline void
254 __LOG(std::string file, int line, const char* msg)
255 {
256  if(file.find('/') != std::string::npos)
257  file = file.substr(file.find_last_of('/'));
258  fprintf(stderr, "[Log @ %s:%i]> %s\n", file.c_str(), line, msg);
259 }
260 
261 //--------------------------------------------------------------------------------------//
262 // auto insert the file and line
263 # define _LOG(...) __LOG(__FILE__, __LINE__, __VA_ARGS__)
264 
265 //--------------------------------------------------------------------------------------//
266 
267 template <typename... Args>
268 inline void
269 _DBG(const char* msg, Args&&... args)
270 {
271  fprintf(stderr, msg, std::forward<Args>(args)...);
272 }
273 
274 //--------------------------------------------------------------------------------------//
275 
276 inline void
277 _DBG(const char* msg)
278 {
279  fprintf(stderr, "%s", msg);
280 }
281 
282 #else
283 # define _LOG(...) \
284  {}
285 # define _DBG(...) \
286  {}
287 #endif
288 
289 //======================================================================================//
290 //
291 // Define macros for utility
292 //
293 //======================================================================================//
294 //
295 #if defined(TIMEMORY_UTILITY_SOURCE)
296 # define TIMEMORY_UTILITY_LINKAGE(...) __VA_ARGS__
297 # define TIMEMORY_UTILITY_INLINE
298 #elif defined(TIMEMORY_USE_EXTERN) || defined(TIMEMORY_USE_UTILITY_EXTERN)
299 # define TIMEMORY_UTILITY_LINKAGE(...) __VA_ARGS__
300 # define TIMEMORY_UTILITY_INLINE
301 #else
302 # define TIMEMORY_UTILITY_LINKAGE(...) inline __VA_ARGS__
303 # define TIMEMORY_UTILITY_INLINE inline
304 # define TIMEMORY_UTILITY_HEADER_MODE
305 #endif
const auto & _file
Definition: definition.hpp:72
tim::mpl::apply< std::string > string
Definition: macros.hpp:52
auto timemory_proxy_value(Arg &&arg, int) -> decltype(arg.proxy_value())
Definition: macros.hpp:123
#define _DBG(...)
Definition: macros.hpp:285
void timemory_print_here(const char *_pid_tid, const char *_file, int _line, const char *_func, Args &&... args)
Definition: macros.hpp:137