Skip to content

Commit

Permalink
feat: add performance manager (#4150)
Browse files Browse the repository at this point in the history
* feat: add performance manager

* fix: test

* chore: add static method

* fix: for node12
  • Loading branch information
czy88840616 authored Nov 8, 2024
1 parent 2d39d05 commit 7e04b8e
Show file tree
Hide file tree
Showing 9 changed files with 374 additions and 5 deletions.
2 changes: 1 addition & 1 deletion .eslintrc.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"extends": "./node_modules/mwts/",
"ignorePatterns": ["node_modules", "packages/version", "dist", "test", "jest.config.js", "interface.ts", "interface", "app.js", "agent.js", "site"],
"ignorePatterns": ["node_modules", "packages/version", "dist", "test", "jest.config.js", "interface.ts", "interface", "app.js", "agent.js", "site", "function.js"],
"rules": {
"no-control-regex": "off"
},
Expand Down
172 changes: 172 additions & 0 deletions packages/core/src/common/performanceManager.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
import {
performance,
PerformanceObserver,
PerformanceObserverEntryList,
} from 'perf_hooks';

export class MidwayPerformanceManager {
private static instances: Map<string, MidwayPerformanceManager> = new Map();
public static DEFAULT_GROUP = {
INITIALIZE: 'MidwayInitialize',
};
private observer: PerformanceObserver | null = null;
private marks: Set<string> = new Set();
private measures: Set<string> = new Set();

private constructor(private readonly group: string) {}

static getInstance(group: string): MidwayPerformanceManager {
if (!this.instances.has(group)) {
this.instances.set(group, new MidwayPerformanceManager(group));
}
return this.instances.get(group)!;
}

private formatKey(key: string, step: 'start' | 'end') {
return `${this.group}:${key}-${step}`;
}

public markStart(key: string) {
const markKey = this.formatKey(key, 'start');
performance.mark(markKey);
this.marks.add(markKey);
}

public markEnd(key: string) {
const startKey = this.formatKey(key, 'start');
const endKey = this.formatKey(key, 'end');
const measureKey = `${this.group}:${key}`;

performance.mark(endKey);
this.marks.add(endKey);

performance.measure(measureKey, startKey, endKey);
this.measures.add(measureKey);
}

public observeMeasure(
callback: (list: PerformanceObserverEntryList) => void
) {
if (this.observer) {
return;
}

this.observer = new PerformanceObserver(list => {
const filteredEntries = list
.getEntries()
.filter(entry => entry.name.startsWith(`${this.group}:`));
if (filteredEntries.length > 0) {
callback({
getEntries: () => filteredEntries,
} as PerformanceObserverEntryList);
}
});

this.observer.observe({ entryTypes: ['measure'] });
return this.observer;
}

public disconnect() {
if (this.observer) {
this.observer.disconnect();
this.observer = null;
}
}

public clean() {
this.marks.forEach(mark => {
try {
performance.clearMarks(mark);
} catch (error) {
console.warn(`Failed to clear mark ${mark}: ${error}`);
}
});
this.marks.clear();

this.measures.forEach(measure => {
try {
performance.clearMeasures(measure);
} catch (error) {
console.warn(`Failed to clear measure ${measure}: ${error}`);
}
});
this.measures.clear();

this.disconnect();
}

public static cleanAll() {
this.instances.forEach(instance => instance.clean());
this.instances.clear();
}

public static getInitialPerformanceEntries(): any[] {
const entries: any[] = [];
performance?.getEntries().forEach(entry => {
if (entry.name.startsWith(this.DEFAULT_GROUP.INITIALIZE)) {
entries.push(entry.toJSON());
}
});
return entries;
}
}

export class MidwayInitializerPerformanceManager {
static MEASURE_KEYS = {
INITIALIZE: 'Initialize',
METADATA_PREPARE: 'MetadataPrepare',
DETECTOR_PREPARE: 'DetectorPrepare',
DEFINITION_PREPARE: 'DefinitionPrepare',
CONFIG_LOAD: 'ConfigLoad',
LOGGER_PREPARE: 'LoggerPrepare',
FRAMEWORK_PREPARE: 'FrameworkPrepare',
FRAMEWORK_INITIALIZE: 'FrameworkInitialize',
FRAMEWORK_RUN: 'FrameworkRun',
LIFECYCLE_PREPARE: 'LifecyclePrepare',
PRELOAD_MODULE_PREPARE: 'PreloadModulePrepare',
};

static markStart(key: string) {
const manager = MidwayPerformanceManager.getInstance(
MidwayPerformanceManager.DEFAULT_GROUP.INITIALIZE
);
manager.markStart(key);
}

static markEnd(key: string) {
const manager = MidwayPerformanceManager.getInstance(
MidwayPerformanceManager.DEFAULT_GROUP.INITIALIZE
);
manager.markEnd(key);
}

static frameworkInitializeStart(frameworkName: string) {
this.markStart(
`${this.MEASURE_KEYS.FRAMEWORK_INITIALIZE}:${frameworkName}`
);
}

static frameworkInitializeEnd(frameworkName: string) {
this.markEnd(`${this.MEASURE_KEYS.FRAMEWORK_INITIALIZE}:${frameworkName}`);
}

static frameworkRunStart(frameworkName: string) {
this.markStart(`${this.MEASURE_KEYS.FRAMEWORK_RUN}:${frameworkName}`);
}

static frameworkRunEnd(frameworkName: string) {
this.markEnd(`${this.MEASURE_KEYS.FRAMEWORK_RUN}:${frameworkName}`);
}

static lifecycleStart(namespace: string, lifecycleName: string) {
this.markStart(
`${this.MEASURE_KEYS.LIFECYCLE_PREPARE}:${namespace}:${lifecycleName}`
);
}

static lifecycleEnd(namespace: string, lifecycleName: string) {
this.markEnd(
`${this.MEASURE_KEYS.LIFECYCLE_PREPARE}:${namespace}:${lifecycleName}`
);
}
}
1 change: 1 addition & 0 deletions packages/core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,3 +87,4 @@ export { PathFileUtil } from './util/pathFileUtil';
export { FileUtils } from './util/fs';
export { FORMAT } from './util/format';
export { ServerResponse, HttpServerResponse } from './response/index';
export { MidwayPerformanceManager } from './common/performanceManager';
14 changes: 14 additions & 0 deletions packages/core/src/service/frameworkService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import { MidwayApplicationManager } from '../common/applicationManager';
import * as util from 'util';
import { MidwayCommonError, MidwayParameterError } from '../error';
import { REQUEST_OBJ_CTX_KEY } from '../constants';
import { MidwayInitializerPerformanceManager } from '../common/performanceManager';

const debug = util.debuglog('midway:debug');

Expand Down Expand Up @@ -168,13 +169,20 @@ export class MidwayFrameworkService {
>(frameworkClz, [this.applicationContext]);
// if enable, just init framework
if (frameworkInstance.isEnable()) {
MidwayInitializerPerformanceManager.frameworkInitializeStart(
frameworkInstance.getFrameworkName()
);
// app init
await frameworkInstance.initialize({
applicationContext: this.applicationContext,
namespace: frameworkInstance.getNamespace(),
...this.globalOptions,
});

MidwayInitializerPerformanceManager.frameworkInitializeEnd(
frameworkInstance.getFrameworkName()
);

debug(
`[core]: Found Framework "${frameworkInstance.getFrameworkName()}" and initialize.`
);
Expand Down Expand Up @@ -250,11 +258,17 @@ export class MidwayFrameworkService {
for (const frameworkInstance of this.globalFrameworkList) {
// if enable, just init framework
if (frameworkInstance.isEnable()) {
MidwayInitializerPerformanceManager.frameworkRunStart(
frameworkInstance.getFrameworkName()
);
// app init
await frameworkInstance.run();
debug(
`[core]: Found Framework "${frameworkInstance.getFrameworkName()}" and run.`
);
MidwayInitializerPerformanceManager.frameworkRunEnd(
frameworkInstance.getFrameworkName()
);
}
}
}
Expand Down
19 changes: 15 additions & 4 deletions packages/core/src/service/lifeCycleService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ import { MidwayConfigService } from './configService';
import { debuglog } from 'util';
import { MidwayMockService } from './mockService';
import { MidwayHealthService } from './healthService';
import { MidwayInitializerPerformanceManager } from '../common/performanceManager';

const debug = debuglog('midway:debug');

@Provide()
Expand Down Expand Up @@ -156,27 +158,36 @@ export class MidwayLifeCycleService {
debug(
`[core]: Lifecycle run ${cycle.instance.constructor.name} ${lifecycle}`
);
MidwayInitializerPerformanceManager.lifecycleStart(
cycle.namespace,
lifecycle
);
const result = await cycle.instance[lifecycle](
this.applicationContext,
this.frameworkService.getMainApp()
);
if (resultHandler) {
resultHandler(result);
}
MidwayInitializerPerformanceManager.lifecycleEnd(
cycle.namespace,
lifecycle
);
}
}
} else {
if (typeof lifecycleInstanceOrList[lifecycle] === 'function') {
debug(
`[core]: Lifecycle run ${lifecycleInstanceOrList.constructor.name} ${lifecycle}`
);
const name = lifecycleInstanceOrList.constructor.name;
debug(`[core]: Lifecycle run ${name} ${lifecycle}`);
MidwayInitializerPerformanceManager.lifecycleStart(name, lifecycle);
const result = await lifecycleInstanceOrList[lifecycle](
this.applicationContext,
this.frameworkService.getMainApp()
);
if (resultHandler) {
resultHandler(result);
}
MidwayInitializerPerformanceManager.lifecycleEnd(name, lifecycle);
}
}
}
Expand All @@ -195,7 +206,7 @@ export class MidwayLifeCycleService {
debug(
`[core]: Lifecycle run ${cycle.instance.constructor.name} ${lifecycle}`
);
return this.applicationContext[lifecycle](
return await this.applicationContext[lifecycle](
cycle.instance[lifecycle].bind(cycle.instance)
);
}
Expand Down
Loading

0 comments on commit 7e04b8e

Please sign in to comment.