Skip to content
Vitest 3
Main Navigation Guide & APIConfigBrowser ModeAdvanced API
3.2.0
2.1.9
1.6.1
0.34.6

English

简体中文
繁體中文
Español
Français
Русский
Português – Brasil
Deutsch
日本語
한국어
Italiano
Polski
Türkçe
čeština
magyar

English

简体中文
繁體中文
Español
Français
Русский
Português – Brasil
Deutsch
日本語
한국어
Italiano
Polski
Türkçe
čeština
magyar

Appearance

Sidebar Navigation

Introduction

Why Vitest

Getting Started

Features

Config Reference

API

Test API Reference

Mock Functions

Vi Utility

Expect

ExpectTypeOf

Assert

AssertType

Guides

CLI

Test Filtering

Test Projects

Reporters

Coverage

Snapshot

Mocking

Parallelism

Testing Types

Vitest UI

In-Source Testing

Test Context

Test Annotations

Environment

Extending Matchers

IDE Integration

Debugging

Common Errors

Migration Guide

Migrating to Vitest 3.0

Migrating from Jest

Performance

Profiling Test Performance

Improving Performance

Browser Mode

Node API Reference

Comparisons

On this page

Profiling Test Performance ​

When you run Vitest it reports multiple time metrics of your tests:

bash
RUN  v2.1.1 /x/vitest/examples/profiling

✓ test/prime-number.test.ts (1) 4517ms
  ✓ generate prime number 4517ms

Test Files  1 passed (1)
     Tests  1 passed (1)
  Start at  09:32:53
  Duration  4.80s (transform 44ms, setup 0ms, collect 35ms, tests 4.52s, environment 0ms, prepare 81ms)
  # Time metrics ^^
  • Transform: How much time was spent transforming the files. See File Transform.
  • Setup: Time spent for running the setupFiles files.
  • Collect: Time spent for collecting all tests in the test files. This includes the time it took to import all file dependencies.
  • Tests: Time spent for actually running the test cases.
  • Environment: Time spent for setting up the test environment, for example JSDOM.
  • Prepare: Time Vitest uses to prepare the test runner.

Test runner ​

In cases where your test execution time is high, you can generate a profile of the test runner. See NodeJS documentation for following options:

  • --cpu-prof
  • --heap-prof
  • --prof

WARNING

The --prof option does not work with pool: 'threads' due to node:worker_threads limitations.

To pass these options to Vitest's test runner, define poolOptions.<pool>.execArgv in your Vitest configuration:

ts
import { defineConfig } from 'vitest/config';

export default defineConfig({
  test: {
    pool: 'forks',
    poolOptions: {
      forks: {
        execArgv: [
          '--cpu-prof',
          '--cpu-prof-dir=test-runner-profile',
          '--heap-prof',
          '--heap-prof-dir=test-runner-profile',
        ],

        // To generate a single profile
        singleFork: true,
      },
    },
  },
});
ts
import { defineConfig } from 'vitest/config';

export default defineConfig({
  test: {
    pool: 'threads',
    poolOptions: {
      threads: {
        execArgv: [
          '--cpu-prof',
          '--cpu-prof-dir=test-runner-profile',
          '--heap-prof',
          '--heap-prof-dir=test-runner-profile',
        ],

        // To generate a single profile
        singleThread: true,
      },
    },
  },
});

After the tests have run there should be a test-runner-profile/*.cpuprofile and test-runner-profile/*.heapprofile files generated. See Inspecting profiling records for instructions how to analyze these files.

See Profiling | Examples for example.

Main thread ​

Profiling main thread is useful for debugging Vitest's Vite usage and globalSetup files. This is also where your Vite plugins are running.

TIP

See Performance | Vite for more tips about Vite specific profiling.

We recommend vite-plugin-inspect for profiling your Vite plugin performance.

To do this you'll need to pass arguments to the Node process that runs Vitest.

bash
$ node --cpu-prof --cpu-prof-dir=main-profile ./node_modules/vitest/vitest.mjs --run
#      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^                                  ^^^^^
#               NodeJS arguments                                           Vitest arguments

After the tests have run there should be a main-profile/*.cpuprofile file generated. See Inspecting profiling records for instructions how to analyze these files.

File transform ​

In cases where your test transform and collection time is high, you can use DEBUG=vite-node:* environment variable to see which files are being transformed and executed by vite-node.

bash
$ DEBUG=vite-node:* vitest --run

 RUN  v2.1.1 /x/vitest/examples/profiling

  vite-node:server:request /x/vitest/examples/profiling/global-setup.ts +0ms
  vite-node:client:execute /x/vitest/examples/profiling/global-setup.ts +0ms
  vite-node:server:request /x/vitest/examples/profiling/test/prime-number.test.ts +45ms
  vite-node:client:execute /x/vitest/examples/profiling/test/prime-number.test.ts +26ms
  vite-node:server:request /src/prime-number.ts +9ms
  vite-node:client:execute /x/vitest/examples/profiling/src/prime-number.ts +9ms
  vite-node:server:request /src/unnecessary-file.ts +6ms
  vite-node:client:execute /x/vitest/examples/profiling/src/unnecessary-file.ts +4ms
...

This profiling strategy is a good way to identify unnecessary transforms caused by barrel files. If these logs contain files that should not be loaded when your test is run, you might have barrel files that are importing files unnecessarily.

You can also use Vitest UI to debug slowness caused by barrel file. The example below shows how importing files without barrel file reduces amount of transformed files by ~85%.

├── src
│   └── utils
│       ├── currency.ts
│       ├── formatters.ts  <-- File to test
│       ├── index.ts
│       ├── location.ts
│       ├── math.ts
│       ├── time.ts
│       └── users.ts
├── test
│   └── formatters.test.ts
└── vitest.config.ts
ts
import { expect, test } from 'vitest';
import { formatter } from '../src/utils'; 
import { formatter } from '../src/utils/formatters'; 

test('formatter works', () => {
  expect(formatter).not.toThrow();
});
Vitest UI demonstrating barrel file issues

To see how files are transformed, you can use VITE_NODE_DEBUG_DUMP environment variable to write transformed files in the file system:

bash
$ VITE_NODE_DEBUG_DUMP=true vitest --run

[vite-node] [debug] dump modules to /x/examples/profiling/.vite-node/dump

 RUN  v2.1.1 /x/vitest/examples/profiling
...

$ ls .vite-node/dump/
_x_examples_profiling_global-setup_ts-1292904907.js
_x_examples_profiling_test_prime-number_test_ts-1413378098.js
_src_prime-number_ts-525172412.js

Code coverage ​

If code coverage generation is slow on your project you can use DEBUG=vitest:coverage environment variable to enable performance logging.

bash
$ DEBUG=vitest:coverage vitest --run --coverage

 RUN  v3.1.1 /x/vitest-example

  vitest:coverage Reading coverage results 2/2
  vitest:coverage Converting 1/2
  vitest:coverage 4 ms /x/src/multiply.ts
  vitest:coverage Converting 2/2
  vitest:coverage 552 ms /x/src/add.ts
  vitest:coverage Uncovered files 1/2
  vitest:coverage File "/x/src/large-file.ts" is taking longer than 3s
  vitest:coverage 3027 ms /x/src/large-file.ts
  vitest:coverage Uncovered files 2/2
  vitest:coverage 4 ms /x/src/untested-file.ts
  vitest:coverage Generate coverage total time 3521 ms

This profiling approach is great for detecting large files that are accidentally picked by coverage providers. For example if your configuration is accidentally including large built minified Javascript files in code coverage, they should appear in logs. In these cases you might want to adjust your coverage.include and coverage.exclude options.

Inspecting profiling records ​

You can inspect the contents of *.cpuprofile and *.heapprofile with various tools. See list below for examples.

  • Speedscope
  • Performance Profiling JavaScript in Visual Studio Code
  • Profile Node.js performance with the Performance panel | developer.chrome.com
  • Memory panel overview | developer.chrome.com
Pager
Previous pageMigration Guide
Next pageImproving Performance

Released under the MIT License.

Copyright (c) 2021-Present Vitest Team

https://vitest.dev/guide/profiling-test-performance

Released under the MIT License.

Copyright (c) 2021-Present Vitest Team