Node.js Nodejs内存管理
我开始学习Nodejs并试图理解它管理内存的方式。 我知道有一种东西叫做“GC”(垃圾收集器) 我尝试使用Express JS编写以下小代码:Node.js Nodejs内存管理,node.js,memory-management,memory-leaks,garbage-collection,Node.js,Memory Management,Memory Leaks,Garbage Collection,我开始学习Nodejs并试图理解它管理内存的方式。 我知道有一种东西叫做“GC”(垃圾收集器) 我尝试使用Express JS编写以下小代码: const express = require('express') const app = express() const port = 3000 app.get('/', (req, res) => { res.send('Hello World!') let used = process.memoryUsage().heap
const express = require('express')
const app = express()
const port = 3000
app.get('/', (req, res) => {
res.send('Hello World!')
let used = process.memoryUsage().heapUsed / 1024 / 1024;
console.log(`The script uses approximately ${Math.round(used * 100) / 100} MB`);
})
app.get('/a', (req, res) => {
var array = Array(1e7).fill("a");
delete array;
let used = process.memoryUsage().heapUsed / 1024 / 1024;
console.log(`The script uses approximately ${Math.round(used * 100) / 100} MB`);
res.send('Hello World!')
})
app.listen(port, () => {
console.log(`Example app listening at http://localhost:${port}`)
})
我增加了两条路线。
第一条路径没有什么特别的,只是一段代码,用来打印内存使用量
在第二条路径中,我创建了一个巨大的数组,然后删除它
我叫第一条路线。我得到:
脚本使用大约5.87 MB
然后我呼叫第二条路线,我得到:
脚本大约使用82.2MB
然后我刷新第一条路线,我得到:
脚本大约使用4.36 MB
然后我再次刷新第二条路线。我得到:
该脚本使用大约80.6MB
从现在起,无论我刷新第一条路线多少次,我都会得到:
脚本使用大约80.65 MB
我知道“delete”关键字只会破坏引用,并不能立即释放内存
但是GC呢?它在做什么?
我等待了10多分钟,尝试了第一条路线,结果几乎相同(>80MB)
有人能解释为什么记忆没有减少吗?
感谢您的帮助大型对象总是属于“垃圾收集”的第2代,这就是为什么即使没有引用,此类对象也比小型对象“存活”更长的原因
除了
删除数组
您可以执行array.length=0代码>之前。大型对象总是属于“垃圾收集”的第2代,这就是为什么即使没有引用,此类对象也比小型对象“存活”更长的原因
除了删除数组
您可以执行array.length=0代码>预先删除。删除
用于从对象中删除属性。它不是用来删除局部变量的-它不是这样做的。。请参阅此以了解详细信息。如果希望数组符合垃圾收集的条件,请将局部变量设置为null
。@jfriend00当函数完成执行并清除堆栈帧时,该数组无论如何都应该是可GC的,因为它没有在其他任何地方被引用。@VLAZ-是的,这不是这个问题的内容。OP试图测量即时内存使用量的变化,这种变化在delete
或将其设置为null
时不会发生,因为GC不是这样工作的。我以前的注释末尾应该有“立即”一词,但遗憾的是,我不能再编辑该注释了。@jfriend00场景是,最终调用了第一条路由,但堆内存似乎仍被数组使用,该数组仅在处理第二条路由时才存在。如果它在2小时内仍然存在,这可能是一个度量问题,而不是内存使用问题。内存可能仍属于进程,但可用于恢复。如果在两次请求之间间隔几秒钟运行同一请求1000次,服务器内存使用是否会在每次请求时不断增加,并在完成所有操作后保持非常高的使用率。delete
用于从对象中删除属性。它不是用来删除局部变量的-它不是这样做的。。请参阅此以了解详细信息。如果希望数组符合垃圾收集的条件,请将局部变量设置为null
。@jfriend00当函数完成执行并清除堆栈帧时,该数组无论如何都应该是可GC的,因为它没有在其他任何地方被引用。@VLAZ-是的,这不是这个问题的内容。OP试图测量即时内存使用量的变化,这种变化在delete
或将其设置为null
时不会发生,因为GC不是这样工作的。我以前的注释末尾应该有“立即”一词,但遗憾的是,我不能再编辑该注释了。@jfriend00场景是,最终调用了第一条路由,但堆内存似乎仍被数组使用,该数组仅在处理第二条路由时才存在。如果它在2小时内仍然存在,这可能是一个度量问题,而不是内存使用问题。内存可能仍属于进程,但可用于恢复。如果在两次请求之间间隔几秒钟运行同一个请求1000次,服务器内存使用是否会在每次请求时不断增加,并在完成所有操作后保持非常高的使用率。array=null
会更好<代码>删除数组
根本不删除局部变量<代码>删除
用于从对象中删除属性,而不是删除局部变量delete
在本例中无法尝试释放局部变量使用的内存。对于局部变量,通常无需执行任何操作(如果它们不存储非托管资源)。同意,无需执行任何操作。那么,为什么您要说“除了删除数组;
之外,您还可以执行array.length=0;
”?当第一个什么都不做,第二个在这里是不需要的。最终,这个问题需要通过深入研究垃圾收集的时间以及process.memoryUsage().heapUsed
报告来解释。这个问题的答案绝对与delete array
或array.length=0
有关。这就是我的观点。我只是忘记了无用的delete somevar
。我的错。我只是认为array.length=0
可以帮助更快地释放内存。@jfriend00正如我在问题中提到的,我知道delete
不能立即释放内存。我也尝试了array=null
。但我的问题是,为什么这个未使用的变量会存在很长时间?为什么GD不收集它?array=null
会更好<代码>删除数组根本不删除局部变量<代码>删除用于删除pro