| 1 | /** |
| 2 | * Copyright (c) Meta Platforms, Inc. and 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 | * @flow strict-local |
| 8 | */ |
| 9 | |
| 10 | import {__PERFORMANCE_PROFILE__} from './constants'; |
| 11 | |
| 12 | const supportsUserTiming = |
| 13 | typeof performance !== 'undefined' && |
| 14 | // $FlowFixMe[method-unbinding] |
| 15 | typeof performance.mark === 'function' && |
| 16 | // $FlowFixMe[method-unbinding] |
| 17 | typeof performance.clearMarks === 'function'; |
| 18 | |
| 19 | const supportsPerformanceNow = |
| 20 | // $FlowFixMe[method-unbinding] |
| 21 | typeof performance !== 'undefined' && typeof performance.now === 'function'; |
| 22 | |
| 23 | function mark(markName: string): void { |
| 24 | if (supportsUserTiming) { |
| 25 | performance.mark(markName + '-start'); |
| 26 | } |
| 27 | } |
| 28 | |
| 29 | function measure(markName: string): void { |
| 30 | if (supportsUserTiming) { |
| 31 | performance.mark(markName + '-end'); |
| 32 | performance.measure(markName, markName + '-start', markName + '-end'); |
| 33 | performance.clearMarks(markName + '-start'); |
| 34 | performance.clearMarks(markName + '-end'); |
| 35 | } |
| 36 | } |
| 37 | |
| 38 | function now(): number { |
| 39 | if (supportsPerformanceNow) { |
| 40 | return performance.now(); |
| 41 | } |
| 42 | return Date.now(); |
| 43 | } |
| 44 | |
| 45 | export async function withAsyncPerfMeasurements<TReturn>( |
| 46 | markName: string, |
| 47 | callback: () => Promise<TReturn>, |
| 48 | onComplete?: number => void, |
| 49 | ): Promise<TReturn> { |
| 50 | const start = now(); |
| 51 | // $FlowFixMe[constant-condition] |
| 52 | if (__PERFORMANCE_PROFILE__) { |
| 53 | mark(markName); |
| 54 | } |
| 55 | const result = await callback(); |
| 56 | |
| 57 | // $FlowFixMe[constant-condition] |
| 58 | if (__PERFORMANCE_PROFILE__) { |
| 59 | measure(markName); |
| 60 | } |
| 61 | |
| 62 | if (onComplete != null) { |
| 63 | const duration = now() - start; |
| 64 | onComplete(duration); |
| 65 | } |
| 66 | |
| 67 | return result; |
| 68 | } |
| 69 | |
| 70 | export function withSyncPerfMeasurements<TReturn>( |
| 71 | markName: string, |
| 72 | callback: () => TReturn, |
| 73 | onComplete?: number => void, |
| 74 | ): TReturn { |
| 75 | const start = now(); |
| 76 | // $FlowFixMe[constant-condition] |
| 77 | if (__PERFORMANCE_PROFILE__) { |
| 78 | mark(markName); |
| 79 | } |
| 80 | const result = callback(); |
| 81 | |
| 82 | // $FlowFixMe[constant-condition] |
| 83 | if (__PERFORMANCE_PROFILE__) { |
| 84 | measure(markName); |
| 85 | } |
| 86 | |
| 87 | if (onComplete != null) { |
| 88 | const duration = now() - start; |
| 89 | onComplete(duration); |
| 90 | } |
| 91 | |
| 92 | return result; |
| 93 | } |
| 94 | |
| 95 | export function withCallbackPerfMeasurements<TReturn>( |
| 96 | markName: string, |
| 97 | callback: (done: () => void) => TReturn, |
| 98 | onComplete?: number => void, |
| 99 | ): TReturn { |
| 100 | const start = now(); |
| 101 | // $FlowFixMe[constant-condition] |
| 102 | if (__PERFORMANCE_PROFILE__) { |
| 103 | mark(markName); |
| 104 | } |
| 105 | |
| 106 | const done = () => { |
| 107 | // $FlowFixMe[constant-condition] |
| 108 | if (__PERFORMANCE_PROFILE__) { |
| 109 | measure(markName); |
| 110 | } |
| 111 | |
| 112 | if (onComplete != null) { |
| 113 | const duration = now() - start; |
| 114 | onComplete(duration); |
| 115 | } |
| 116 | }; |
| 117 | return callback(done); |
| 118 | } |