mirror of
https://github.com/angular/angular.git
synced 2026-09-14 13:54:52 +08:00
refactor(core): allow multiple profilers (#60548)
This commit changes the profiler infrastructure to allow multiple profilers running at the same time. PR Close #60548
This commit is contained in:
committed by
Alex Rickabaugh
parent
fe9b79b615
commit
64f6fc0095
@@ -8,21 +8,40 @@
|
||||
|
||||
import {type Profiler} from './profiler_types';
|
||||
|
||||
let profilerCallback: Profiler | null = null;
|
||||
const profilerCallbacks: Profiler[] = [];
|
||||
|
||||
const NOOP_PROFILER_REMOVAL = () => {};
|
||||
|
||||
function removeProfiler(profiler: Profiler) {
|
||||
const profilerIdx = profilerCallbacks.indexOf(profiler);
|
||||
if (profilerIdx !== -1) {
|
||||
profilerCallbacks.splice(profilerIdx, 1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the callback function which will be invoked before and after performing certain actions at
|
||||
* runtime (for example, before and after running change detection).
|
||||
* Adds a callback function which will be invoked before and after performing certain actions at
|
||||
* runtime (for example, before and after running change detection). Multiple profiler callbacks can be set:
|
||||
* in this case profiling events are reported to every registered callback.
|
||||
*
|
||||
* Warning: this function is *INTERNAL* and should not be relied upon in application's code.
|
||||
* The contract of the function might be changed in any release and/or the function can be removed
|
||||
* completely.
|
||||
*
|
||||
* @param profiler function provided by the caller or null value to disable profiling.
|
||||
* @param profiler function provided by the caller or null value to disable all profilers.
|
||||
* @returns a cleanup function that, when invoked, removes a given profiler callback.
|
||||
*/
|
||||
export const setProfiler = (profiler: Profiler | null) => {
|
||||
profilerCallback = profiler;
|
||||
};
|
||||
export function setProfiler(profiler: Profiler | null): () => void {
|
||||
if (profiler !== null) {
|
||||
if (!profilerCallbacks.includes(profiler)) {
|
||||
profilerCallbacks.push(profiler);
|
||||
}
|
||||
return () => removeProfiler(profiler);
|
||||
} else {
|
||||
profilerCallbacks.length = 0;
|
||||
return NOOP_PROFILER_REMOVAL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Profiler function which wraps user code executed by the runtime.
|
||||
@@ -32,10 +51,10 @@ export const setProfiler = (profiler: Profiler | null) => {
|
||||
* @param eventFn function associated with event.
|
||||
* For example a template function, lifecycle hook, or output listener.
|
||||
* The value depends on the execution context
|
||||
* @returns
|
||||
*/
|
||||
export const profiler: Profiler = function (event, instance = null, eventFn) {
|
||||
if (profilerCallback != null /* both `null` and `undefined` */) {
|
||||
export const profiler: Profiler = function (event, instance = null, eventFn): void {
|
||||
for (let i = 0; i < profilerCallbacks.length; i++) {
|
||||
const profilerCallback = profilerCallbacks[i];
|
||||
profilerCallback(event, instance, eventFn);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
* found in the LICENSE file at https://angular.dev/license
|
||||
*/
|
||||
|
||||
import {setProfiler} from '../../src/render3/profiler';
|
||||
import {setProfiler, profiler} from '../../src/render3/profiler';
|
||||
import {ProfilerEvent} from '../../src/render3/profiler_types';
|
||||
import {TestBed} from '../../testing';
|
||||
|
||||
@@ -540,3 +540,54 @@ describe('profiler', () => {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('profiler activation and removal', () => {
|
||||
it('should allow adding and removing multiple profilers', () => {
|
||||
const events: string[] = [];
|
||||
const r1 = setProfiler((e) => events.push('P1: ' + e));
|
||||
const r2 = setProfiler((e) => events.push('P2: ' + e));
|
||||
|
||||
profiler(ProfilerEvent.TemplateCreateStart);
|
||||
expect(events).toEqual(['P1: 0', 'P2: 0']);
|
||||
|
||||
r1();
|
||||
profiler(ProfilerEvent.TemplateCreateEnd);
|
||||
expect(events).toEqual(['P1: 0', 'P2: 0', 'P2: 1']);
|
||||
|
||||
r2();
|
||||
profiler(ProfilerEvent.TemplateCreateStart);
|
||||
expect(events).toEqual(['P1: 0', 'P2: 0', 'P2: 1']);
|
||||
});
|
||||
|
||||
it('should not add / remove the same profiler twice', () => {
|
||||
const events: string[] = [];
|
||||
const p1 = (e: ProfilerEvent) => events.push('P1: ' + e);
|
||||
const r1 = setProfiler(p1);
|
||||
const r2 = setProfiler(p1);
|
||||
|
||||
profiler(ProfilerEvent.TemplateCreateStart);
|
||||
expect(events).toEqual(['P1: 0']);
|
||||
|
||||
r1();
|
||||
profiler(ProfilerEvent.TemplateCreateStart);
|
||||
expect(events).toEqual(['P1: 0']);
|
||||
|
||||
// subsequent removals should be noop
|
||||
r1();
|
||||
r2();
|
||||
});
|
||||
|
||||
it('should clear all profilers when passing null', () => {
|
||||
const events: string[] = [];
|
||||
setProfiler((e) => events.push('P1: ' + e));
|
||||
setProfiler((e) => events.push('P2: ' + e));
|
||||
|
||||
profiler(ProfilerEvent.TemplateCreateStart);
|
||||
expect(events).toEqual(['P1: 0', 'P2: 0']);
|
||||
|
||||
// clear all profilers
|
||||
setProfiler(null);
|
||||
profiler(ProfilerEvent.TemplateCreateEnd);
|
||||
expect(events).toEqual(['P1: 0', 'P2: 0']);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -429,6 +429,8 @@
|
||||
"producerMarkClean",
|
||||
"producerRemoveLiveConsumerAtIndex",
|
||||
"producerUpdateValueVersion",
|
||||
"profiler",
|
||||
"profilerCallbacks",
|
||||
"refreshContentQueries",
|
||||
"refreshView",
|
||||
"rememberChangeHistoryAndInvokeOnChangesHook",
|
||||
|
||||
@@ -455,6 +455,8 @@
|
||||
"producerMarkClean",
|
||||
"producerRemoveLiveConsumerAtIndex",
|
||||
"producerUpdateValueVersion",
|
||||
"profiler",
|
||||
"profilerCallbacks",
|
||||
"refreshContentQueries",
|
||||
"refreshView",
|
||||
"rememberChangeHistoryAndInvokeOnChangesHook",
|
||||
|
||||
@@ -369,6 +369,8 @@
|
||||
"producerMarkClean",
|
||||
"producerRemoveLiveConsumerAtIndex",
|
||||
"producerUpdateValueVersion",
|
||||
"profiler",
|
||||
"profilerCallbacks",
|
||||
"refreshContentQueries",
|
||||
"refreshView",
|
||||
"rememberChangeHistoryAndInvokeOnChangesHook",
|
||||
|
||||
@@ -433,6 +433,7 @@
|
||||
"producerRemoveLiveConsumerAtIndex",
|
||||
"producerUpdateValueVersion",
|
||||
"profiler",
|
||||
"profilerCallbacks",
|
||||
"refreshContentQueries",
|
||||
"refreshView",
|
||||
"registerPostOrderHooks",
|
||||
|
||||
@@ -552,6 +552,8 @@
|
||||
"producerRemoveLiveConsumerAtIndex",
|
||||
"producerUpdateValueVersion",
|
||||
"producerUpdatesAllowed",
|
||||
"profiler",
|
||||
"profilerCallbacks",
|
||||
"providerToFactory",
|
||||
"readableStreamLikeToAsyncGenerator",
|
||||
"refreshContentQueries",
|
||||
|
||||
@@ -541,6 +541,8 @@
|
||||
"producerRemoveLiveConsumerAtIndex",
|
||||
"producerUpdateValueVersion",
|
||||
"producerUpdatesAllowed",
|
||||
"profiler",
|
||||
"profilerCallbacks",
|
||||
"providerToFactory",
|
||||
"readableStreamLikeToAsyncGenerator",
|
||||
"refreshContentQueries",
|
||||
|
||||
@@ -297,6 +297,8 @@
|
||||
"producerMarkClean",
|
||||
"producerRemoveLiveConsumerAtIndex",
|
||||
"producerUpdateValueVersion",
|
||||
"profiler",
|
||||
"profilerCallbacks",
|
||||
"refreshContentQueries",
|
||||
"refreshView",
|
||||
"rememberChangeHistoryAndInvokeOnChangesHook",
|
||||
|
||||
@@ -396,6 +396,8 @@
|
||||
"producerMarkClean",
|
||||
"producerRemoveLiveConsumerAtIndex",
|
||||
"producerUpdateValueVersion",
|
||||
"profiler",
|
||||
"profilerCallbacks",
|
||||
"readableStreamLikeToAsyncGenerator",
|
||||
"refreshContentQueries",
|
||||
"refreshView",
|
||||
|
||||
@@ -633,6 +633,8 @@
|
||||
"producerNotifyConsumers",
|
||||
"producerRemoveLiveConsumerAtIndex",
|
||||
"producerUpdateValueVersion",
|
||||
"profiler",
|
||||
"profilerCallbacks",
|
||||
"readableStreamLikeToAsyncGenerator",
|
||||
"redirectIfUrlTree",
|
||||
"redirectingNavigationError",
|
||||
|
||||
@@ -329,6 +329,8 @@
|
||||
"producerMarkClean",
|
||||
"producerRemoveLiveConsumerAtIndex",
|
||||
"producerUpdateValueVersion",
|
||||
"profiler",
|
||||
"profilerCallbacks",
|
||||
"refreshContentQueries",
|
||||
"refreshView",
|
||||
"rememberChangeHistoryAndInvokeOnChangesHook",
|
||||
|
||||
@@ -442,6 +442,8 @@
|
||||
"producerMarkClean",
|
||||
"producerRemoveLiveConsumerAtIndex",
|
||||
"producerUpdateValueVersion",
|
||||
"profiler",
|
||||
"profilerCallbacks",
|
||||
"refreshContentQueries",
|
||||
"refreshView",
|
||||
"registerPostOrderHooks",
|
||||
|
||||
Reference in New Issue
Block a user