Skip to content
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

fix(@wdio/reporter): transform scripts in TestStats (#13209) #13219

Merged
merged 12 commits into from
Aug 16, 2024

Conversation

johnp
Copy link
Contributor

@johnp johnp commented Jul 27, 2024

Proposed changes

Fixes #13209 and dequelabs/axe-core-npm#1086. Simply adds a Map which points any script string larger than 1KB at the same in-memory script instance. Now, @axe/webdriverio only leaks the script a total of three times (due whitespace differences in @axe/webdriverio), regardless of the number of Axe calls. The cutoff point at 1KB is arbitrary. I'm pretty sure we could set it higher to avoid trashing the Map too much, while still benefiting from deduplication, but I don't have any knowledge as to how big execute scripts in the ecosystem usually are, especially one's which are executed so many times, that their additive size could become problematic.

Changed to instead transform the scripts strings into short representations w/ byte count and, if easily available, the first function name (can make it easier to locate than the byte count alone).

Types of changes

  • Polish (an improvement for an existing feature)
  • Bugfix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Documentation update (improvements to the project's docs)
  • Specification changes (updates to WebDriver command specifications)
  • Internal updates (everything related to internal scripts, governance documentation and CI files)

Checklist

  • I have read the CONTRIBUTING doc
  • I have added tests that prove my fix is effective or that my feature works
  • I have added the necessary documentation (if appropriate)
  • I have added proper type definitions for new commands (if appropriate)

Backport Request

//: # (The current main branch is the development branch for WebdriverIO v9. If your change should be released to the current major version of WebdriverIO (v8), please raise another PR with the same changes against the v8 branch.)

I'd like to at least backport the fix to v8, if not the test as well.

  • Back-ported PR at #XXXXX TODO: Once this PR has been reviewed/approved.

Further comments

I wasn't entirely sure where to place the test for this, as the e2e package.json looks a bit broken (everything that's not test:browser:...), and since I needed access to the GC I just went with a separate test file, command and config. Ah, the top-level package.json has all the scripts. Went with the already pre-existing testrunner.

I chose to preserve the behavior of any custom onBeforeCommand and onAfterCommand reporter hooks. Only the internal event handler hooks do the deduplication transformation.

Reviewers: @webdriverio/project-committers

@johnp johnp force-pushed the jp/fix-reporter-mem-leak branch from 3e81415 to c15a75f Compare July 27, 2024 23:58
Copy link
Contributor Author

@johnp johnp left a comment

Choose a reason for hiding this comment

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

Short self-review; going to do some fine-tuning -> Draft.

packages/wdio-reporter/src/index.ts Outdated Show resolved Hide resolved
e2e/wdio/wdio.memory.conf.ts Outdated Show resolved Hide resolved
e2e/wdio/wdio.memory.conf.ts Outdated Show resolved Hide resolved
packages/wdio-reporter/src/index.ts Outdated Show resolved Hide resolved
@johnp johnp marked this pull request as draft July 28, 2024 10:36
@johnp johnp force-pushed the jp/fix-reporter-mem-leak branch from c15a75f to 3ac8a70 Compare July 28, 2024 18:45
@johnp johnp marked this pull request as ready for review July 28, 2024 19:00
e2e/wdio/headless/execute-leak.e2e.ts Outdated Show resolved Hide resolved
packages/wdio-reporter/src/index.ts Outdated Show resolved Hide resolved
packages/wdio-reporter/src/index.ts Outdated Show resolved Hide resolved
@christian-bromann
Copy link
Member

Thanks for taking a stab at this, added some comments.

@christian-bromann christian-bromann added the PR: Bug Fix 🐛 PRs that contain bug fixes label Aug 1, 2024
@christian-bromann
Copy link
Member

@johnp let me know if there is anything I can do to help.

@johnp
Copy link
Contributor Author

johnp commented Aug 7, 2024

@christian-bromann I think I'll be able to provide an updated version this weekend. I have a version just using a function similar to transformCommandLogResult, but the new smoke test leaks memory even with the fix, so I want to debug that first.

@johnp
Copy link
Contributor Author

johnp commented Aug 11, 2024

So, unfortunately, using a smoke test seems to be impossible due to setTimeout handlers leaking the same scripts in the mock tests. Based on the mention of requestBodyString, I think Nock is to blame for that.

In this screenshot you can see three test runs with 10 2MiB scripts (30 -> 71 MiB) and one test run with 20 2MiB scripts (30 -> 112 MiB).

fetch leak

I'll clean up, rebase and push my commits.

johnp added 3 commits August 11, 2024 23:20
To avoid leaking memory due to execution of large scripts, we transform
them for internal use, similiar to `transformCommandLogResult`. Other
registered event handlers will still receive the full scripts (we're actually
copying the `payload.body`, instead of modifying it in-place).
…-leak

* upstream/main:
  V9 ai support (webdriverio#13340)
  docs(devtools manipulation): (webdriverio#13334)
  breaking(build): migrate to Esbuild for bundling (webdriverio#13338)
  fix(@wdio/protocols): remove return value for navigateTo (webdriverio#13335)
  fix(@wdio/runner): check if getTypes is available when filtering through browser logs
  fix(@wdio/runner): filter for severe errors
  fix(@wdio/runner): retry on Outdated Optimize Dep Vite errors (webdriverio#13330)
  feat(webdriverio): new command to set viewport (webdriverio#13258)
  chore(deps): fix pnpm-lock
  chore(deps): bump vite-plugin-top-level-await from 1.4.1 to 1.4.2 (webdriverio#13282)
  fix(dependabot): fix dependabot ignore setting
  chore(testing): update Vitest to v2
  chore(sponsoring): add Route4Me to Backers.md and Readme.md
@johnp johnp changed the title fix(@wdio/reporter): deduplicate long scripts in TestStats (#13209) fix(@wdio/reporter): transform scripts in TestStats (#13209) Aug 11, 2024
johnp added 2 commits August 12, 2024 00:20
While the global static properties on `RegExp` are deprecated, they are still populated by NodeJS and it is prudent to clear them when
matching against potentially large inputs.
@johnp
Copy link
Contributor Author

johnp commented Aug 11, 2024

I've kept the two e2e tests for now, but reduced the number of iterations to 10. With that change, their runtime is comparable to the runtime of the (failing) smoke test (~3-4s locally).

johnp added 3 commits August 14, 2024 19:25
This does **not** resolve an additional memory leak
of the last request+response pair happening in the
nock interceptor. Neither abortPendingRequests, nor
cleanAll, clears that leak. Since it's only one 2MB
request+response pair, just accept it.
Copy link
Member

@christian-bromann christian-bromann left a comment

Choose a reason for hiding this comment

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

This is excellent work 👌 thanks a lot!

Mind backporting this to the v8 branch?

@johnp
Copy link
Contributor Author

johnp commented Aug 14, 2024

You're welcome. I'm glad to do some open source work for a change.

Sure, I'll backport this after I've taken a look into resolving the Nock leak on their side. I really don't see why they should hold onto finished or otherwise cleared setTimeout / setImmediate references, and the setInterval spy appears completely unused (unless it's supposed to be a public export, which it doesn't appear it is).

@christian-bromann
Copy link
Member

Awesome, I will go ahead and merge then.

@christian-bromann christian-bromann merged commit 7867ac7 into webdriverio:main Aug 16, 2024
43 of 44 checks passed
@wdio-bot
Copy link
Contributor

Hey johnp 👋

Thank you for your contribution to WebdriverIO! Your pull request has been marked as an "Expensable" contribution. We've sent you an email with further instructions on how to claim your expenses from our development fund. Please make sure to check your spam folder as well. If you have any questions, feel free to reach out to us at [email protected] or in the contributing channel on Discord.

We are looking forward to more contributions from you in the future 🙌

Have a nice day,
The WebdriverIO Team 🤖

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[🐛 Bug]: Repeated execute / executeAsync can leak large amounts of memory
3 participants