-
Notifications
You must be signed in to change notification settings - Fork 3.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Reduce Memory Usage with window.gc() #8525
Comments
--js-flags=--expose-gc
Chrome flag--js-flags=--expose-gc
Chrome flag and window.gc()
calls
--js-flags=--expose-gc
Chrome flag and window.gc()
callswindow.gc
by default via --js-flags=--expose-gc
window.gc
by default via --js-flags=--expose-gc
I have not been able to find a way to expose the garbage collector in Edge or FireFox. In the past there were a lot of different APIs for causing GC - the documentation around all of them is pretty sparse, or no longer exists.
It's possible to "force" garbage collection by manually increasing memory pressure (creating tons of objects/keys). It's probably going to be slower though. I'm not sure if this is worth implementing as a fallback, but it may provide some benefit for browsers where the a GC method is not available. |
There's a chance that tests for low-memory apps would run slower with this, because calling I'm not sure if high memory apps also run slower too, in my case the tests would crash vs not crash so the performance hit was not noticeable and worth taking on. |
@CoryDanielson that's the reason why forced GC has not been implemented in Cypress as a whole - it is expensive, and causes user tests to pause/stutter during garbage collection. When Cypress initially introduced Firefox support, code was introduced that used the Firefox driver protocol to force garbage collection after tests ( You can manually trigger the Firefox GC routine (even in FF >= 80) by using The reason why forced GC was removed as soon as Firefox 80 became available was because it was causing user tests to run much more slowly than if we didn't force GC. With this in mind, I still think that the functionality you're proposing is a good idea, because users do run into memory issues that can be helped with the use of forced GC. However, it is probably better-suited to being a user plugin than to being in Cypress core. |
Thanks for the info! Does it make sense to expose chrome/electron gc in the same way as FF, or are you planning on removing the |
If you want to, you can open up a PR to add the Closing since this feature request will not be implemented in Cypress core. |
Thanks alot @CoryDanielson !! I tried this fix in our jenkins-docker pipeline.. it seem to have fixed the stuck runs with chrome. |
@CoryDanielson how can I check that flag is set in browse? |
If it's working properly you can open the browse and type " If you want to test in Electron, simply do if (win.gc) throw new Error("win.gc exists!") |
I exactly tried this and i also tried to set the ELECTRON_EXTRA_LAUNCH_ARGS=--js-flags=--expose_gc with export on my linux system, but neither can i use window.gc in the developer tools console nor does the gc work on the tests. |
Yes, win.gc() definitely helped me too.
…On Tue, 30 Aug 2022 at 19:49, Marcus Trepte ***@***.***> wrote:
I recently discovered that a method can be exposed in Chrome and Electron
to trigger garbage collection, and it seems to improve memory consumption
significantly during test runs.
*I'm wondering if adding this functionality to cypress by default (rather
than a plugin) would be worthwhile, to hopefully reduce the number of
crashes and improve performance.*
Browser Flag/Switch
Chrome --js-flags=--expose-gc
Electron --js-flags=--expose_gc
Once enabled, you can simply call window.gc() within javascript code.
I ran the same Cypress test with and without calling window.gc() in a
global afterEach and saw a *30-50%* reduction in peak memory usage
<#350 (comment)>
from the same tests.
I suspect that this will also reduce the number of crashes due to hitting
the max memory. For a large and complex app with lots of requests, I think
the CPU is too busy and never has the downtime required for javascripts
garbage collector to clean up stale references. GC does occur occasionally,
but not often enough, and that eventually becomes a fatal mistake as the
cypress process gets closer to the max memory threshold and GC is not run.
In my case, starting a new test could increase memory usage by 100-300mb,
and put the app over the 2gb limit.
To enable win.gc() for election, run cypress with the following with this
environment variable set:
ELECTRON_EXTRA_LAUNCH_ARGS=--js-flags=--expose_gc cypress run
*cypress/plugins/index.js*
- enable win.gc() for chrome
// enables win.gc() for chrome
module.exports = (on, config) => {
on('before:browser:launch', (browser, launchOptions) => {
if (browser.name === 'chrome') {
// exposes window.gc() function that will manually force garbage collection
launchOptions.args.push('--js-flags=--expose-gc');
}
return launchOptions;
});};
*cypress/support/index.js*
afterEach(() => {
cy.window().then(win => {
// window.gc is enabled with --js-flags=--expose-gc chrome flag
if (typeof win.gc === 'function') {
// run gc multiple times in an attempt to force a major GC between tests
win.gc();
win.gc();
win.gc();
win.gc();
win.gc();
}
});});
I exactly tried this and i also tried to set the
ELECTRON_EXTRA_LAUNCH_ARGS=--js-flags=--expose_gc with export on my linux
system, but neither can i use window.gc in the developer tools console nor
does the gc work on the tests.
I'm using chrome version: 104.0.5112.101 (Official Build) (64-bit)
Does anyone of you know if this is not supported by chrome anymore?
—
Reply to this email directly, view it on GitHub
<#8525 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AFKDNFEXSA2RN64OOLVAMVLV3YUPVANCNFSM4RAORJVQ>
.
You are receiving this because you commented.Message ID:
***@***.***>
|
@MarcusElevait window.gc still works fine for me in Chrome 104 |
@MarcusElevait in the latest version of Cypress, cypress/plugins/index.js does not work the same as it used to. If you copy/pasted the code from this ticket into plugins/index.js that may be the problem See https://docs.cypress.io/guides/references/migration-guide#Plugins-File-Removed |
What is the command to collect garbage in chrome 105? Window/win.gc() no longer work for me :? |
@JohnSmithyy Have you followed the steps from the original post in this thread to enable |
I have and i get undefined errors but my cypress still crashes too :/ |
You'll have to debug and see if that plugin change to enable GC is being run, as you expect. I'm on Cypress 9.3 still, so I can't give you exact code for how to load it in Cypress 10 |
So i found out what was doing wrong. I had another browser window open. So to try it out locally, you first have to close all chrome instances. So i managed to do it while starting chrome from command line. But still struggling to use it with cypress. I can see, that the launchoptions.args now have the --js-flags=expose-gc option set and i also set the ELECTRON_EXTRA_LAUNCH_ARGS, but still the window.gc function is not present in the browser. |
You may want to file a bug for window.gc not working. If you're using the code I provided in this GitHub thread it should work in Cypress 9 and below, but I don't know the exact code for Cypress 10 |
Okay now i managed to make it work. I guess it just works with cypress run, not with cypress open, right? Thanks for the help here. |
It works with Cypress open too. Maybe try |
This was the command i've tried With this it worked But it's fine for me, i don't need it in the watch mode. |
Sorry i was wrong, it doesn't work for both cases. |
@MarcusElevait ELECTRON_EXTRA_LAUNCH_ARGS are for electron, not Chrome. To set these flags for Chrome, you'll need to do it in your cypress.config.js (for Cypress 10). Based on this section of the docs, it should look something like this for Cypress 10 // cypress.config.js
const { defineConfig } = require('cypress')
module.exports = defineConfig({
// setupNodeEvents can be defined in either
// the e2e or component configuration
e2e: {
setupNodeEvents(on, config) {
on('before:browser:launch', (browser = {}, launchOptions) => {
// Chrome is used by default for `cypress open`
// Electron is used for `cypress run` but the command line flags are modified by ELECTRON_EXTRA_LAUNCH_ARGS environment variable
if (browser.name === 'chrome') {
// exposes window.gc() function that will manually force garbage collection
launchOptions.args.push('--js-flags=--expose-gc');
}
return launchOptions;
})
}
}
}) Once that is set up, you'll need to add a global afterEach hook to your Support File that calls // cypress/support/e2e.js
afterEach(() => {
cy.window().then(win => {
// window.gc is enabled with --js-flags=--expose-gc chrome flag
// window.gc is enabled for electron with ELECTRON_EXTRA_LAUNCH_ARGS=--js-flags=--expose_gc
if (typeof win.gc === 'function') {
// run gc multiple times in an attempt to force a major GC between tests
win.gc();
win.gc();
win.gc();
win.gc();
win.gc();
}
});
}); |
@CoryDanielson so much thanks for your help. I finally managed to make it work for our project and it really helps us a lot with damn bitbucket pipelines ;-) |
This was my plan B. Nice thread! |
My browser still crashed even with window.gc being called. I ran all my tests with Really just need to avoid this issue with the specific Chrome versions, until it's fixed by Chrome. |
I believe it is not a good idea to run all your tests in |
I recently discovered that a method can be exposed in Chrome and Electron to trigger garbage collection, and it seems to improve memory consumption significantly during test runs.
I'm wondering if adding this functionality to cypress by default (rather than a plugin) would be worthwhile, to hopefully reduce the number of crashes and improve performance.
Once enabled, you can simply call
window.gc()
within javascript code.I ran the same Cypress test with and without calling
window.gc()
in a globalafterEach
and saw a 30-50% reduction in peak memory usage from the same tests.I suspect that this will also reduce the number of crashes due to hitting the max memory. For a large and complex app with lots of requests, I think the CPU is too busy and never has the downtime required for javascripts garbage collector to clean up stale references. GC does occur occasionally, but not often enough, and that eventually becomes a fatal mistake as the cypress process gets closer to the max memory threshold and GC is not run. In my case, starting a new test could increase memory usage by 100-300mb, and put the app over the 2gb limit.
To enable
win.gc()
for election, run cypress with the following with this environment variable set:ELECTRON_EXTRA_LAUNCH_ARGS=--js-flags=--expose_gc cypress run
cypress/plugins/index.js
cypress/support/index.js
The text was updated successfully, but these errors were encountered: