• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Copyright 2018 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_INTERNAL_TRACEME_RECORDER_H_
16 #define TENSORFLOW_CORE_PROFILER_INTERNAL_TRACEME_RECORDER_H_
17 
18 #include <atomic>
19 #include <vector>
20 #include "absl/base/optimization.h"
21 #include "tensorflow/core/platform/types.h"
22 
23 namespace tensorflow {
24 namespace profiler {
25 
26 namespace internal {
27 extern std::atomic<int> g_trace_level;
28 }  // namespace internal
29 
30 // TraceMeRecorder is a singleton repository of TraceMe events.
31 // It can be safely and cheaply appended to by multiple threads.
32 //
33 // Start() and Stop() must be called in pairs, Stop() returns the events added
34 // since the previous Start().
35 //
36 // This is the backend for TraceMe instrumentation.
37 // The profiler starts the recorder, the TraceMe constructor records begin
38 // events, and the destructor records end events.
39 // The profiler then stops the recorder and finds start/end pairs. (Unpaired
40 // start/end events are discarded at that point).
41 class TraceMeRecorder {
42  public:
43   // An Event is either the start of a TraceMe, the end of a TraceMe, or both.
44   // Times are in ns since the Unix epoch.
45   struct Event {
46     uint64 activity_id;
47     string name;
48     uint64 start_time;  // 0 = missing
49     uint64 end_time;    // 0 = missing
50   };
51   struct ThreadInfo {
52     int64 tid;
53     string name;
54   };
55   struct ThreadEvents {
56     const ThreadInfo thread;
57     std::vector<Event> events;
58   };
59   using Events = std::vector<ThreadEvents>;
60 
61   // Starts recording of TraceMe().
62   // Only traces <= level will be recorded.
63   // Level must be >= 0.
64   // If level is 0, no traces will be recorded.
65   static bool Start(int level);
66 
67   // Stops recording and returns events recorded since Start().
68   static Events Stop();
69 
70   // Returns events recorded till now without stopping the recording. Empty
71   // container is returned if the recorder was already stopped.
72   static Events Collect();
73 
74   // Returns whether we're currently recording. Racy, but cheap!
75   static inline bool Active(int level = 1) {
76     return ABSL_PREDICT_FALSE(
77         internal::g_trace_level.load(std::memory_order_acquire) >= level);
78   }
79 
80   static void Record(Event);
81 
82  private:
83   // No copy and assignment
84   TraceMeRecorder(const TraceMeRecorder&) = delete;
85   TraceMeRecorder& operator=(const TraceMeRecorder&) = delete;
86 
87   // Implementation of g_trace_level must be lock-free for faster execution
88   // of the TraceMe() public API. This can be commented (if compilation is
89   // failing) but execution might be slow (even when host tracing is disabled).
90   static_assert(ATOMIC_INT_LOCK_FREE == 2, "Assumed atomic<int> was lock free");
91 };
92 
93 }  // namespace profiler
94 }  // namespace tensorflow
95 #endif  // TENSORFLOW_CORE_PROFILER_INTERNAL_TRACEME_RECORDER_H_
96