Storybook: Storyshots is leaking memory

Created on 26 Mar 2018  路  9Comments  路  Source: storybookjs/storybook

Bug or support request summary

Bug

Steps to reproduce

See https://github.com/SimenB/storyshots-leak for example, but every single installation of storyshots (at least for React, haven't tested others) should reproduce without issue following the steps in the linked README.

To satisfy template:

  1. Install and setup storyshots
  2. Run jest
  3. See leakage either through Jest's builtin capabilities (logHeapUsage and detectLeaks) or using some OS tool to see memory usage.

Please specify which version of Storybook and optionally any affected addons that you're running

"@storybook/addon-storyshots": "^3.3.15",
"@storybook/react": "^3.3.15",

Affected platforms

Screenshots / Screencast / Code Snippets (Optional)

image

(A bonus would be to remove the info => Loading custom .babelrc text...)

P2 storyshots help wanted performance issue todo

Most helpful comment

I've ran into this issue too and while waiting for the fix, we fixed it by mocking @storybook/core/server. This solution was inspired by https://github.com/storybookjs/storybook/issues/3286#issuecomment-595011324 Thank you @jrmurad

jest.mock('@storybook/core/server', () => ({ toRequireContext: require('@storybook/core/dist/server/preview/to-require-context').toRequireContext }));

Also here is a great article that helped me a lot finding memory leaks : https://chanind.github.io/javascript/2019/10/12/jest-tests-memory-leak.html

All 9 comments

I think we have narrowed down where the leak is. Our project has 198 test suites and we see large increase for each one with node --expose-gc ./node_modules/.bin/jest --runInBand --logHeapUsage. When stubbing out initStoryshots with no-op test, the leak is ~45mb per test suite.

We eliminated that (and had tests running same as usual) by commenting out lines in node_modules/@storybook/core/server.js:

const defaultWebpackConfig = require('./dist/server/preview/base-webpack.config');
const serverUtils = require('./dist/server/utils/template');
//const buildStatic = require('./dist/server/build-static');
//const buildDev = require('./dist/server/build-dev');
const toRequireContext = require('./dist/server/preview/to-require-context');

const managerPreset = require.resolve('./dist/server/manager/manager-preset');

module.exports = {
  managerPreset,
  ...defaultWebpackConfig,
  //...buildStatic,
  //...buildDev,
  ...serverUtils,
  ...toRequireContext,
};

We're on 5.3.14.

Before (machine has 64gb RAM):

node --expose-gc ./node_modules/.bin/jest --runInBand --logHeapUsage
 PASS  a (9.709s, 252 MB heap size)
 PASS  b (5.631s, 362 MB heap size)
 PASS  c (437 MB heap size)
...
 PASS  x (1937 MB heap size)
 PASS  y (5.015s, 1962 MB heap size)
 RUNS  z

<--- Last few GCs --->

[14445:0x5127f60]   117729 ms: Mark-sweep 1986.7 (2074.5) -> 1973.7 (2076.5) MB, 466.6 / 0.8 ms  (average mu = 0.246, current mu = 0.227) allocation failure scavenge might not succeed
[14445:0x5127f60]   118383 ms: Mark-sweep 1989.2 (2077.5) -> 1974.9 (2079.5) MB, 467.9 / 0.7 ms  (average mu = 0.264, current mu = 0.285) allocation failure scavenge might not succeed


<--- JS stacktrace --->

==== JS stack trace =========================================

    0: ExitFrame [pc: 0x145ce19]
Security context: 0x271be7b40921 <JSObject>
    1: _execModule [0x3187af0ba299] [.../node_modules/@jest/core/node_modules/jest-runtime/build/index.js:~936] [pc=0x64bf4aa52dc](this=0x1a8368f186e1 <Runtime map = 0x1c6ac7f12d21>,0x17f756364109 <Object map = 0x9dbcc75c5f1>,0x213632f004b9 <undefined>,0x1a8368f18a61 <Map map = 0x357ddfac0f31>,0x31ee342896e1 <String[#98]: ...

FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed - JavaScript heap out of memory

After:

node --expose-gc ./node_modules/.bin/jest --runInBand --logHeapUsage
 PASS  a (9.377s, 241 MB heap size)
 PASS  b (5.489s, 225 MB heap size)
 PASS  c (294 MB heap size)
...

This is now causing issues for our workflow as well. We were unable to upgrade our storybook dependencies (including storyshots) from version 5.2.6 to 5.3.18 as our jest run would just fail with memory allocation errors.

We had the same problem and fixed it for us by separating our storyshots by folder into different testsuites. We accomplished this by creating separate Storyshot files and using the storyKindRegex to only snapshot a specific subset of stories in each file.

I've ran into this issue too with Storybook. Had my storybook open for a few days working on my own design system and it ended up eating up 19GB of ram (well my computer doesn't have that much ram so of course it swapping). On a Mac with the latest OS updates and using the MDX plugin too.

I've ran into this issue too and while waiting for the fix, we fixed it by mocking @storybook/core/server. This solution was inspired by https://github.com/storybookjs/storybook/issues/3286#issuecomment-595011324 Thank you @jrmurad

jest.mock('@storybook/core/server', () => ({ toRequireContext: require('@storybook/core/dist/server/preview/to-require-context').toRequireContext }));

Also here is a great article that helped me a lot finding memory leaks : https://chanind.github.io/javascript/2019/10/12/jest-tests-memory-leak.html

@vidal7 do you know what the proper storyshots fix would be for that?

@shilman, I think so. Maybe just changing in this file (addons/storyshots/storyshots-core/src/frameworks/configure.ts) a import. So

Change
import { toRequireContext } from '@storybook/core/server';

To
const toRequireContext = require('../../../core/dist/server/preview/to-require-context');

I think it will work. The problem is that importing toRequireContext from '@storybook/core/server'; imports too much things in addons/storyshots/storyshots-core/src/frameworks/configure.js. Because of typescript compilation to javascript, the first import is compiled to var server_1 = require("@storybook/core/server"); in @storybook/addon-storyshots/dist/frameworks/configure.js

Oof that's pretty ugly though. @ndelangen @tmeasday WDYT about a little refactoring here?

This might work:

import { toRequireContext } from '@storybook/core/dist/server/preview/to-require-context';

?

Was this page helpful?
0 / 5 - 0 ratings

Related issues

purplecones picture purplecones  路  3Comments

shilman picture shilman  路  3Comments

levithomason picture levithomason  路  3Comments

zvictor picture zvictor  路  3Comments

wahengchang picture wahengchang  路  3Comments