Skip to content
This repository has been archived by the owner on Mar 23, 2023. It is now read-only.

Tests are leaking memory. #1629

Closed
dav1app opened this issue Jan 27, 2020 · 20 comments
Closed

Tests are leaking memory. #1629

dav1app opened this issue Jan 27, 2020 · 20 comments
Labels
Difficulty: Challenging The issue requires extensive understanding of the code base. Type: Bug The issue relates to broken or incorrect behaviour.

Comments

@dav1app
Copy link
Contributor

dav1app commented Jan 27, 2020

I've debugging this issue for some time.

Running the desktop-wallet using either --runInBand and --maxWorkers=1 result in a memory leak that ends up consuming ~4GB of RAM, forcing the usage of --max_old_space_size=4096 to run the tests. If using any inspect tools (--inspect-brk), even 4GB isn't safe to be used.

  • Using nodes --optimize-for-size and --gc-interval doesn't seem to impact the results directly.
  • Using nodes --gc-interval=1 --gc_global reduce the memory consumed by the tests, but didn't improve it well enough to fit on 2GB. It goes from 3.8GB to 2.8GB. It also makes the test run for a very long time (30~40min).
  • Chrome debugger didn't give a precise answer of who is being responsible for the leak. The biggest arrays loaded on the memory come from locales and translations. jasmine also seems to have a lot of presence there. Better analysis is needded.
  • I have created a repository with jest, jest-extended, vue, vue-template-compiler and jest-vue-preprocessor and a bunch of expect(true).toBeTruthy() to check if the handles were the ones leaking memory. They are not, the memory increased ~1MB per 20 tests. This is used as a base for improving the tests.

image

  • Tests related to Transactions seems to be the tests consuming the biggest amount of RAM. I'm testing them right now.
node --max_old_space_size=8192  --expose-gc --gc_interval=1 --gc_global ./node_modules/jest/bin/jest.js --runInBand --config __tests__/unit.jest.conf.js --logHeapUsage --no-cache --json --outputFile=testResult.json

The tests for the Transactions (partially):
image
The rest of tests:
image

  • I've also tried to change jest-vue-preprocessor to vue-test. Since it is used by more packages, I'm expecting this to be more stable than jest-vue-preprocessor, and almost no code needs to be changed. Anyway, this package is not responsible for the leak.

Expected Behavior

  • Run the tests with the default heap size (2GB) with --runInBand.

Current Behavior

  • Consuming 4GB with --runInBand.
  • Running with multiple workers (4+) uses less RAM.

Possible Solution

  • --max_old_space_size=4096. We also need to check Github Actions for more options.
  • Fixing the leak itself.

Steps to Reproduce (for bugs)

  1. Clone desktop-wallet.
  2. Run it using test:unity:band (./node_modules/jest/bin/jest.js --config __tests__/unit.jest.conf.js --runInBand. You can use --logHeapUsage to check the increasing memory consumption).
  3. See Allocation failed - JavaScript heap out of memory error.

Your Environment

  • Version used: Latest 2.6-tx-types branch. Also, since my last PR broke the tests, you can use mems branch. jest-vue-preprocessor seems to be broken.
  • Environment name and version: Node 12.12
  • Operating System and version: Debian 10
@dav1app dav1app added the Status: Needs Investigation The issue needs more investigation before it can be verified and resolved. label Jan 27, 2020
@ghost
Copy link

ghost commented Jan 27, 2020

This issue or pull request needs further investigation. Please wait for further information, thank you.

@dav1app dav1app added the Type: Bug The issue relates to broken or incorrect behaviour. label Jan 27, 2020
@dav1app
Copy link
Contributor Author

dav1app commented Jan 27, 2020

Things that can be done

  • Spend some time with the debugger.
  • Striping all the dependencies inside the Transaction and run them separately.
  • Since Objects and Arrays are the most used constructor (even when analyzing the diff between snapshots, finding where they are been used inside Transactions can lead to the leak.
  • Find out every memory consumption test and check if all of them have the same dependency.
  • Use jest clearMocks option.
  • Create a initial file that loads all the tests inside them. This way the gc will be more agressive and remove everything after one test is finished.
  • Creating an universal afterAll and afterEach inside setupFilesAfterEnv to use global.gc().

@dav1app dav1app changed the title Memory leak with tests Tests are leaking memory. Jan 27, 2020
@dav1app
Copy link
Contributor Author

dav1app commented Jan 28, 2020

After some debugging, I got the conclusion that tests themselves are leaking memory. Not the dependencies, not the setup, not anything. The answer is inside describe()

I've created a module that tracks the memory, measuring its diff and placed it inside afterEach, afterAll, beforeEach and beforeAll. It also runs inside setup.js. I also placed a function to force the garbage collector.

afterAll(() => {
  memo('afterAll > before running GC()')
  if (global.gc) {
    global.gc()
    memo('afterAll > after running GC()')
  }
})

afterEach(() => {
  memo('afterEach > before running GC()')
  if (global.gc) {
    global.gc()
    memo('afterEach > after running GC()')
  }
})

This is the log for TransactionFormMultiSignature.spec.js. See how the heap increases inside each test.

Results ``` file | console | Heap size | Delta --------------------------------------------------------------------------------------- setup.js | loaded after dependencies | 332.05 MB | 332.05 MB setup.js | before setting up Vue | 332.07 MB | 0.02 MB setup.js | last sync line | 332.18 MB | 0.11 MB setup-env.js | loaded | 344.42 MB | 12.24 MB setup-env.js | afterEach > before running GC() | 387.90 MB | 43.48 MB setup-env.js | afterEach > after running GC() | 356.60 MB | -31.30 MB setup-env.js | afterEach > before running GC() | 362.58 MB | 5.98 MB setup-env.js | afterEach > after running GC() | 357.27 MB | -5.31 MB setup-env.js | afterEach > before running GC() | 360.93 MB | 3.66 MB setup-env.js | afterEach > after running GC() | 358.38 MB | -2.55 MB setup-env.js | afterEach > before running GC() | 361.98 MB | 3.60 MB setup-env.js | afterEach > after running GC() | 359.66 MB | -2.32 MB setup-env.js | afterEach > before running GC() | 363.27 MB | 3.61 MB setup-env.js | afterEach > after running GC() | 360.62 MB | -2.65 MB setup-env.js | afterEach > before running GC() | 364.93 MB | 4.31 MB setup-env.js | afterEach > after running GC() | 361.94 MB | -2.99 MB setup-env.js | afterEach > before running GC() | 367.70 MB | 5.76 MB setup-env.js | afterEach > after running GC() | 364.01 MB | -3.69 MB setup-env.js | afterEach > before running GC() | 373.68 MB | 9.67 MB setup-env.js | afterEach > after running GC() | 367.70 MB | -5.98 MB setup-env.js | afterEach > before running GC() | 378.03 MB | 10.33 MB setup-env.js | afterEach > after running GC() | 371.32 MB | -6.71 MB setup-env.js | afterEach > before running GC() | 381.40 MB | 10.08 MB setup-env.js | afterEach > after running GC() | 374.85 MB | -6.55 MB setup-env.js | afterEach > before running GC() | 380.58 MB | 5.73 MB setup-env.js | afterEach > after running GC() | 376.40 MB | -4.18 MB setup-env.js | afterEach > before running GC() | 382.00 MB | 5.60 MB setup-env.js | afterEach > after running GC() | 378.28 MB | -3.72 MB setup-env.js | afterEach > before running GC() | 388.23 MB | 9.95 MB setup-env.js | afterEach > after running GC() | 382.22 MB | -6.01 MB setup-env.js | afterEach > before running GC() | 387.76 MB | 5.54 MB setup-env.js | afterEach > after running GC() | 383.66 MB | -4.10 MB setup-env.js | afterEach > before running GC() | 387.11 MB | 3.45 MB setup-env.js | afterEach > after running GC() | 384.66 MB | -2.45 MB setup-env.js | afterEach > before running GC() | 388.50 MB | 3.84 MB setup-env.js | afterEach > after running GC() | 385.80 MB | -2.70 MB setup-env.js | afterEach > before running GC() | 391.74 MB | 5.94 MB setup-env.js | afterEach > after running GC() | 388.01 MB | -3.73 MB setup-env.js | afterEach > before running GC() | 391.51 MB | 3.50 MB setup-env.js | afterEach > after running GC() | 389.17 MB | -2.34 MB setup-env.js | afterEach > before running GC() | 392.49 MB | 3.32 MB setup-env.js | afterEach > after running GC() | 390.04 MB | -2.45 MB setup-env.js | afterEach > before running GC() | 394.10 MB | 4.06 MB setup-env.js | afterEach > after running GC() | 391.45 MB | -2.65 MB setup-env.js | afterEach > before running GC() | 395.50 MB | 4.05 MB setup-env.js | afterEach > after running GC() | 392.74 MB | -2.76 MB setup-env.js | afterEach > before running GC() | 396.06 MB | 3.32 MB setup-env.js | afterEach > after running GC() | 393.84 MB | -2.22 MB setup-env.js | afterEach > before running GC() | 397.16 MB | 3.32 MB setup-env.js | afterEach > after running GC() | 394.93 MB | -2.23 MB setup-env.js | afterEach > before running GC() | 399.29 MB | 4.36 MB setup-env.js | afterEach > after running GC() | 396.13 MB | -3.16 MB setup-env.js | afterEach > before running GC() | 400.67 MB | 4.54 MB setup-env.js | afterEach > after running GC() | 397.44 MB | -3.23 MB setup-env.js | afterEach > before running GC() | 401.95 MB | 4.51 MB setup-env.js | afterEach > after running GC() | 398.53 MB | -3.42 MB setup-env.js | afterEach > before running GC() | 402.76 MB | 4.23 MB setup-env.js | afterEach > after running GC() | 399.70 MB | -3.06 MB setup-env.js | afterEach > before running GC() | 404.67 MB | 4.97 MB setup-env.js | afterEach > after running GC() | 401.07 MB | -3.60 MB setup-env.js | afterEach > before running GC() | 406.19 MB | 5.12 MB setup-env.js | afterEach > after running GC() | 402.60 MB | -3.59 MB setup-env.js | afterEach > before running GC() | 407.77 MB | 5.17 MB setup-env.js | afterEach > after running GC() | 403.82 MB | -3.95 MB setup-env.js | afterEach > before running GC() | 408.72 MB | 4.90 MB setup-env.js | afterEach > after running GC() | 405.21 MB | -3.51 MB setup-env.js | afterEach > before running GC() | 408.91 MB | 3.70 MB setup-env.js | afterEach > after running GC() | 406.39 MB | -2.52 MB setup-env.js | afterEach > before running GC() | 409.91 MB | 3.52 MB setup-env.js | afterEach > after running GC() | 407.43 MB | -2.48 MB setup-env.js | afterEach > before running GC() | 413.34 MB | 5.91 MB setup-env.js | afterEach > after running GC() | 409.72 MB | -3.62 MB setup-env.js | afterEach > before running GC() | 415.51 MB | 5.79 MB setup-env.js | afterEach > after running GC() | 411.71 MB | -3.80 MB setup-env.js | afterEach > before running GC() | 415.21 MB | 3.50 MB setup-env.js | afterEach > after running GC() | 412.69 MB | -2.52 MB setup-env.js | afterEach > before running GC() | 416.80 MB | 4.11 MB setup-env.js | afterEach > after running GC() | 413.93 MB | -2.87 MB setup-env.js | afterEach > before running GC() | 418.03 MB | 4.10 MB setup-env.js | afterEach > after running GC() | 415.05 MB | -2.98 MB setup-env.js | afterEach > before running GC() | 418.52 MB | 3.47 MB setup-env.js | afterEach > after running GC() | 416.14 MB | -2.38 MB setup-env.js | afterEach > before running GC() | 419.98 MB | 3.84 MB setup-env.js | afterEach > after running GC() | 417.25 MB | -2.73 MB setup-env.js | afterEach > before running GC() | 421.06 MB | 3.81 MB setup-env.js | afterEach > after running GC() | 418.43 MB | -2.63 MB setup-env.js | afterEach > before running GC() | 421.70 MB | 3.27 MB setup-env.js | afterEach > after running GC() | 419.67 MB | -2.03 MB setup-env.js | afterEach > before running GC() | 425.85 MB | 6.18 MB setup-env.js | afterEach > after running GC() | 421.81 MB | -4.04 MB setup-env.js | afterEach > before running GC() | 428.02 MB | 6.21 MB setup-env.js | afterEach > after running GC() | 423.89 MB | -4.13 MB setup-env.js | afterEach > before running GC() | 427.59 MB | 3.70 MB setup-env.js | afterEach > after running GC() | 424.98 MB | -2.61 MB setup-env.js | afterEach > before running GC() | 428.71 MB | 3.73 MB setup-env.js | afterEach > after running GC() | 426.21 MB | -2.50 MB setup-env.js | afterEach > before running GC() | 429.89 MB | 3.68 MB setup-env.js | afterEach > after running GC() | 427.33 MB | -2.56 MB setup-env.js | afterEach > before running GC() | 430.99 MB | 3.66 MB setup-env.js | afterEach > after running GC() | 428.52 MB | -2.47 MB setup-env.js | afterEach > before running GC() | 431.82 MB | 3.30 MB setup-env.js | afterEach > after running GC() | 429.56 MB | -2.26 MB setup-env.js | afterEach > before running GC() | 435.74 MB | 6.18 MB setup-env.js | afterEach > after running GC() | 431.88 MB | -3.86 MB setup-env.js | afterEach > before running GC() | 435.85 MB | 3.97 MB setup-env.js | afterEach > after running GC() | 433.07 MB | -2.78 MB setup-env.js | afterEach > before running GC() | 439.50 MB | 6.43 MB setup-env.js | afterEach > after running GC() | 435.44 MB | -4.06 MB setup-env.js | afterEach > before running GC() | 438.89 MB | 3.45 MB setup-env.js | afterEach > after running GC() | 436.28 MB | -2.61 MB setup-env.js | afterEach > before running GC() | 439.71 MB | 3.43 MB setup-env.js | afterEach > after running GC() | 437.46 MB | -2.25 MB setup-env.js | afterEach > before running GC() | 440.73 MB | 3.27 MB setup-env.js | afterEach > after running GC() | 438.34 MB | -2.39 MB setup-env.js | afterEach > before running GC() | 442.58 MB | 4.24 MB setup-env.js | afterEach > after running GC() | 439.50 MB | -3.08 MB setup-env.js | afterEach > before running GC() | 444.04 MB | 4.54 MB setup-env.js | afterEach > after running GC() | 440.67 MB | -3.37 MB setup-env.js | afterEach > before running GC() | 444.63 MB | 3.96 MB setup-env.js | afterEach > after running GC() | 441.76 MB | -2.87 MB setup-env.js | afterEach > before running GC() | 446.04 MB | 4.28 MB setup-env.js | afterEach > after running GC() | 442.96 MB | -3.08 MB setup-env.js | afterEach > before running GC() | 447.16 MB | 4.20 MB setup-env.js | afterEach > after running GC() | 444.04 MB | -3.12 MB setup-env.js | afterEach > before running GC() | 448.26 MB | 4.22 MB setup-env.js | afterEach > after running GC() | 445.21 MB | -3.05 MB setup-env.js | afterEach > before running GC() | 449.83 MB | 4.62 MB setup-env.js | afterEach > after running GC() | 446.72 MB | -3.11 MB setup-env.js | afterEach > before running GC() | 451.51 MB | 4.79 MB setup-env.js | afterEach > after running GC() | 447.86 MB | -3.65 MB setup-env.js | afterEach > before running GC() | 452.62 MB | 4.76 MB setup-env.js | afterEach > after running GC() | 449.12 MB | -3.50 MB setup-env.js | afterEach > before running GC() | 452.85 MB | 3.73 MB setup-env.js | afterEach > after running GC() | 450.33 MB | -2.52 MB setup-env.js | afterEach > before running GC() | 453.73 MB | 3.40 MB setup-env.js | afterEach > after running GC() | 451.35 MB | -2.38 MB setup-env.js | afterEach > before running GC() | 454.61 MB | 3.26 MB setup-env.js | afterEach > after running GC() | 452.40 MB | -2.21 MB setup-env.js | afterEach > before running GC() | 457.66 MB | 5.26 MB setup-env.js | afterEach > after running GC() | 454.31 MB | -3.35 MB setup-env.js | afterEach > before running GC() | 459.61 MB | 5.30 MB setup-env.js | afterEach > after running GC() | 456.10 MB | -3.51 MB setup-env.js | afterEach > before running GC() | 459.73 MB | 3.63 MB setup-env.js | afterEach > after running GC() | 457.18 MB | -2.55 MB setup-env.js | afterEach > before running GC() | 460.79 MB | 3.61 MB setup-env.js | afterEach > after running GC() | 458.28 MB | -2.51 MB setup-env.js | afterEach > before running GC() | 462.82 MB | 4.54 MB setup-env.js | afterEach > after running GC() | 459.62 MB | -3.20 MB setup-env.js | afterEach > before running GC() | 464.01 MB | 4.39 MB setup-env.js | afterEach > after running GC() | 461.11 MB | -2.90 MB setup-env.js | afterEach > before running GC() | 465.65 MB | 4.54 MB setup-env.js | afterEach > after running GC() | 462.21 MB | -3.44 MB setup-env.js | afterEach > before running GC() | 466.16 MB | 3.95 MB setup-env.js | afterEach > after running GC() | 463.34 MB | -2.82 MB setup-env.js | afterEach > before running GC() | 467.06 MB | 3.72 MB setup-env.js | afterEach > after running GC() | 464.43 MB | -2.63 MB setup-env.js | afterEach > before running GC() | 468.35 MB | 3.92 MB setup-env.js | afterEach > after running GC() | 465.59 MB | -2.76 MB setup-env.js | afterEach > before running GC() | 469.12 MB | 3.53 MB setup-env.js | afterEach > after running GC() | 466.77 MB | -2.35 MB setup-env.js | afterEach > before running GC() | 470.23 MB | 3.46 MB setup-env.js | afterEach > after running GC() | 467.71 MB | -2.52 MB setup-env.js | afterEach > before running GC() | 471.13 MB | 3.42 MB setup-env.js | afterEach > after running GC() | 468.76 MB | -2.37 MB setup-env.js | afterEach > before running GC() | 472.22 MB | 3.46 MB setup-env.js | afterEach > after running GC() | 469.83 MB | -2.39 MB setup-env.js | afterEach > before running GC() | 473.41 MB | 3.58 MB setup-env.js | afterEach > after running GC() | 470.95 MB | -2.46 MB setup-env.js | afterEach > before running GC() | 477.39 MB | 6.44 MB setup-env.js | afterEach > after running GC() | 473.34 MB | -4.05 MB setup-env.js | afterEach > before running GC() | 476.77 MB | 3.43 MB setup-env.js | afterEach > after running GC() | 474.23 MB | -2.54 MB setup-env.js | afterEach > before running GC() | 477.52 MB | 3.29 MB setup-env.js | afterEach > after running GC() | 475.36 MB | -2.16 MB setup-env.js | afterEach > before running GC() | 478.66 MB | 3.30 MB setup-env.js | afterEach > after running GC() | 476.41 MB | -2.25 MB setup-env.js | afterEach > before running GC() | 479.71 MB | 3.30 MB setup-env.js | afterEach > after running GC() | 477.51 MB | -2.20 MB setup-env.js | afterEach > before running GC() | 480.81 MB | 3.30 MB setup-env.js | afterEach > after running GC() | 478.63 MB | -2.18 MB setup-env.js | afterEach > before running GC() | 481.91 MB | 3.28 MB setup-env.js | afterEach > after running GC() | 479.76 MB | -2.15 MB setup-env.js | afterEach > before running GC() | 483.08 MB | 3.32 MB setup-env.js | afterEach > after running GC() | 480.89 MB | -2.19 MB setup-env.js | afterEach > before running GC() | 484.54 MB | 3.65 MB setup-env.js | afterEach > after running GC() | 482.05 MB | -2.49 MB setup-env.js | afterAll > before running GC() | 482.12 MB | 0.07 MB setup-env.js | afterAll > after running GC() | 481.88 MB | -0.24 MB ```

@alexbarnsley
Copy link
Member

I've been looking at this for the past few hours also. I think the main cause of the increase in memory usage is due to vue components not being removed from memory, even when component.destroy() is called. The best example test is __tests__/unit/components/Transaction/TransactionForm/TransactionFormBusiness/mixin.spec.js which increases mem usage to ~330mb from 111 tests. Removing the call to createWrapper which mounts the components, mem usage drops to ~130mb.

I could be wrong about this, but that's my current line of thinking right now.

I also noticed the same thing you did, empty tests increase memory. I couldn't figure out the specific cause after changing config or setup.

@dav1app
Copy link
Contributor Author

dav1app commented Jan 29, 2020

One way of testing that is using an empty repository with the minimum requirements for tests and just try mounting and unmounting components programmatically.

  • Check if the vue component itself is the cause.
  • Check if the dependency is the cause.
  • Check if the gc() cleans the createWrapper content after.
  • Check intl and i18n inside the createWrapper and inside the component itself. Those variables constantly show up inside the debugger using a lot of RAM and I wasn't able to find if they are causing the leak.

@dav1app
Copy link
Contributor Author

dav1app commented Jan 29, 2020

Here is the garbageman module that I am using to debug the leak. See if it can help. Will create a package after this.

garbageman.js

let lastHeap = 0

module.exports = (scope) => {
  return function (msg) {
    const heap = (process.memoryUsage().heapUsed / 1024 / 1024).toFixed(2)
    const diffHeap = (heap - lastHeap).toFixed(2)
    console.log(`${scope} ${'\t'}| ${msg} ${'\t'}| ${heap} MB ${'\t'}| ${diffHeap} MB ${'\t'}`)
    lastHeap = heap
  }
}

setup-after-env.js

const garbageman = require('./garbageman.js')('setup-after-env.js')

garbageman('loaded') 

afterAll(() => {
  garbageman('afterAll > before running GC()')
  if (global.gc) {
    global.gc()
   garbageman('afterAll > after running GC()')
  }
})

afterEach(() => {
  garbageman('afterEach > before running GC()')
  if (global.gc) {
    global.gc()
    garbageman('afterEach > after running GC()')
  }
})

unit.jest.conf.js

module.exports = {
   //...
   setupFilesAfterEnv: [
      '<rootDir>/__tests__/unit/__utils__/setup-after-env.js'
   ]
   //...
}

@dav1app
Copy link
Contributor Author

dav1app commented Jan 29, 2020

So, I programmatically added a heapdump on afterEach to track down who is leaking memory. It took a long time to debug a very small number of tests.

This is the difference between 2 tests, after gc(). The result should be nothing.

image

Almost all of the (object.proprieties)[] are comming from VueComponent $root and $parant. The class is also retaining a lot of memory.

So, as you find out yesterday, this was caused by the VueComponent class.

  • Try to shallowMount everywhere.
  • Try to use vm.$destroy() on localVue.
  • Update @vue/test-utilsto beta 31 because of this.

@dav1app
Copy link
Contributor Author

dav1app commented Jan 30, 2020

Issue related to breaking changes of beta 31: vuejs/vue-test-utils#1137

@brenopolanski
Copy link
Contributor

brenopolanski commented Jan 31, 2020

I did some tests to try to reduce the memory leak problem using the destroy() function of @vue/test-utils to remove the instance of the Vue component.

Example of using the destroy() function:

let wrapper = null

beforeEach(() => {
  wrapper = shallowMount(Rating, {
    propsData: {
      maxStars: 6
    }
  })
})

afterEach(() => {
  wrapper.destroy()
})

describe('Rating', () => {
  //
  // …
}

Source: https://vue-test-utils.vuejs.org/api/wrapper/#destroy

However, there was no considerable decrease in memory consumption. See the results below:

Tests without using the destroy() function

Results
#  ./node_modules/jest/bin/jest.js --config __tests__/unit.jest.conf.js --logHeapUsage --runInBand --no-cache
 PASS  __tests__/unit/mixins/currency.spec.js (80 MB heap size)
 PASS  __tests__/unit/pages/Profile/ProfileAll.spec.js (19.098s, 377 MB heap size)
 PASS  __tests__/unit/mixins/wallet.spec.js (386 MB heap size)
 PASS  __tests__/unit/components/utils/merge-table-transactions.spec.js (167 MB heap size)
 PASS  __tests__/unit/components/utils/Sorting.spec.js (173 MB heap size)
 PASS  __tests__/unit/pages/Wallet/WalletAll.spec.js (202 MB heap size)
 PASS  __tests__/unit/mixins/qr.spec.js (212 MB heap size)
 PASS  __tests__/unit/mixins/formatter.spec.js (221 MB heap size)
 PASS  __tests__/unit/pages/Wallet/WalletNew.spec.js (252 MB heap size)
 PASS  __tests__/unit/components/utils/WebFrame.spec.js (267 MB heap size)
 PASS  __tests__/unit/components/AlertMessage.spec.js (279 MB heap size)
 PASS  __tests__/unit/components/ListDivided.spec.js (284 MB heap size)
 PASS  __tests__/unit/components/Collapse.spec.js (295 MB heap size)
 PASS  __tests__/unit/components/Button/ButtonSwitch.spec.js (300 MB heap size)
 PASS  __tests__/unit/pages/PluginManager/PluginManager.spec.js (330 MB heap size)
 PASS  __tests__/unit/pages/Contact/ContactNew.spec.js (349 MB heap size)
 PASS  __tests__/unit/mixins/strings.spec.js (353 MB heap size)
 PASS  __tests__/unit/components/Button/ButtonGeneric.spec.js (380 MB heap size)
 PASS  __tests__/unit/components/Button/ButtonLetter.spec.js (391 MB heap size)
 PASS  __tests__/unit/components/Button/ButtonReload.spec.js (403 MB heap size)
 PASS  __tests__/unit/components/Button/ButtonClose.spec.js (404 MB heap size)
 PASS  __tests__/unit/components/SvgIcon.spec.js (414 MB heap size)

 ... and the heap increases inside each test

Tests using the destroy() function

Results
#  ./node_modules/jest/bin/jest.js --config __tests__/unit.jest.conf.js --logHeapUsage --runInBand --no-cache
 PASS  __tests__/unit/mixins/currency.spec.js (80 MB heap size)
 PASS  __tests__/unit/pages/Profile/ProfileAll.spec.js (16.032s, 370 MB heap size)
 PASS  __tests__/unit/mixins/wallet.spec.js (391 MB heap size)
 PASS  __tests__/unit/components/utils/merge-table-transactions.spec.js (165 MB heap size)
 PASS  __tests__/unit/components/utils/Sorting.spec.js (172 MB heap size)
 PASS  __tests__/unit/pages/Wallet/WalletAll.spec.js (203 MB heap size)
 PASS  __tests__/unit/mixins/qr.spec.js (213 MB heap size)
 PASS  __tests__/unit/mixins/formatter.spec.js (223 MB heap size)
 PASS  __tests__/unit/pages/Wallet/WalletNew.spec.js (253 MB heap size)
 PASS  __tests__/unit/components/utils/WebFrame.spec.js (260 MB heap size)
 PASS  __tests__/unit/components/ListDivided.spec.js (274 MB heap size)
 PASS  __tests__/unit/components/Collapse.spec.js (285 MB heap size)
 PASS  __tests__/unit/components/AlertMessage.spec.js (298 MB heap size)
 PASS  __tests__/unit/components/Button/ButtonSwitch.spec.js (302 MB heap size)
 PASS  __tests__/unit/pages/PluginManager/PluginManager.spec.js (332 MB heap size)
 PASS  __tests__/unit/pages/Contact/ContactNew.spec.js (353 MB heap size)
 PASS  __tests__/unit/mixins/strings.spec.js (356 MB heap size)
 PASS  __tests__/unit/components/Button/ButtonGeneric.spec.js (383 MB heap size)
 PASS  __tests__/unit/components/Button/ButtonLetter.spec.js (394 MB heap size)
 PASS  __tests__/unit/components/Button/ButtonReload.spec.js (397 MB heap size)
 PASS  __tests__/unit/components/Button/ButtonClose.spec.js (408 MB heap size)
 PASS  __tests__/unit/components/SvgIcon.spec.js (418 MB heap size)

 ... and the heap increases inside each test yet

@dav1app
Copy link
Contributor Author

dav1app commented Jan 31, 2020

I also ran beta-31 and adjusted some tests. Beta-31 doesn't seem to solve the problem either. 😞

@brenopolanski
Copy link
Contributor

I've debugging this issue using chrome debugger for Node.

There are references in the memory for Vue components that aren't unmount.

Steps to reproduce:

  1. To do that, start tests with debugging enabled with: node --inspect-brk --expose-gc ./node_modules/jest/bin/jest.js --config __tests__/unit.jest.conf.js --runInBand --logHeapUsage. That will pause the tests when they first start and wait for you to attach the Chrome debugger.
  2. Open up Chrome and go to chrome://inspect in the address bar.
  3. Click on Open dedicated DevTools for Node to open the debugger.
  4. From the Sources tab, click the Play icon in the top right to Resume script execution. You will now see the Jest console begin running the tests. You can also pause the script execution with the Pause icon to stop Jest.
  5. After allowing the tests to run for a bit to build up memory we’ll take a heap snapshot.
  6. Go to Memory tab.
  7. Take heap snapshots.

@dav1app
Copy link
Contributor Author

dav1app commented Feb 3, 2020

According to this (most specific this), we should not place variables inside the describe().

@dav1app
Copy link
Contributor Author

dav1app commented Feb 3, 2020

Jest 22 had an option to --detectLeaks .Check this out!

@dav1app
Copy link
Contributor Author

dav1app commented Feb 3, 2020

Well...

image

  • Check for async operations that didn't finished.
  • Check for timers that are not properly mocked.
  • Remove references in the global scope.
  • --detectLeaks doesn't work.

@brenopolanski
Copy link
Contributor

brenopolanski commented Feb 3, 2020

Jest 22 had an option to --detectLeaks.Check this out!

Just an update:

Using the Jest 25 its necessary to install the weak-napi(to use --detectLeaks) as a project dependency.

@dav1app
Copy link
Contributor Author

dav1app commented Feb 3, 2020

According to --detectLeaks this test:

describe('MemoryLeakTest', function () {
  it('should should do nothing', function () {
    expect(true).toBeTruthy()
  })
})

executed with ./node_modules/jest/bin/jest.js --detectLeaks leaks memory.

Is jest leaking memory? No setup was included, nothing.

This is getting weird.

@dav1app
Copy link
Contributor Author

dav1app commented Feb 3, 2020

Another possible related issue here.

@dav1app dav1app added the Difficulty: Challenging The issue requires extensive understanding of the code base. label Feb 3, 2020
@dav1app
Copy link
Contributor Author

dav1app commented Feb 3, 2020

GitLab runs a similar stack for the tests.

desktop-walllet GitLab
jest@25.1.0 jest@24.8.0
jest-vue-preprocessor@1.5.0 vue-jest@4.0.0-beta.2

@alexbarnsley
Copy link
Member

I've also raised an issue with Jest here. Very basic tests seem to keep/hold on to memory, the results can be seen in this repo

@ghost ghost removed the Status: Needs Investigation The issue needs more investigation before it can be verified and resolved. label Jun 18, 2020
@faustbrian
Copy link
Contributor

Closing, no longer relevant for 3.0

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Difficulty: Challenging The issue requires extensive understanding of the code base. Type: Bug The issue relates to broken or incorrect behaviour.
Projects
None yet
Development

No branches or pull requests

4 participants