Skip to content
This repository has been archived by the owner on Dec 1, 2021. It is now read-only.

Should it be destoyed when Promise.resolve is invoked? #16

Open
cmershen1 opened this issue May 13, 2019 · 15 comments
Open

Should it be destoyed when Promise.resolve is invoked? #16

cmershen1 opened this issue May 13, 2019 · 15 comments

Comments

@cmershen1
Copy link

when the resolve function is invoked, the promiseResolve callback function will be called.
I used your library in my project, and got memory leak in the end.
I think the reason is promiseResolve isn't handled. Am I right?

@vicanso
Copy link
Owner

vicanso commented May 13, 2019

Promises are destroyed by gc, so the data of promise will be removed later, which is similar to the situation you mention. I raise a example below, if your problem hasn't been solved, please show me you code.

node --expose-gc test.js
const als = require('async-local-storage');

als.enable();

setTimeout(() => {
  new Promise((resolve) => {
    als.set("a", 1);
    resolve();
  }).then(() => {
    als.set("b", 1);
    // getAllData is supported in version 2.2.0
    console.dir(als.getAllData());
    return Promise.resolve();
  })
})

setTimeout(() => {
  console.dir(als.getAllData());
  global.gc();
}, 1000)
setTimeout(() => {
  console.dir(als.getAllData());
}, 2000);

@vicanso
Copy link
Owner

vicanso commented May 20, 2019

@cmershen1 Has the problem you mentioned been solved?

@cmershen1
Copy link
Author

cmershen1 commented May 22, 2019

@cmershen1 Has the problem you mentioned been solved?

my question has not been solved yet.
I checked my code again and again, can this usage cause memory leak?

exports.query = function(sql, data=[]) {
    const traceid = ALS.get('__traceid');
    const start = ALS.get('__start');

	return new Promise((resolve, reject)=>{
		pool.query(sql, data, (err, results, fields) => {
            ALS.set('__traceid', traceid);
            ALS.set('__start', start);
                        
			if (err) {
				reject(err);
			} else {
				resolve(results);
			}
		});
	});
}

@cmershen1
Copy link
Author

I tried to print the map, the output is like this:
2019-05-22 17:21:13|25634|INFO|app.js:40|1184,{"created":[1558516873,924536775],"parent":{"created":[1558516871,925288429],"parent":{"created":[1558516869,924660300],"parent":{"created":[1558516867,924269489],"parent":{"created":[1558516865,923400076],"parent":{"created":[1558516863,922600607],"parent":{"created":[1558516861,922927699],"parent":{"created":[1558516859,922768321],"parent":{"created":[1558516857,921752524],"parent":{"created":[1558516855,920830227],"parent":{"created":[1558516853,921297443],"parent":{"created":[1558516851,921274300],"parent":{"created":[1558516849,920369574],"parent":{"created":[1558516847,919384971],"parent":{"created":[1558516845,918546701],"parent":{"created":[1558516843,918050732],"parent":{"created":[1558516841,918103027],"parent":{"created":[1558516839,917946609],"parent":{"created":[1558516837,917317481],"parent":{"created":[1558516835,917083043],"parent":{"created":[1558516833,917044200],"parent":{"created":[1558516831,914159696],"parent":{"created":[1558516829,913760412],"parent":{"created":[1558516827,912996596],"parent":{"created":[1558516825,912413567],"parent":{"created":[1558516823,912186882],"parent":{"created":[1558516821,912223413],"parent":{"created":[1558516819,912218556],"parent":{"created":[1558516817,912167310],"parent":{"created":[1558516815,911406521]}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}

and the layer becomes more and more deeper.

@vicanso
Copy link
Owner

vicanso commented May 22, 2019

It seem abnormal and I found that each item of data you shown 2ms deviated. Did you use setInterval ?

Can you please show me complete and operational codes, otherwise I can't help you.

@cmershen1
Copy link
Author

It seem abnormal and I found that each item of data you shown 2ms deviated. Did you use setInterval ?

Can you please show me complete and operational codes, otherwise I can't help you.

my server runs on the rpc framework Tars, and my business code doesn't use setInterval anywhere.
whatever, I don't know the details on how the rpc framework works clearly.

maybe we can find some clues in :
https://github.com/tars-node/rpc
https://github.com/tars-node/Tars.js
https://github.com/tars-node/monitor

@vicanso
Copy link
Owner

vicanso commented May 23, 2019

You can use scope function to create a new scope.

@cmershen1
Copy link
Author

cmershen1 commented May 23, 2019

You can use scope function to create a new scope.

how to use scope? I use ALS.scope() in the starting of every RPC function implements. and I use ALS.enable() in app.js when my service starts.

I use scope like the codes below. then I will show my pseudo code as a demo:

app.js:

const FooBarImp = require('FooBarImp');
global.ALS = require('async-local-storage');

ALS.enable();

...
...
createServer(FooBarImp);

FooBarImp.js:

FooBarImp.prototype.function1 = function(req, rsp) {
       ALS.scope();
       ALS.set('traceid', req.traceid);
       ALS.set('start', Date.now());
       // then 业务逻辑 of function1
       sendResponse(rsp);
};

FooBarImp.prototype.function2 = function(req, rsp) {
       ALS.scope();
       ALS.set('traceid', req.traceid);
       ALS.set('start', Date.now());
       // then 业务逻辑 of function2
       sendResponse(rsp);
};

@vicanso
Copy link
Owner

vicanso commented May 27, 2019

Yes, you can use scope function in the starting of each RPC call.

@ebrahimiaval
Copy link

ebrahimiaval commented Mar 9, 2020

@vicanso
I have such a problem with the project,have memory leak.
you can clone my repository
run:
1- npm i
2- npm run dev

then go to '~/src/render/server/server.js' and check my code.

if you run 'als.map()' see in each time map It gets bigger.
if you write 'console.log(req.url)' see only one time this function run.
search 'als.set()' and 'als.get()' over project to see usage.

@vicanso
Copy link
Owner

vicanso commented Mar 10, 2020

Try to call gc like this commemt.

@ebrahimiaval
Copy link

ebrahimiaval commented Mar 10, 2020

Try to call gc like this commemt.

if i use GC in high traffic ,am I not mistaken by run gc and cleanup memory between other Express request.

i have another problem. in first run (node v12.10.0, npm 6.11.3) have this error:

(node:896) UnhandledPromiseRejectionWarning: TypeError: Cannot convert undefined or null to object
    at Object.scope (C:\Users\Mohammad\Documents\RSSR\dist\webpack:\node_modules\async-local-storage\als.js:234:1)
    at _callee$ (C:\Users\Mohammad\Documents\RSSR\dist\webpack:\src\render\server\server.js:16:13)

@ebrahimiaval
Copy link

ebrahimiaval commented Mar 10, 2020

Try to call gc like this commemt.

it has error
(node:896) UnhandledPromiseRejectionWarning: TypeError: global.gc is not a function

@ebrahimiaval
Copy link

i back to pass down way and remove async-local-storage because have more memory leak.

@vicanso
Copy link
Owner

vicanso commented Mar 11, 2020

The map gets bigger may be not memory leak. Some data will be removed after gc, so you should check the map after gc. If you want to use global.gc, the application should be run like this:

node --expose-gc app.js

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants