summaryrefslogtreecommitdiffstats
path: root/mozglue/baseprofiler/public/BaseProfilerLabels.h
blob: 8da596e3abf603ce9bf0c53c2c33624f79174f79 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

// This header contains all definitions related to Base Profiler labels (outside
// of XUL).
// It is safe to include unconditionally, and only defines empty macros if
// MOZ_GECKO_PROFILER is not set.

#ifndef BaseProfilerLabels_h
#define BaseProfilerLabels_h

#ifndef MOZ_GECKO_PROFILER

#  define AUTO_BASE_PROFILER_LABEL(label, categoryPair)
#  define AUTO_BASE_PROFILER_LABEL_CATEGORY_PAIR(categoryPair)
#  define AUTO_BASE_PROFILER_LABEL_DYNAMIC_CSTR(label, categoryPair, cStr)
#  define AUTO_BASE_PROFILER_LABEL_DYNAMIC_STRING(label, categoryPair, str)
#  define AUTO_BASE_PROFILER_LABEL_FAST(label, categoryPair, ctx)
#  define AUTO_BASE_PROFILER_LABEL_DYNAMIC_FAST(label, dynamicString, \
                                                categoryPair, ctx, flags)

#else  // !MOZ_GECKO_PROFILER

#  include "BaseProfilingStack.h"

#  include "mozilla/Attributes.h"
#  include "mozilla/Maybe.h"
#  include "mozilla/BaseProfilerRAIIMacro.h"
#  include "mozilla/BaseProfilerState.h"
#  include "mozilla/ThreadLocal.h"

#  include <stdint.h>
#  include <string>

namespace mozilla::baseprofiler {

// Insert an RAII object in this scope to enter a label stack frame. Any
// samples collected in this scope will contain this label in their stack.
// The label argument must be a static C string. It is usually of the
// form "ClassName::FunctionName". (Ideally we'd use the compiler to provide
// that for us, but __func__ gives us the function name without the class
// name.) If the label applies to only part of a function, you can qualify it
// like this: "ClassName::FunctionName:PartName".
//
// Use AUTO_BASE_PROFILER_LABEL_DYNAMIC_* if you want to add additional /
// dynamic information to the label stack frame.
#  define AUTO_BASE_PROFILER_LABEL(label, categoryPair)       \
    ::mozilla::baseprofiler::AutoProfilerLabel PROFILER_RAII( \
        label, nullptr,                                       \
        ::mozilla::baseprofiler::ProfilingCategoryPair::categoryPair)

// Similar to AUTO_BASE_PROFILER_LABEL, but with only one argument: the category
// pair. The label string is taken from the category pair. This is convenient
// for labels like
// AUTO_BASE_PROFILER_LABEL_CATEGORY_PAIR(GRAPHICS_LayerBuilding) which would
// otherwise just repeat the string.
#  define AUTO_BASE_PROFILER_LABEL_CATEGORY_PAIR(categoryPair)         \
    ::mozilla::baseprofiler::AutoProfilerLabel PROFILER_RAII(          \
        "", nullptr,                                                   \
        ::mozilla::baseprofiler::ProfilingCategoryPair::categoryPair,  \
        uint32_t(::mozilla::baseprofiler::ProfilingStackFrame::Flags:: \
                     LABEL_DETERMINED_BY_CATEGORY_PAIR))

// Similar to AUTO_BASE_PROFILER_LABEL, but with an additional string. The
// inserted RAII object stores the cStr pointer in a field; it does not copy the
// string.
//
// WARNING: This means that the string you pass to this macro needs to live at
// least until the end of the current scope. Be careful using this macro with
// ns[C]String; the other AUTO_BASE_PROFILER_LABEL_DYNAMIC_* macros below are
// preferred because they avoid this problem.
//
// If the profiler samples the current thread and walks the label stack while
// this RAII object is on the stack, it will copy the supplied string into the
// profile buffer. So there's one string copy operation, and it happens at
// sample time.
//
// Compare this to the plain AUTO_BASE_PROFILER_LABEL macro, which only accepts
// literal strings: When the label stack frames generated by
// AUTO_BASE_PROFILER_LABEL are sampled, no string copy needs to be made because
// the profile buffer can just store the raw pointers to the literal strings.
// Consequently, AUTO_BASE_PROFILER_LABEL frames take up considerably less space
// in the profile buffer than AUTO_BASE_PROFILER_LABEL_DYNAMIC_* frames.
#  define AUTO_BASE_PROFILER_LABEL_DYNAMIC_CSTR(label, categoryPair, cStr) \
    ::mozilla::baseprofiler::AutoProfilerLabel PROFILER_RAII(              \
        label, cStr,                                                       \
        ::mozilla::baseprofiler::ProfilingCategoryPair::categoryPair)

// Similar to AUTO_BASE_PROFILER_LABEL_DYNAMIC_CSTR, but takes an std::string.
//
// Note: The use of the Maybe<>s ensures the scopes for the dynamic string and
// the AutoProfilerLabel are appropriate, while also not incurring the runtime
// cost of the string assignment unless the profiler is active. Therefore,
// unlike AUTO_BASE_PROFILER_LABEL and AUTO_BASE_PROFILER_LABEL_DYNAMIC_CSTR,
// this macro doesn't push/pop a label when the profiler is inactive.
#  define AUTO_BASE_PROFILER_LABEL_DYNAMIC_STRING(label, categoryPair, str) \
    Maybe<std::string> autoStr;                                             \
    Maybe<::mozilla::baseprofiler::AutoProfilerLabel> raiiObjectString;     \
    if (::mozilla::baseprofiler::profiler_is_active()) {                    \
      autoStr.emplace(str);                                                 \
      raiiObjectString.emplace(                                             \
          label, autoStr->c_str(),                                          \
          ::mozilla::baseprofiler::ProfilingCategoryPair::categoryPair);    \
    }

// Similar to AUTO_BASE_PROFILER_LABEL, but accepting a JSContext* parameter,
// and a no-op if the profiler is disabled. Used to annotate functions for which
// overhead in the range of nanoseconds is noticeable. It avoids overhead from
// the TLS lookup because it can get the ProfilingStack from the JS context, and
// avoids almost all overhead in the case where the profiler is disabled.
#  define AUTO_BASE_PROFILER_LABEL_FAST(label, categoryPair, ctx) \
    ::mozilla::baseprofiler::AutoProfilerLabel PROFILER_RAII(     \
        ctx, label, nullptr,                                      \
        ::mozilla::baseprofiler::ProfilingCategoryPair::categoryPair)

// Similar to AUTO_BASE_PROFILER_LABEL_FAST, but also takes an extra string and
// an additional set of flags. The flags parameter should carry values from the
// ProfilingStackFrame::Flags enum.
#  define AUTO_BASE_PROFILER_LABEL_DYNAMIC_FAST(label, dynamicString,     \
                                                categoryPair, ctx, flags) \
    ::mozilla::baseprofiler::AutoProfilerLabel PROFILER_RAII(             \
        ctx, label, dynamicString,                                        \
        ::mozilla::baseprofiler::ProfilingCategoryPair::categoryPair, flags)

// This class creates a non-owning ProfilingStack reference. Objects of this
// class are stack-allocated, and so exist within a thread, and are thus bounded
// by the lifetime of the thread, which ensures that the references held can't
// be used after the ProfilingStack is destroyed.
class MOZ_RAII AutoProfilerLabel {
 public:
  // This is the AUTO_BASE_PROFILER_LABEL and AUTO_BASE_PROFILER_LABEL_DYNAMIC
  // variant.
  AutoProfilerLabel(const char* aLabel, const char* aDynamicString,
                    ProfilingCategoryPair aCategoryPair, uint32_t aFlags = 0) {
    // Get the ProfilingStack from TLS.
    Push(GetProfilingStack(), aLabel, aDynamicString, aCategoryPair, aFlags);
  }

  void Push(ProfilingStack* aProfilingStack, const char* aLabel,
            const char* aDynamicString, ProfilingCategoryPair aCategoryPair,
            uint32_t aFlags = 0) {
    // This function runs both on and off the main thread.

    mProfilingStack = aProfilingStack;
    if (mProfilingStack) {
      mProfilingStack->pushLabelFrame(aLabel, aDynamicString, this,
                                      aCategoryPair, aFlags);
    }
  }

  ~AutoProfilerLabel() {
    // This function runs both on and off the main thread.

    if (mProfilingStack) {
      mProfilingStack->pop();
    }
  }

  MFBT_API static ProfilingStack* GetProfilingStack();

 private:
  // We save a ProfilingStack pointer in the ctor so we don't have to redo the
  // TLS lookup in the dtor.
  ProfilingStack* mProfilingStack;

 public:
  // See the comment on the definition in platform.cpp for details about this.
  static MOZ_THREAD_LOCAL(ProfilingStack*) sProfilingStack;
};

}  // namespace mozilla::baseprofiler

#endif  // !MOZ_GECKO_PROFILER

#endif  // BaseProfilerLabels_h