UNPKG

6.47 kBJavaScriptView Raw
1/**
2 * Copyright (c) Facebook, Inc. and its affiliates.
3 *
4 * This source code is licensed under the MIT license found in the
5 * LICENSE file in the root directory of this source tree.
6 *
7 *
8 * @format
9 */
10'use strict';
11
12var _asyncToGenerator = require("@babel/runtime/helpers/asyncToGenerator");
13
14var enabled = false;
15var traces = [{
16 ph: 'M',
17 pid: 0,
18 tid: 0,
19 name: 'process_name',
20 args: {
21 name: 'relay-compiler'
22 }
23}, {
24 ph: 'M',
25 pid: 0,
26 tid: 0,
27 name: 'thread_name',
28 args: {
29 name: 'relay-compiler'
30 }
31}];
32var stack = [];
33
34function enable() {
35 enabled = true;
36}
37
38function getTraces() {
39 return traces;
40}
41/**
42 * Run the provided function as part of a stack profile.
43 */
44
45
46function run(name, fn) {
47 return instrument(fn, name)();
48}
49/**
50 * Run the provided async function as part context in a stack profile.
51 * See instrumentAsyncContext() for limitations and usage notes.
52 */
53
54
55function asyncContext(name, fn) {
56 return instrumentAsyncContext(fn, name)();
57}
58/**
59 * Wait for the provided async operation as an async profile.
60 */
61
62
63function waitFor(name, fn) {
64 return instrumentWait(fn, name)();
65}
66/**
67 * Return a new instrumented sync function to be part of a stack profile.
68 *
69 * This instruments synchronous functions to be displayed in a stack
70 * visualization. To instrument async functions, see instrumentAsyncContext()
71 * and instrumentWait().
72 */
73
74
75function instrument(fn, name) {
76 if (!enabled) {
77 return fn;
78 }
79
80 var profileName = name || fn.displayName || fn.name;
81
82 var instrumented = function instrumented() {
83 var traceId = start(profileName);
84
85 try {
86 return fn.apply(this, arguments);
87 } finally {
88 end(traceId);
89 }
90 };
91
92 instrumented.displayName = profileName;
93 return instrumented;
94}
95/**
96 * Return a new instrumented async function which provides context for a stack.
97 *
98 * Because the resulting profiling information will be incorporated into a
99 * stack visualization, the instrumented function must represent a distinct
100 * region of time which does not overlap with any other async context.
101 *
102 * In other words, functions instrumented with instrumentAsyncContext must not
103 * run in parallel via Promise.all().
104 *
105 * To instrument functions which will run in parallel, use instrumentWait().
106 */
107
108
109function instrumentAsyncContext(fn, name) {
110 if (!enabled) {
111 return fn;
112 }
113
114 var profileName = name || fn.displayName || fn.name;
115
116 var instrumented =
117 /*#__PURE__*/
118 function () {
119 var _instrumented = _asyncToGenerator(function* () {
120 var traceId = start(profileName);
121
122 try {
123 return yield fn.apply(this, arguments);
124 } finally {
125 end(traceId);
126 }
127 });
128
129 return function instrumented() {
130 return _instrumented.apply(this, arguments);
131 };
132 }();
133
134 instrumented.displayName = profileName;
135 return instrumented;
136}
137/**
138 * Return a new instrumented function which performs an awaited async operation.
139 *
140 * The instrumented function is not included in the overall run time of the
141 * compiler, instead it captures the time waiting on some asynchronous external
142 * resource such as network or filesystem which are often run in parallel.
143 */
144
145
146function instrumentWait(fn, name) {
147 if (!enabled) {
148 return fn;
149 }
150
151 var profileName = name || fn.displayName || fn.name;
152
153 var instrumented =
154 /*#__PURE__*/
155 function () {
156 var _instrumented2 = _asyncToGenerator(function* () {
157 var traceId = startWait(profileName);
158
159 try {
160 return yield fn.apply(this, arguments);
161 } finally {
162 end(traceId);
163 }
164 });
165
166 return function instrumented() {
167 return _instrumented2.apply(this, arguments);
168 };
169 }();
170
171 instrumented.displayName = profileName;
172 return instrumented;
173}
174
175var T_ZERO = process.hrtime(); // Return a Uint32 of microtime duration since program start.
176
177function microtime() {
178 var hrtime = process.hrtime(T_ZERO); // eslint-disable-next-line no-bitwise
179
180 return 0 | hrtime[0] * 1e6 + Math.round(hrtime[1] / 1e3);
181}
182/**
183 * Start a stack profile with a particular name, returns an ID to pass to end().
184 *
185 * Other profiles may start before this one ends, which will be represented as
186 * nested operations, however all nested operations must end before this ends.
187 *
188 * In particular, be careful to end after errors.
189 */
190
191
192function start(name) {
193 var beginTrace = {
194 ph: 'B',
195 name: name,
196 pid: 0,
197 tid: 0,
198 ts: microtime()
199 };
200 traces.push(beginTrace);
201 stack.push(beginTrace);
202 return traces.length - 1;
203}
204
205var asyncID = 0;
206/**
207 * Start an async wait profile with a particular name, returns an ID to pass
208 * to end().
209 *
210 * Other profiles may start before this one ends, which will be represented as
211 * nested operations, however all nested operations must end before this ends.
212 *
213 * In particular, be careful to end after errors.
214 */
215
216function startWait(name) {
217 traces.push({
218 ph: 'b',
219 name: name,
220 cat: 'wait',
221 id: asyncID++,
222 pid: 0,
223 tid: 0,
224 ts: microtime()
225 });
226 return traces.length - 1;
227}
228
229function end(traceIdx) {
230 var trace = traces[traceIdx];
231
232 if (trace.ph === 'b') {
233 traces.push({
234 ph: 'e',
235 cat: trace.cat,
236 name: trace.name,
237 id: trace.id,
238 pid: trace.pid,
239 tid: trace.tid,
240 ts: microtime()
241 });
242 return;
243 }
244
245 !(trace.ph === 'B') ? process.env.NODE_ENV !== "production" ? require("fbjs/lib/invariant")(false, 'Begin trace phase') : require("fbjs/lib/invariant")(false) : void 0;
246 !(stack.pop() === trace) ? process.env.NODE_ENV !== "production" ? require("fbjs/lib/invariant")(false, 'GraphQLCompilerProfiler: The profile trace %s ended before nested traces. ' + 'If it is async, try using Profile.waitFor or Profile.profileWait.', trace.name) : require("fbjs/lib/invariant")(false) : void 0;
247 var prevTrace = traces[traces.length - 1];
248
249 if (trace === prevTrace) {
250 traces[traceIdx] = {
251 ph: 'X',
252 name: trace.name,
253 pid: trace.pid,
254 tid: trace.tid,
255 ts: trace.ts,
256 dur: microtime() - trace.ts
257 };
258 return;
259 }
260
261 traces.push({
262 ph: 'E',
263 name: trace.name,
264 pid: trace.pid,
265 tid: trace.tid,
266 ts: microtime()
267 });
268}
269
270module.exports = {
271 enable: enable,
272 getTraces: getTraces,
273 run: run,
274 asyncContext: asyncContext,
275 waitFor: waitFor,
276 instrument: instrument,
277 instrumentAsyncContext: instrumentAsyncContext,
278 instrumentWait: instrumentWait,
279 start: start,
280 startWait: startWait,
281 end: end
282};
\No newline at end of file