mirror of
https://github.com/microsoft/vscode.git
synced 2026-05-08 17:19:48 +01:00
release object group
This commit is contained in:
@@ -110,6 +110,14 @@ export class PlaywrightDriver {
|
||||
return await this._cdpSession.send('Runtime.evaluate', options);
|
||||
}
|
||||
|
||||
async releaseObjectGroup(parameters: Protocol.Runtime.releaseObjectGroupParameters): Promise<void> {
|
||||
if (!this._cdpSession) {
|
||||
throw new Error('CDP not started');
|
||||
}
|
||||
|
||||
await this._cdpSession.send('Runtime.releaseObjectGroup', parameters);
|
||||
}
|
||||
|
||||
async queryObjects(parameters: Protocol.Runtime.queryObjectsParameters): Promise<Protocol.Runtime.queryObjectsReturnValue> {
|
||||
if (!this._cdpSession) {
|
||||
throw new Error('CDP not started');
|
||||
@@ -132,11 +140,15 @@ export class PlaywrightDriver {
|
||||
}
|
||||
|
||||
let snapshot = '';
|
||||
this._cdpSession.addListener('HeapProfiler.addHeapSnapshotChunk', ({ chunk }) => {
|
||||
snapshot += chunk;
|
||||
});
|
||||
const listener = (c: { chunk: string }) => {
|
||||
snapshot += c.chunk;
|
||||
};
|
||||
|
||||
this._cdpSession.addListener('HeapProfiler.addHeapSnapshotChunk', listener);
|
||||
|
||||
await this._cdpSession.send('HeapProfiler.takeHeapSnapshot');
|
||||
|
||||
this._cdpSession.removeListener('HeapProfiler.addHeapSnapshotChunk', listener);
|
||||
return snapshot;
|
||||
}
|
||||
|
||||
|
||||
@@ -12,26 +12,28 @@ export class Profiler {
|
||||
constructor(private readonly code: Code) {
|
||||
}
|
||||
|
||||
async checkLeaks(classNames: string | string[], fn: () => Promise<void>): Promise<void> {
|
||||
async checkObjectLeaks(classNames: string | string[], fn: () => Promise<void>): Promise<void> {
|
||||
await this.code.driver.startCDP();
|
||||
|
||||
const countsBefore: { [key: string]: number } = {};
|
||||
const instancesBefore = await getInstances(this.code.driver);
|
||||
const classNamesArray = Array.isArray(classNames) ? classNames : [classNames];
|
||||
for (const className of classNamesArray) {
|
||||
const matchedInstances = instancesBefore.find(e => e.name !== undefined && e.name === className);
|
||||
const matchedInstances = instancesBefore.value.find(e => e.name !== undefined && e.name === className);
|
||||
if (!matchedInstances) {
|
||||
throw new Error(`${className} not found`);
|
||||
}
|
||||
countsBefore[className] = matchedInstances.count;
|
||||
}
|
||||
|
||||
await instancesBefore.dispose();
|
||||
|
||||
await fn();
|
||||
|
||||
const instancesAfter = await getInstances(this.code.driver);
|
||||
const leaks: string[] = [];
|
||||
for (const className of classNamesArray) {
|
||||
const matchedInstancesAfter = instancesAfter.find(e => e.name !== undefined && e.name === className);
|
||||
const matchedInstancesAfter = instancesAfter.value.find(e => e.name !== undefined && e.name === className);
|
||||
if (!matchedInstancesAfter) {
|
||||
throw new Error(`${className} not found`);
|
||||
}
|
||||
@@ -42,6 +44,8 @@ export class Profiler {
|
||||
}
|
||||
}
|
||||
|
||||
await instancesAfter.dispose();
|
||||
|
||||
if (leaks.length > 0) {
|
||||
throw new Error(leaks.join('\n'));
|
||||
}
|
||||
@@ -126,7 +130,7 @@ function generateUuid() {
|
||||
* This code is derived from https://github.com/SimonSiefke/vscode-memory-leak-finder
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
const getInstances = async (driver: PlaywrightDriver): Promise<Array<{ name: string; count: number }>> => {
|
||||
const getInstances = async (driver: PlaywrightDriver): Promise<{ value: Array<{ name: string; count: number }>; dispose: () => Promise<void> }> => {
|
||||
await driver.collectGarbage();
|
||||
const objectGroup = `og:${generateUuid()}`;
|
||||
const prototypeDescriptor = await driver.evaluate({
|
||||
@@ -207,7 +211,13 @@ const getInstances = async (driver: PlaywrightDriver): Promise<Array<{ name: str
|
||||
|
||||
const fnResult2 = await getInstanceCountMap(driver, objectGroup, fnResult1.result);
|
||||
const fnResult3 = await getInstanceCountArray(driver, objectGroup, fnResult2.result);
|
||||
return fnResult3.result.value;
|
||||
return {
|
||||
value: fnResult3.result.value,
|
||||
dispose: async () => {
|
||||
// release object group
|
||||
await driver.releaseObjectGroup({ objectGroup: objectGroup });
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
const getInstanceCountMap = async (driver: PlaywrightDriver, objectGroup: string, objects: Protocol.Runtime.RemoteObject) => {
|
||||
|
||||
@@ -25,7 +25,7 @@ export function setup(logger: Logger) {
|
||||
cp.execSync('git reset --hard HEAD --quiet', { cwd: app.workspacePathOrFolder });
|
||||
});
|
||||
|
||||
it('check heap leaks', async function () {
|
||||
it.skip('check heap leaks', async function () {
|
||||
const app = this.app as Application;
|
||||
await app.profiler.checkHeapLeaks(['NotebookTextModel', 'NotebookCellTextModel', 'NotebookEventDispatcher'], async () => {
|
||||
await app.workbench.notebook.openNotebook();
|
||||
@@ -36,7 +36,7 @@ export function setup(logger: Logger) {
|
||||
|
||||
it('check object leaks', async function () {
|
||||
const app = this.app as Application;
|
||||
await app.profiler.checkLeaks(['NotebookTextModel'], async () => {
|
||||
await app.profiler.checkObjectLeaks(['NotebookTextModel', 'NotebookCellTextModel', 'NotebookEventDispatcher'], async () => {
|
||||
await app.workbench.notebook.openNotebook();
|
||||
await app.workbench.quickaccess.runCommand('workbench.action.files.save');
|
||||
await app.workbench.quickaccess.runCommand('workbench.action.closeActiveEditor');
|
||||
|
||||
Reference in New Issue
Block a user