-
Notifications
You must be signed in to change notification settings - Fork 154
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
Memory leak when isolate is passed to the Sandbox context #510
Comments
Try: let ivm = require('isolated-vm');
async function run() {
while (true) {
{
let isolate = new ivm.Isolate;
let context = isolate.createContextSync();
let jail = context.global;
jail.setSync('isolate', isolate);
isolate.compileScriptSync(`
isolate.compileScriptSync('1');
// nb: This doesn't work and I cannot explain it
// delete globalThis.isolate;
`);
jail.deleteSync('isolate');
context.evalSync('gc()');
context.release();
gc();
const memoryUsage = process.memoryUsage();
const rssMemory = Math.round(memoryUsage.rss / 1024 / 1024);
console.log(`RSS memory: ${rssMemory} MB`);
}
await new Promise(resolve => setTimeout(resolve, 10));
}
}
run().catch(console.error); It is strange that deleting the reference from inside the isolate doesn't work. Anyway, it is easy to create circular references between isolates in this manner. v8 cannot detect those. It is certainly best to dispose the isolate explicitly if you're going to give an isolate its own handle. |
Debugging this I think I have found a separate issue. Technically if you only create Isolate instances with some memory allocated in them, the GC in the main isolate never runs. RUN AS let ivm = require('isolated-vm');
async function run() {
setInterval(() => {
const memoryUsage = process.memoryUsage();
const rssMemory = Math.round(memoryUsage.rss / 1024 / 1024);
console.log(`RSS memory: ${rssMemory} MB`);
}, 1000);
while (true) {
{
let isolate = new ivm.Isolate;
let context = isolate.createContextSync();
const allocatedSize = 10 * 1024 * 1024;
context.evalSync(`
const data = new ArrayBuffer(${allocatedSize});
globalThis.data = data;
const view = new Uint8Array(data);
view.fill(123);
void 0;
`);
}
await new Promise(resolve => setTimeout(resolve, 10));
}
}
run().catch(console.error);
If you run it, it only ever does I think the problem might be in how IVM reports allocated memory. Because I can see only RSS grow, but not external memory, which if I understand it correctly should grow as well. |
The two garbage collectors run independently of one and other. You need to dispose of isolates when you are done with them otherwise you will run into memory issues. |
Overview
I suspect the Isolate referenced in itself is never garbage collected. I have even tried calling
jail.deleteSync('isolate')
, but without any change.Calling
isolate.dispose()
of course works.Personal Diagnostics
Please answer the following questions:
JavaScript includes a
setTimeout
function:Functions are a type of primitive value in JavaScript:
Objects can be shared between isolates:
The Code
main.mjs
and then runnode main.mjs
.The text was updated successfully, but these errors were encountered: