Closed dav1app closed 4 years ago
This issue or pull request needs further investigation. Please wait for further information, thank you.
Things that can be done
Transaction
and run them separately.Transactions
can lead to the leak. clearMocks
option. gc
will be more agressive and remove everything after one test is finished. afterAll
and afterEach
inside setupFilesAfterEnv
to use global.gc()
. 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.
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.
One way of testing that is using an empty repository with the minimum requirements for tests and just try mounting and unmounting components programmatically.
gc()
cleans the createWrapper
content after.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. 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
```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: [
'
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.
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.
shallowMount
everywhere.~vm.$destroy()
on localVue
.~@vue/test-utils
to beta 31 because of this.Issue related to breaking changes of beta 31: https://github.com/vuejs/vue-test-utils/issues/1137
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
Tests using the destroy()
function
I also ran beta-31
and adjusted some tests. Beta-31 doesn't seem to solve the problem either. :disappointed:
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:
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.chrome://inspect
in the address bar.Open dedicated DevTools for Node
to open the debugger.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.Memory
tab.Jest 22 had an option to --detectLeaks
.Check this out!
Well...
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.
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.
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 |
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
Closing, no longer relevant for 3.0
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.--optimize-for-size
and--gc-interval
doesn't seem to impact the results directly.--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).jasmine
also seems to have a lot of presence there. Better analysis is needded.jest
,jest-extended
,vue
,vue-template-compiler
andjest-vue-preprocessor
and a bunch ofexpect(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.Transactions
seems to be the tests consuming the biggest amount of RAM. I'm testing them right now.The tests for the Transactions (partially): The rest of tests:
jest-vue-preprocessor
tovue-test
. Since it is used by more packages, I'm expecting this to be more stable thanjest-vue-preprocessor
, and almost no code needs to be changed. Anyway, this package is not responsible for the leak.Expected Behavior
--runInBand
.Current Behavior
--runInBand
.Possible Solution
--max_old_space_size=4096
. We also need to check Github Actions for more options.Steps to Reproduce (for bugs)
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).Allocation failed - JavaScript heap out of memory
error.Your Environment
2.6-tx-types
branch. Also, since my last PR broke the tests, you can usemems
branch.jest-vue-preprocessor
seems to be broken.