-
-
Notifications
You must be signed in to change notification settings - Fork 1.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
Severe performance regression when reporter with terminal output is enabled #2602
Comments
Reproduction: I'm able to reproduce this on a different computer (M1) with a barebones project setup. Enabling console reporters seems to introduce some sort of O(n^2) or worse performance profile scaling with the number of tests. Surprised this hasn't been noted/filed before, the degradation is quite stark and seems to be a showstopper above a few thousand tests. Will edit the initial issue on my other account (adam-te) later today. |
Looked into this a bit more.
My take:
|
Reporters are running in the main thread, while tests are running in separate workers. |
Well that's odd, because the tests do not appear to continue to run unimpeded when console output is sufficiently slow. Test execution slows down commensurately with console rendering time. You can replicate the problem easily with my repo above and observe for yourself (at least on macOS with default shell) Any comment or opinion on the issue generally? |
Does test execution actually slows down, or does reporters shows them like they are slowed down? It's possible RPC call is awaited somewhere, when console log is happening, so tests are slowed down, but I'm not sure if this is actually the problem. |
Well you can clone my repo above and replicate it within 5m. Test execution slows down, yes, and pretty much completely broken performance wise after 5000 tests or so. Running 1000 tests with expect(true).toBe(true) is close to instant. Running 5000 tests with the same takes 30s or more. It's not a linear scaling at all, there appears to be some O(n^2) or worse slowdown corresponding with the number of tests This is not a minor performance issue, vitest is unusable beyond a few thousand tests with these reporters. You can tweak the number of generated tests in the repo by changing a variable to check the scaling behavior |
With your reproduction I don't see significant performance regression in |
It affects all of the reporters that act to clear the terminal/contain layout logic. I'll get numbers for it soon, but surprised you didn't observe this. The extent to which performance degrades depends on the specific reporter. As stated in other comments, the CI reporter which seems to only append/not clear is order of magnitudes faster for large number of tests. If I had the time to focus on this I would:
|
Pushed an update to: https://github.com/adam-arthur/vitest-perf-regression You can now observe that So just tweaked the expects to trigger slowness in verbose as well. The other reporters seem fine, though I recall even vitest UI being slow on my work testcases... may have been running it along with a slower console reporter though. Will investigate that later to see if can reproduce |
I'm working on a perf fix to: chalk/wrap-ansi Main problem lines are: |
See: chalk/wrap-ansi#51 for fix on that side. |
In addition to chalk/wrap-ansi#51 some optimization on Vitest side is needed. When there are lots of test cases the vitest/packages/vitest/src/node/reporters/renderers/listRenderer.ts Lines 163 to 165 in 1fe8286
The Video of slow renderTree callsrender-tree-slow.movBy limiting the - renderTree(tasks, options)
+ const rows = process.stdout.rows || 80
+ renderTree(tasks.slice(tasks.length - rows), options) Video of fast reduced renderTree callsrender-tree-limit-tasks.movBut if we still need to print all tasks to terminal on each Also maybe the vitest/packages/vitest/src/node/reporters/renderers/listRenderer.ts Lines 174 to 178 in 1fe8286
Changes for showing the execution time of renderTree in listRenderer.tsexport const createListRenderer = (_tasks: Task[], options: ListRendererOptions) => {
let tasks = _tasks
let timer: any
const log = options.logger.logUpdate
let timeSpentOnUpdate = 0n
let lastLog = 0n
let lastRenderTree = 0n
function update() {
const rows = process.stdout.rows || 80
const start = process.hrtime.bigint()
const tree = renderTree(
// tasks,
tasks.slice(tasks.length - rows),
options,
)
lastRenderTree = (process.hrtime.bigint() - start) / 1_000_000n
log(
tree,
'\nTotal time spent on update() calls:', timeSpentOnUpdate.toString(),
'ms\nLast update() took:', lastLog.toString(),
'ms\nLast renderTree() took:', lastRenderTree.toString(),
'ms\nCount of tasks:', tasks.length.toString(),
)
lastLog = (process.hrtime.bigint() - start) / 1_000_000n
timeSpentOnUpdate += lastLog
}
return { |
Not sure if this is the right solution, but the idea is nice. I don't think we can slice it before passing it down, because it's possible to have more than 1 line for a task. But maybe an early return from a |
Using early I'll do some more manual testing and see if the |
Describe the bug
Problem:
Full test suite performance is 10x slower when enabling a reporter with terminal output (e.g.
default
,verbose
,dot
).Details:
In converting our unit tests (~8000) from karma to vitest I noticed performance of vitest was significantly worse than karma. After a lot of debugging, I came to find that the
wrapAnsi(
function call, used in the vitestlog-update
dependency, was the culprit. This call alone takes ~95% of test execution time.https://github.com/sindresorhus/log-update/blob/main/index.js#L54
Workaround:
Tests run 10-20x faster if the wrapAnsi line in the
vitest/dist/chunk-snapshot-manager.js
file is commented out. Console output continues to look normal and functional with ansi wrapping disabledVitest entrypoint into
log-update
dependency:https://github.com/vitest-dev/vitest/blob/main/packages/vitest/src/node/logger.ts#L13
Thoughts:
Its bizarre that terminal output logic is reducing test performance by an order of magnitude. Ideally the performance would be optimized here, but perhaps terminal logic can be moved to a worker/sub-process?
Reproduction
TODO: Will add soon. Should be able to reproduce on any large test suite via enabling/disabling
default
ordot
reporter though.System Info
Used Package Manager
npm
Validations
The text was updated successfully, but these errors were encountered: