Open
Description
Version
14.17.5
Platform
All
Subsystem
No response
What steps will reproduce the bug?
See https://github.com/Brooooooklyn/node-ref-object-leak for detail
I have a js function in native side, which accept a JsBuffer
:
#[js_function(1)]
fn ref_buffer(ctx: napi::CallContext) -> napi::Result<napi::JsNumber> {
let buffer = ctx.get::<napi::JsBuffer>(0)?;
let ref_buffer = buffer.into_ref()?;
let ref_count = ref_buffer.unref(ctx.env.clone())?;
ctx.env.create_uint32(ref_count)
}
The napi_create_reference
, napi_reference_unref
and napi_delete_reference
are called in this function.
In the JavaScript side:
const { readFileSync } = require('fs')
const { refBuffer } = require('./index.node')
const { displayMemoryUsageFromNode } = require('./util')
const BigBuffer = readFileSync('yarn.lock')
const initial = process.memoryUsage()
async function main() {
for (const [i] of Array.from({ length: 10000000 }).entries()) {
let refCount = refBuffer(BigBuffer)
if (refCount) {
throw new Error(`refCount should be 0, but got ${refCount}`)
}
if (i % 1000000 === 0) {
await sleep() // Async function to give GC a chance
if (typeof global.gc === 'function') {
global.gc()
}
displayMemoryUsageFromNode(initial)
}
}
}
function sleep() {
return new Promise((resolve) => {
setTimeout(resolve, 1000)
})
}
main()
We can see the memory is growing:
╔══════════╤═══════════╤══════════╤══════════╤══════════════╗
║ rss │ heapTotal │ heapUsed │ external │ arrayBuffers ║
╟──────────┼───────────┼──────────┼──────────┼──────────────╢
║ +80.1 MB │ +80 MB │ +80 MB │ +40 B │ 0 B ║
╚══════════╧═══════════╧══════════╧══════════╧══════════════╝
╔═════════╤═══════════╤══════════╤══════════╤══════════════╗
║ rss │ heapTotal │ heapUsed │ external │ arrayBuffers ║
╟─────────┼───────────┼──────────┼──────────┼──────────────╢
║ +250 MB │ +85.3 MB │ +79 MB │ -170 kB │ -162 kB ║
╚═════════╧═══════════╧══════════╧══════════╧══════════════╝
╔═════════╤═══════════╤══════════╤══════════╤══════════════╗
║ rss │ heapTotal │ heapUsed │ external │ arrayBuffers ║
╟─────────┼───────────┼──────────┼──────────┼──────────────╢
║ +414 MB │ +85.3 MB │ +79.7 MB │ -170 kB │ -162 kB ║
╚═════════╧═══════════╧══════════╧══════════╧══════════════╝
╔═════════╤═══════════╤══════════╤══════════╤══════════════╗
║ rss │ heapTotal │ heapUsed │ external │ arrayBuffers ║
╟─────────┼───────────┼──────────┼──────────┼──────────────╢
║ +576 MB │ +85.3 MB │ +79.3 MB │ -170 kB │ -162 kB ║
╚═════════╧═══════════╧══════════╧══════════╧══════════════╝
╔═════════╤═══════════╤══════════╤══════════╤══════════════╗
║ rss │ heapTotal │ heapUsed │ external │ arrayBuffers ║
╟─────────┼───────────┼──────────┼──────────┼──────────────╢
║ +739 MB │ +85.3 MB │ +79.1 MB │ -170 kB │ -162 kB ║
╚═════════╧═══════════╧══════════╧══════════╧══════════════╝
╔═════════╤═══════════╤══════════╤══════════╤══════════════╗
║ rss │ heapTotal │ heapUsed │ external │ arrayBuffers ║
╟─────────┼───────────┼──────────┼──────────┼──────────────╢
║ +902 MB │ +85.3 MB │ +79 MB │ -170 kB │ -162 kB ║
╚═════════╧═══════════╧══════════╧══════════╧══════════════╝
╔══════════╤═══════════╤══════════╤══════════╤══════════════╗
║ rss │ heapTotal │ heapUsed │ external │ arrayBuffers ║
╟──────────┼───────────┼──────────┼──────────┼──────────────╢
║ +1.06 GB │ +85.3 MB │ +79 MB │ -170 kB │ -162 kB ║
╚══════════╧═══════════╧══════════╧══════════╧══════════════╝
╔══════════╤═══════════╤══════════╤══════════╤══════════════╗
║ rss │ heapTotal │ heapUsed │ external │ arrayBuffers ║
╟──────────┼───────────┼──────────┼──────────┼──────────────╢
║ +1.23 GB │ +85.3 MB │ +79.1 MB │ -170 kB │ -162 kB ║
╚══════════╧═══════════╧══════════╧══════════╧══════════════╝
╔══════════╤═══════════╤══════════╤══════════╤══════════════╗
║ rss │ heapTotal │ heapUsed │ external │ arrayBuffers ║
╟──────────┼───────────┼──────────┼──────────┼──────────────╢
║ +1.39 GB │ +85.3 MB │ +79 MB │ -170 kB │ -162 kB ║
╚══════════╧═══════════╧══════════╧══════════╧══════════════╝
╔══════════╤═══════════╤══════════╤══════════╤══════════════╗
║ rss │ heapTotal │ heapUsed │ external │ arrayBuffers ║
╟──────────┼───────────┼──────────┼──────────┼──────────────╢
║ +1.55 GB │ +85.3 MB │ +79 MB │ -170 kB │ -162 kB ║
╚══════════╧═══════════╧══════════╧══════════╧══════════════╝
How often does it reproduce? Is there a required condition?
Always
What is the expected behavior?
Buffer is deallocated
What do you see instead?
Buffer is never been deallocated
Activity