From 8435cdc952cfe98b7e7ed6f8f01b15e250ec20bf Mon Sep 17 00:00:00 2001 From: Matt Schile Date: Mon, 23 Jan 2023 12:09:52 -0700 Subject: [PATCH] fix: Revert "fix: adding emergency garbage collection for chromium-based browsers" (#25546) --- .../{memory_many_tests.cy.js => memory.cy.js} | 0 .../e2e/memory/memory_large_test.cy.js | 7 -- packages/server/lib/browsers/memory/index.ts | 30 ++----- .../test/unit/browsers/memory/memory_spec.ts | 84 +------------------ 4 files changed, 11 insertions(+), 110 deletions(-) rename packages/driver/cypress/e2e/memory/{memory_many_tests.cy.js => memory.cy.js} (100%) delete mode 100644 packages/driver/cypress/e2e/memory/memory_large_test.cy.js diff --git a/packages/driver/cypress/e2e/memory/memory_many_tests.cy.js b/packages/driver/cypress/e2e/memory/memory.cy.js similarity index 100% rename from packages/driver/cypress/e2e/memory/memory_many_tests.cy.js rename to packages/driver/cypress/e2e/memory/memory.cy.js diff --git a/packages/driver/cypress/e2e/memory/memory_large_test.cy.js b/packages/driver/cypress/e2e/memory/memory_large_test.cy.js deleted file mode 100644 index 63e86ffffd36..000000000000 --- a/packages/driver/cypress/e2e/memory/memory_large_test.cy.js +++ /dev/null @@ -1,7 +0,0 @@ -describe('memory spec', { browser: { family: 'chromium' } }, () => { - it('passes when loading page a 100 times', () => { - for (let index = 0; index < 100; index++) { - cy.visit('http://localhost:3500/memory') - } - }) -}) diff --git a/packages/server/lib/browsers/memory/index.ts b/packages/server/lib/browsers/memory/index.ts index 904d8313b085..9bcddb6468a7 100644 --- a/packages/server/lib/browsers/memory/index.ts +++ b/packages/server/lib/browsers/memory/index.ts @@ -16,7 +16,6 @@ const debug = debugModule('cypress:server:browsers:memory') const debugVerbose = debugModule('cypress-verbose:server:browsers:memory') const MEMORY_THRESHOLD_PERCENTAGE = Number(process.env.CYPRESS_INTERNAL_MEMORY_THRESHOLD_PERCENTAGE) || 50 -const EMERGENCY_MEMORY_THRESHOLD_PERCENTAGE = Number(process.env.CYPRESS_INTERNAL_EMERGENCY_MEMORY_THRESHOLD_PERCENTAGE) || 90 const MEMORY_PROFILER_INTERVAL = Number(process.env.CYPRESS_INTERNAL_MEMORY_PROFILER_INTERVAL) || 1000 const MEMORY_FOLDER = process.env.CYPRESS_INTERNAL_MEMORY_FOLDER_PATH || path.join('cypress', 'logs', 'memory') const SAVE_MEMORY_STATS = ['1', 'true'].includes(process.env.CYPRESS_INTERNAL_MEMORY_SAVE_STATS?.toLowerCase() as string) @@ -55,7 +54,6 @@ export type MemoryHandler = { * 2. set current renderer mem usage * 3. set max avail render mem to minimum of v8 heap size limit and total available mem (current available mem + current renderer mem usage) * 4. calc % of memory used, current renderer mem usage / max avail render mem - * 5. if % of memory used exceeds the emergency memory threshold percentage (e.g. 90%) do a GC * * Before each test: * 1. if any interval exceeded the defined memory threshold (e.g. 50%), do a GC @@ -210,7 +208,7 @@ export const getAvailableMemory: () => Promise = measure(() => { /** * Calculates the memory stats used to determine if garbage collection should be run before the next test starts. */ -export const calculateMemoryStats: (automation: Automation) => Promise = measure(async (automation: Automation) => { +export const calculateMemoryStats: () => Promise = measure(async () => { // retrieve the available memory and the renderer process memory usage const [currentAvailableMemory, rendererProcessMemRss] = await Promise.all([ getAvailableMemory(), @@ -234,14 +232,6 @@ export const calculateMemoryStats: (automation: Automation) => Promise = m // if we should collect garbage, set the flag to true so we can collect garbage on the next test collectGarbageOnNextTest = collectGarbageOnNextTest || shouldCollectGarbage - // if the renderer's memory is above the EMERGENCY_MEMORY_THRESHOLD_PERCENTAGE, we should perform an emergency garbage collection now - const shouldEmergencyCollectGarbage = rendererUsagePercentage >= EMERGENCY_MEMORY_THRESHOLD_PERCENTAGE && !SKIP_GC - - if (shouldEmergencyCollectGarbage) { - debug('emergency garbage collection triggered') - await checkMemoryPressure(automation, shouldEmergencyCollectGarbage) - } - // set all the memory stats on the stats log statsLog.jsHeapSizeLimit = jsHeapSizeLimit statsLog.totalMemoryLimit = totalMemoryLimit @@ -251,8 +241,6 @@ export const calculateMemoryStats: (automation: Automation) => Promise = m statsLog.currentAvailableMemory = currentAvailableMemory statsLog.maxAvailableRendererMemory = maxAvailableRendererMemory statsLog.shouldCollectGarbage = shouldCollectGarbage - statsLog.emergencyGarbageCollected = shouldEmergencyCollectGarbage - statsLog.emergencyRendererMemoryThreshold = maxAvailableRendererMemory * (EMERGENCY_MEMORY_THRESHOLD_PERCENTAGE / 100) statsLog.timestamp = Date.now() }, { name: 'calculateMemoryStats', save: true }) @@ -281,8 +269,8 @@ const checkMemoryPressureAndLog = async ({ automation, test }: { automation: Aut * Collects the browser's garbage if it previously exceeded the threshold when it was measured. * @param automation the automation client used to collect garbage */ -const checkMemoryPressure: (automation: Automation, emergencyCollectGarbage?: boolean) => Promise = measure(async (automation: Automation, emergencyCollectGarbage: boolean = false) => { - if (collectGarbageOnNextTest || emergencyCollectGarbage) { +const checkMemoryPressure: (automation: Automation) => Promise = measure(async (automation: Automation) => { + if (collectGarbageOnNextTest) { debug('forcing garbage collection') try { await automation.request('collect:garbage', null, null) @@ -309,24 +297,24 @@ const addCumulativeStats = (stats: { [key: string]: any }) => { /** * Gathers the memory stats and schedules the next check. */ -const gatherMemoryStats = async (automation: Automation) => { +const gatherMemoryStats = async () => { try { - await calculateMemoryStats(automation) + await calculateMemoryStats() addCumulativeStats(statsLog) statsLog = {} } catch (err) { debug('error gathering memory stats: %o', err) } - scheduleMemoryCheck(automation) + scheduleMemoryCheck() } /** * Schedules the next gathering of memory stats based on the MEMORY_PROFILER_INTERVAL. */ -const scheduleMemoryCheck = (automation: Automation) => { +const scheduleMemoryCheck = () => { if (started) { // not setinterval, since gatherMemoryStats is asynchronous - timer = setTimeout(() => gatherMemoryStats(automation), MEMORY_PROFILER_INTERVAL) + timer = setTimeout(gatherMemoryStats, MEMORY_PROFILER_INTERVAL) } } @@ -365,7 +353,7 @@ async function startProfiling (automation: Automation, spec: { fileName: string totalMemoryLimit = await handler.getTotalMemoryLimit(), ]) - await gatherMemoryStats(automation) + await gatherMemoryStats() } catch (err) { debug('error starting memory profiler: %o', err) } diff --git a/packages/server/test/unit/browsers/memory/memory_spec.ts b/packages/server/test/unit/browsers/memory/memory_spec.ts index b56b065c23d0..4ef5defafc1c 100644 --- a/packages/server/test/unit/browsers/memory/memory_spec.ts +++ b/packages/server/test/unit/browsers/memory/memory_spec.ts @@ -141,8 +141,6 @@ describe('lib/browsers/memory', () => { rendererUsagePercentage: 75, rendererMemoryThreshold: 50, currentAvailableMemory: 1000, - emergencyGarbageCollected: false, - emergencyRendererMemoryThreshold: 90, maxAvailableRendererMemory: 100, shouldCollectGarbage: true, timestamp: 0, @@ -191,8 +189,6 @@ describe('lib/browsers/memory', () => { rendererUsagePercentage: 25, rendererMemoryThreshold: 25, currentAvailableMemory: 1000, - emergencyGarbageCollected: false, - emergencyRendererMemoryThreshold: 90, maxAvailableRendererMemory: 100, shouldCollectGarbage: true, timestamp: 0, @@ -236,8 +232,6 @@ describe('lib/browsers/memory', () => { rendererUsagePercentage: 50, rendererMemoryThreshold: 50, currentAvailableMemory: 1000, - emergencyGarbageCollected: false, - emergencyRendererMemoryThreshold: 90, maxAvailableRendererMemory: 100, shouldCollectGarbage: true, timestamp: 0, @@ -281,8 +275,6 @@ describe('lib/browsers/memory', () => { rendererUsagePercentage: 71.42857142857143, rendererMemoryThreshold: 17.5, currentAvailableMemory: 10, - emergencyGarbageCollected: false, - emergencyRendererMemoryThreshold: 31.5, maxAvailableRendererMemory: 35, shouldCollectGarbage: true, timestamp: 0, @@ -326,8 +318,6 @@ describe('lib/browsers/memory', () => { rendererUsagePercentage: 25, rendererMemoryThreshold: 50, currentAvailableMemory: 1000, - emergencyGarbageCollected: false, - emergencyRendererMemoryThreshold: 90, maxAvailableRendererMemory: 100, shouldCollectGarbage: false, timestamp: 0, @@ -421,8 +411,6 @@ describe('lib/browsers/memory', () => { rendererUsagePercentage: 51.2, rendererMemoryThreshold: 1000, currentAvailableMemory: 2000, - emergencyGarbageCollected: false, - emergencyRendererMemoryThreshold: 1800, maxAvailableRendererMemory: 2000, shouldCollectGarbage: true, timestamp: 0, @@ -479,8 +467,6 @@ describe('lib/browsers/memory', () => { rendererUsagePercentage: 51.2, rendererMemoryThreshold: 1000, currentAvailableMemory: 2000, - emergencyGarbageCollected: false, - emergencyRendererMemoryThreshold: 1800, maxAvailableRendererMemory: 2000, shouldCollectGarbage: true, timestamp: 0, @@ -538,8 +524,6 @@ describe('lib/browsers/memory', () => { rendererUsagePercentage: 51.2, rendererMemoryThreshold: 5000, currentAvailableMemory: 10000, - emergencyGarbageCollected: false, - emergencyRendererMemoryThreshold: 9000, maxAvailableRendererMemory: 10000, shouldCollectGarbage: true, timestamp: 0, @@ -592,7 +576,7 @@ describe('lib/browsers/memory', () => { await memory.default.startProfiling(automation, { fileName: 'memory_spec' }) // second call will use the existing process id and use pidusage - await memory.default.gatherMemoryStats(automation) + await memory.default.gatherMemoryStats() await memory.default.checkMemoryPressure({ automation, test: { title: 'test', order: 1, currentRetry: 0 } }) @@ -606,8 +590,6 @@ describe('lib/browsers/memory', () => { rendererUsagePercentage: 34.13333333333333, rendererMemoryThreshold: 1500, currentAvailableMemory: 3000, - emergencyGarbageCollected: false, - emergencyRendererMemoryThreshold: 2700, maxAvailableRendererMemory: 3000, shouldCollectGarbage: false, timestamp: 0, @@ -622,8 +604,6 @@ describe('lib/browsers/memory', () => { rendererUsagePercentage: 66.66666666666666, rendererMemoryThreshold: 1500, currentAvailableMemory: 3000, - emergencyGarbageCollected: false, - emergencyRendererMemoryThreshold: 2700, maxAvailableRendererMemory: 3000, shouldCollectGarbage: true, timestamp: 0, @@ -659,7 +639,7 @@ describe('lib/browsers/memory', () => { .onSecondCall().resolves(25) // below threshold await memory.default.startProfiling(automation, { fileName: 'memory_spec' }) - await memory.default.gatherMemoryStats(automation) + await memory.default.gatherMemoryStats() await memory.default.checkMemoryPressure({ automation, test: { title: 'test', order: 1, currentRetry: 0 } }) const expected = [ @@ -671,8 +651,6 @@ describe('lib/browsers/memory', () => { rendererUsagePercentage: 75, rendererMemoryThreshold: 50, currentAvailableMemory: 1000, - emergencyGarbageCollected: false, - emergencyRendererMemoryThreshold: 90, maxAvailableRendererMemory: 100, shouldCollectGarbage: true, timestamp: 0, @@ -686,8 +664,6 @@ describe('lib/browsers/memory', () => { rendererUsagePercentage: 25, rendererMemoryThreshold: 50, currentAvailableMemory: 1000, - emergencyGarbageCollected: false, - emergencyRendererMemoryThreshold: 90, maxAvailableRendererMemory: 100, shouldCollectGarbage: false, timestamp: 0, @@ -706,62 +682,6 @@ describe('lib/browsers/memory', () => { expect(memory.getRendererMemoryUsage).to.be.calledTwice expect(memory.default.getMemoryStats()).to.deep.eql(expected) }) - - it('performs an emergency garbage collection when the renderer memory goes over the emergency threshold', async () => { - const automation = sinon.createStubInstance(Automation) - const gcStub = automation.request.withArgs('collect:garbage').resolves() - const mockHandler = { - getAvailableMemory: sinon.stub().resolves(1000), - getTotalMemoryLimit: sinon.stub().resolves(2000), - } - - sinon.stub(memory, 'getJsHeapSizeLimit').resolves(100) - sinon.stub(memory, 'getMemoryHandler').resolves(mockHandler) - sinon.stub(memory, 'getRendererMemoryUsage') - .onFirstCall().resolves(25) - .onSecondCall().resolves(90) // equal to the emergency threshold - - await memory.default.startProfiling(automation, { fileName: 'memory_spec' }) - // this should trigger an emergency garbage collection without needing a call to checkMemoryPressure - await memory.default.gatherMemoryStats(automation) - - const expected = [ - { - getAvailableMemoryDuration: 0, - jsHeapSizeLimit: 100, - totalMemoryLimit: 2000, - rendererProcessMemRss: 25, - rendererUsagePercentage: 25, - rendererMemoryThreshold: 50, - currentAvailableMemory: 1000, - emergencyGarbageCollected: false, - emergencyRendererMemoryThreshold: 90, - maxAvailableRendererMemory: 100, - shouldCollectGarbage: false, - timestamp: 0, - calculateMemoryStatsDuration: 0, - }, - { - getAvailableMemoryDuration: 0, - jsHeapSizeLimit: 100, - totalMemoryLimit: 2000, - rendererProcessMemRss: 90, - rendererUsagePercentage: 90, - rendererMemoryThreshold: 50, - currentAvailableMemory: 1000, - emergencyGarbageCollected: true, - emergencyRendererMemoryThreshold: 90, - maxAvailableRendererMemory: 100, - shouldCollectGarbage: true, - timestamp: 0, - calculateMemoryStatsDuration: 0, - }, - ] - - expect(gcStub).to.be.calledOnce - expect(memory.getRendererMemoryUsage).to.be.calledTwice - expect(memory.default.getMemoryStats()).to.deep.eql(expected) - }) }) context('#endProfiling', () => {