Skip to content

feat: Close and reopen a new tab in between tests to get around a memory leak#19915

Merged
ryanthemanuel merged 76 commits into
10.0-releasefrom
ryanm/feat/memory-leak
Feb 8, 2022
Merged

feat: Close and reopen a new tab in between tests to get around a memory leak#19915
ryanthemanuel merged 76 commits into
10.0-releasefrom
ryanm/feat/memory-leak

Conversation

@ryanthemanuel
Copy link
Copy Markdown
Collaborator

@ryanthemanuel ryanthemanuel commented Jan 26, 2022

User facing changelog

Additional details

With this work, we will be changing how run mode works with respect to transitioning from spec to spec. As @brian-mann stated in the comments today we:

  1. open browser to about:blank with fresh user profile + data dir folder
  2. bind CDP to the browser / tab
  3. start screencast
  4. navigate tab to URL
  5. browser yields screencast frames
  6. write to ffmpeg
  7. ...spec finishes...
  8. close the browser
  9. stop screencast frames
  10. process video
  11. ...close browser and repeat steps for next spec...

We will be changing this so that on step 11 we:

  1. Stopping the video
  2. Clear the browser state
  3. Close the browser tab
  4. Clear the server state
  5. Open a new tab directly to 'about:blank'
  6. Rebind CDP to the fresh tab
  7. Navigate to the new url
  8. Start the video

A couple of important points to note:

  • before:browser:launch will now only fire once per overall run rather than once per spec file for chrome and firefox. This is due to the fact that the browser is only launched once at the beginning of the run and then subsequent specs close existing tabs and open new ones
  • Irreconcilable CDP disconnects will now be treated as fatal errors since we can't use CDP to continue on with subsequent specs (previously we could at least attempt to launch a new browser)
  • Firefox will have a slightly different functional behavior than chrome. Chrome will close browser tabs in between spec files; however, firefox will close browser tabs, but closing a tab will cause a blank tab to immediately reopen. This is necessary in order to keep the necessary debugging connections available.

How has the user experience changed?

PR Tasks

  • Have tests been added/updated?
  • [na] Has the original issue (or this PR, if no issue exists) been tagged with a release in ZenHub? (user-facing changes only)
  • [na] Has a PR for user-facing changes been opened in cypress-documentation?
  • [na] Have API changes been updated in the type definitions?
  • [na] Have new configuration options been added to the cypress.schema.json?

@cypress-bot
Copy link
Copy Markdown
Contributor

cypress-bot Bot commented Jan 26, 2022

Thanks for taking the time to open a PR!

@brian-mann
Copy link
Copy Markdown
Member

brian-mann commented Jan 26, 2022

Background

Today we currently close the browser in between specs for e2e - which adds a considerable amount of time to the overall run. The desired functionality for CT is to not close the browser and navigate to the new spec URL. Unfortunately, there is currently a memory leak in Unification, and because we use hash based routing - navigating to the new spec URL does not cause a full page refresh, thus building up memory until its fully exhausted.

While I expect us to eventually fix the memory leak, we can take a "middle-of-the-road" approach here and utilize this improvement for both e2e + ct, which would be much more consistent. The "middle-of-the-road" approach avoids needing to close the browser in between specs, and we could simply "clear" or "close" the primary tab to ensure that specs start clean.

Cypress Today (first spec - with video)

  1. opens browser to about:blank with fresh user profile + data dir folder
  2. binds CDP to the browser / tab
  3. starts screencast
  4. navigates tab to URL
  5. browser yields screencast frames
  6. writes to ffmpeg
  7. ...spec finishes...
  8. closes the browser
  9. stop screencast frames
  10. process video
  11. ...repeat steps for next spec...

Cypress Today (first spec - without video)

  1. opens browser to about:blank
  2. binds CDP to the browser / tab
  3. navigates tab to URL
  4. browser yields screencast frames
  5. ...spec finishes...
  6. closes the browser
  7. ...repeat steps for next spec...

Option 1: Closing the primary tab

Consider the experience and technical ramifications of this approach. This may not be a great user experience depending on how long these operations take.

  1. stopping the video
  2. closing the primary tab
  3. clearing the browser state
  4. clearing the server state (AUT target domain)
  5. opening a fresh tab about:blank
  6. rebinding to the fresh tab
  7. starting the video
  8. then navigating the tab to the next spec URL

Option 2: Navigating the primary tab

We'd need to have a design for /__cypress/spec-reset

  1. stopping the video
  2. navigating the primary tab to a special /__cypress/spec-reset URL
  3. clearing the browser state
  4. clearing the server state (AUT target domain)
  5. starting the video
  6. then navigating the primary tab to the next spec URL

@cypress
Copy link
Copy Markdown

cypress Bot commented Jan 26, 2022



Test summary

17929 0 211 0Flakiness 2


Run details

Project cypress
Status Passed
Commit 449dda7
Started Feb 8, 2022 2:39 PM
Ended Feb 8, 2022 2:51 PM
Duration 12:34 💡
OS Linux Debian - 10.10
Browser Multiple

View run in Cypress Dashboard ➡️


Flakiness

commands/xhr.cy.js Flakiness
1 ... > no status when request isnt forced 404
cypress/proxy-logging.cy.ts Flakiness
1 Proxy Logging > request logging > xhr log has response body/status code

This comment has been generated by cypress-bot as a result of this project's GitHub integration settings. You can manage this integration in this project's settings in the Cypress Dashboard

Comment thread packages/server/lib/browsers/protocol.ts Outdated
Comment thread packages/server/lib/open_project.ts Outdated
@ryanthemanuel
Copy link
Copy Markdown
Collaborator Author

The ordering that has seemed to work best so far for Option 1 (no intermediate url) is:

  1. Stopping the video
  2. Clearing the browser state
  3. Clearing the server state
  4. Opening a new tab directly to the new test URL
  5. Rebind CDP to the fresh tab
  6. Start the video
  7. Close the old tab

@ryanthemanuel ryanthemanuel marked this pull request as ready for review January 31, 2022 22:17
@ryanthemanuel ryanthemanuel marked this pull request as draft January 31, 2022 22:17
Comment thread system-tests/__snapshots__/deprecated_spec.ts.js
Comment thread system-tests/__snapshots__/cdp_spec.ts.js
Comment thread packages/server/lib/browsers/chrome.ts Outdated
originalBrowserKill.apply(launchedBrowser, args)
}

const criClient = await browserCriClient.attachToTargetUrl('about:blank')
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

It's not clear to me from the names what the difference is between browserCriClient and criClient.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

I have updated the names to pageCriClient to try and highlight the distinction: ab49d53

@ryanthemanuel ryanthemanuel changed the title feat: Close and reopen a new tab in between tests to get around a memory leak feat: Close and reopen a new tab in between tests to get around a memory leak. Feb 7, 2022
@ryanthemanuel ryanthemanuel changed the title feat: Close and reopen a new tab in between tests to get around a memory leak. feat: Close and reopen a new tab in between tests to get around a memory leak Feb 7, 2022
Comment thread packages/extension/test/integration/background_spec.js Outdated
Comment thread system-tests/test/deprecated_spec.ts Outdated
Comment thread system-tests/test/browser_reset_spec.js
@ryanthemanuel ryanthemanuel requested a review from flotwig February 7, 2022 23:37
flotwig
flotwig previously approved these changes Feb 7, 2022
@ryanthemanuel ryanthemanuel changed the title feat: Close and reopen a new tab in between tests to get around a memory leak feat: Close and reopen a new tab in between tests to get around a memory leak. Feb 8, 2022
@ryanthemanuel ryanthemanuel changed the title feat: Close and reopen a new tab in between tests to get around a memory leak. feat: Close and reopen a new tab in between tests to get around a memory leak Feb 8, 2022
Comment thread packages/server/lib/browsers/chrome.ts
Comment on lines +558 to +559
this._handleDownloads(pageCriClient, options.downloadsFolder, automation),
])
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

just curious, why move the navigate & download order?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Both of these can be done in parallel and aren't dependent upon the navigation to occur. It's a slight performance boost.

@flotwig flotwig changed the title feat: Close and reopen a new tab in between tests to get around a memory leak feat: Close and reopen a new tab in between tests to get around a memory leakx Feb 8, 2022
@flotwig flotwig changed the title feat: Close and reopen a new tab in between tests to get around a memory leakx feat: Close and reopen a new tab in between tests to get around a memory leak Feb 8, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants