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

[Bug]: jest runtime drastically slows down calls to native APIs/modules/globals #15502

Open
carera opened this issue Feb 12, 2025 · 0 comments
Open

Comments

@carera
Copy link

carera commented Feb 12, 2025

Version

29.7.0

Steps to reproduce

The following snippet includes a set of example calls to native/global APIs (modules? globals objects? not sure what do you call them - Number, Math, Array), and a few simple expressions (equality check, and some multiplication) for comparison:

const ITERATIONS = 100000000

let start = Date.now();
for (let i = 0; i < ITERATIONS; i++) {
  Number.isNaN(i)
}
console.log(Date.now() - start);

start = Date.now();
for (let i = 0; i < ITERATIONS; i++) {
  Array.isArray(i);
}
console.log(Date.now() - start);

start = Date.now();
for (let i = 0; i < ITERATIONS; i++) {
  Math.max(i, i-1);
}
console.log(Date.now() - start);

start = Date.now();
for (let i = 0; i < ITERATIONS; i++) {
  i !== i
}
console.log(Date.now() - start);

start = Date.now();
for (let i = 0; i < ITERATIONS; i++) {
  i * (i-1)
}
console.log(Date.now() - start);

Running with plain NodeJS yields results within a few ms:

> node index.test.js
52
63
48
47
64

Running with jest however yields significant performance drawbacks for the native objects:

> node ./node_modules/.bin/jest index.test.js
  console.log
    11252

      at Object.<anonymous> (index.test.js:7:9)

  console.log
    11080

      at Object.<anonymous> (index.test.js:13:9)

  console.log
    11176

      at Object.<anonymous> (index.test.js:19:9)

  console.log
    48

      at Object.<anonymous> (index.test.js:25:9)

  console.log
    63

      at Object.<anonymous> (index.test.js:31:9)

This happens even when transformation and code coverage is explicitly disable via jest config:

export default {
  collectCoverage: false,
  collectCoverageFrom: [],
  transform: {},
}

Expected behavior

I expect Number.isNaN and other native APIs to run as usual

Actual behavior

Number.isNaN and other native APIs are ~20x slower within jest runtime

Additional context

I tried jest versions all the way down to jest@12, as well as [email protected], no change.

Profiling hints at _execModule in jest-runtime (that is, if node --prof captures the correct process):

   ticks parent  name
  26056   93.7%  UNKNOWN
  25262   97.0%    JS: *Object.<anonymous> .../index.test.js:1:114
  25262  100.0%      JS: ^_execModule .../node_modules/jest-runtime/build/index.js:1364:14
  25262  100.0%        JS: ^_loadModule .../node_modules/jest-runtime/build/index.js:1000:14
  25262  100.0%          JS: ^requireModule .../node_modules/jest-runtime/build/index.js:812:16
  25262  100.0%            JS: ~jestAdapter .../node_modules/jest-circus/build/legacy-code-todo-rewrite/jestAdapter.js:16:21

Assigning for example Number.isNaN to a variable and calling instead that make the code execute fast again:

const myNaN = Number.isNaN;
myNaN(3);

Environment

System:
    OS: macOS 14.7.2
    CPU: (10) arm64 Apple M1 Pro
  Binaries:
    Node: 20.11.1 - ~/Library/Caches/fnm_multishells/73147_1739329875570/bin/node
    Yarn: 1.22.21 - ~/Library/Caches/fnm_multishells/73147_1739329875570/bin/yarn
    npm: 10.2.4 - ~/Library/Caches/fnm_multishells/73147_1739329875570/bin/npm
  npmPackages:
    jest: ^29.7.0 => 29.7.0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant