Skip to content

Commit

Permalink
fix: Revert "fix: adding emergency garbage collection for chromium-ba…
Browse files Browse the repository at this point in the history
…sed browsers" (#25546)
  • Loading branch information
mschile authored Jan 23, 2023
1 parent 90187ea commit 8435cdc
Show file tree
Hide file tree
Showing 4 changed files with 11 additions and 110 deletions.
7 changes: 0 additions & 7 deletions packages/driver/cypress/e2e/memory/memory_large_test.cy.js

This file was deleted.

30 changes: 9 additions & 21 deletions packages/server/lib/browsers/memory/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -210,7 +208,7 @@ export const getAvailableMemory: () => Promise<number> = 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<void> = measure(async (automation: Automation) => {
export const calculateMemoryStats: () => Promise<void> = measure(async () => {
// retrieve the available memory and the renderer process memory usage
const [currentAvailableMemory, rendererProcessMemRss] = await Promise.all([
getAvailableMemory(),
Expand All @@ -234,14 +232,6 @@ export const calculateMemoryStats: (automation: Automation) => Promise<void> = 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
Expand All @@ -251,8 +241,6 @@ export const calculateMemoryStats: (automation: Automation) => Promise<void> = 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 })

Expand Down Expand Up @@ -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<void> = measure(async (automation: Automation, emergencyCollectGarbage: boolean = false) => {
if (collectGarbageOnNextTest || emergencyCollectGarbage) {
const checkMemoryPressure: (automation: Automation) => Promise<void> = measure(async (automation: Automation) => {
if (collectGarbageOnNextTest) {
debug('forcing garbage collection')
try {
await automation.request('collect:garbage', null, null)
Expand All @@ -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)
}
}

Expand Down Expand Up @@ -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)
}
Expand Down
84 changes: 2 additions & 82 deletions packages/server/test/unit/browsers/memory/memory_spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -141,8 +141,6 @@ describe('lib/browsers/memory', () => {
rendererUsagePercentage: 75,
rendererMemoryThreshold: 50,
currentAvailableMemory: 1000,
emergencyGarbageCollected: false,
emergencyRendererMemoryThreshold: 90,
maxAvailableRendererMemory: 100,
shouldCollectGarbage: true,
timestamp: 0,
Expand Down Expand Up @@ -191,8 +189,6 @@ describe('lib/browsers/memory', () => {
rendererUsagePercentage: 25,
rendererMemoryThreshold: 25,
currentAvailableMemory: 1000,
emergencyGarbageCollected: false,
emergencyRendererMemoryThreshold: 90,
maxAvailableRendererMemory: 100,
shouldCollectGarbage: true,
timestamp: 0,
Expand Down Expand Up @@ -236,8 +232,6 @@ describe('lib/browsers/memory', () => {
rendererUsagePercentage: 50,
rendererMemoryThreshold: 50,
currentAvailableMemory: 1000,
emergencyGarbageCollected: false,
emergencyRendererMemoryThreshold: 90,
maxAvailableRendererMemory: 100,
shouldCollectGarbage: true,
timestamp: 0,
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -326,8 +318,6 @@ describe('lib/browsers/memory', () => {
rendererUsagePercentage: 25,
rendererMemoryThreshold: 50,
currentAvailableMemory: 1000,
emergencyGarbageCollected: false,
emergencyRendererMemoryThreshold: 90,
maxAvailableRendererMemory: 100,
shouldCollectGarbage: false,
timestamp: 0,
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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 } })

Expand All @@ -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,
Expand All @@ -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,
Expand Down Expand Up @@ -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 = [
Expand All @@ -671,8 +651,6 @@ describe('lib/browsers/memory', () => {
rendererUsagePercentage: 75,
rendererMemoryThreshold: 50,
currentAvailableMemory: 1000,
emergencyGarbageCollected: false,
emergencyRendererMemoryThreshold: 90,
maxAvailableRendererMemory: 100,
shouldCollectGarbage: true,
timestamp: 0,
Expand All @@ -686,8 +664,6 @@ describe('lib/browsers/memory', () => {
rendererUsagePercentage: 25,
rendererMemoryThreshold: 50,
currentAvailableMemory: 1000,
emergencyGarbageCollected: false,
emergencyRendererMemoryThreshold: 90,
maxAvailableRendererMemory: 100,
shouldCollectGarbage: false,
timestamp: 0,
Expand All @@ -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', () => {
Expand Down

5 comments on commit 8435cdc

@cypress-bot
Copy link
Contributor

@cypress-bot cypress-bot bot commented on 8435cdc Jan 23, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Circle has built the linux arm64 version of the Test Runner.

Learn more about this pre-release build at https://on.cypress.io/advanced-installation#Install-pre-release-version

Run this command to install the pre-release locally:

npm install https://cdn.cypress.io/beta/npm/12.4.0/linux-arm64/develop-8435cdc952cfe98b7e7ed6f8f01b15e250ec20bf/cypress.tgz

@cypress-bot
Copy link
Contributor

@cypress-bot cypress-bot bot commented on 8435cdc Jan 23, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Circle has built the linux x64 version of the Test Runner.

Learn more about this pre-release build at https://on.cypress.io/advanced-installation#Install-pre-release-version

Run this command to install the pre-release locally:

npm install https://cdn.cypress.io/beta/npm/12.4.0/linux-x64/develop-8435cdc952cfe98b7e7ed6f8f01b15e250ec20bf/cypress.tgz

@cypress-bot
Copy link
Contributor

@cypress-bot cypress-bot bot commented on 8435cdc Jan 23, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Circle has built the darwin arm64 version of the Test Runner.

Learn more about this pre-release build at https://on.cypress.io/advanced-installation#Install-pre-release-version

Run this command to install the pre-release locally:

npm install https://cdn.cypress.io/beta/npm/12.4.0/darwin-arm64/develop-8435cdc952cfe98b7e7ed6f8f01b15e250ec20bf/cypress.tgz

@cypress-bot
Copy link
Contributor

@cypress-bot cypress-bot bot commented on 8435cdc Jan 23, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Circle has built the darwin x64 version of the Test Runner.

Learn more about this pre-release build at https://on.cypress.io/advanced-installation#Install-pre-release-version

Run this command to install the pre-release locally:

npm install https://cdn.cypress.io/beta/npm/12.4.0/darwin-x64/develop-8435cdc952cfe98b7e7ed6f8f01b15e250ec20bf/cypress.tgz

@cypress-bot
Copy link
Contributor

@cypress-bot cypress-bot bot commented on 8435cdc Jan 23, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Circle has built the win32 x64 version of the Test Runner.

Learn more about this pre-release build at https://on.cypress.io/advanced-installation#Install-pre-release-version

Run this command to install the pre-release locally:

npm install https://cdn.cypress.io/beta/npm/12.4.0/win32-x64/develop-8435cdc952cfe98b7e7ed6f8f01b15e250ec20bf/cypress.tgz

Please sign in to comment.