【发布时间】:2015-01-01 01:44:59
【问题描述】:
我目前正在开展一个项目,该项目使用 node.js 作为控制系统,对图像进行一些相对大规模的机器学习。尽管我正在尝试尽可能优化使用并且我的数据不应该占用过多的空间,但我在尝试执行此操作时很快就会耗尽内存。我的代码严重依赖承诺和匿名函数来管理管道,我想知道这是否是我在测试用例中看到疯狂高使用率的原因。
仅出于上下文考虑,我使用 mnist 数据集进行测试,可以在 here 找到。训练集由 60,000 张 20x20 图像组成。从这些我提取过分特征,可以找到对此的描述here。这归结为每个图像有一个 4,096 个元素的数组,所以其中有 60,000 个。我在 redis 中缓存所有图像和特征数据。
快速计算告诉我,这里的全部功能集应该是4096 * 8 * 60000 = 1966080000 字节或 appx 1.82GB 内存,假设数组的每个元素都是 64 位 JavaScript 数字。图像本身应该只占用非常小的空间,我不会将它们存储在内存中。但是,当我运行我的代码时,我看到提取/加载后使用的内存更像是 8-10GB。当尝试对这些数据执行更多操作时(例如将其全部打印到 JSON 文件中,以便确保提取正常),我很快消耗了计算机上 16GB 的可用内存,导致节点脚本崩溃。
所以我的一般问题是:为什么我看到如此高的内存使用率?是因为我大量使用了承诺/闭包吗?我可以重构我的代码以使用更少的内存并允许更多的变量被垃圾回收吗?
代码可通过here 查阅。请注意,就组织而言,这有点粗糙。
【问题讨论】:
-
为什么你
throw所有错误,而不是拒绝各自的承诺?这可能会导致永远未决的承诺,而这确实会占用内存。 -
另外,我可以发现deferred antipatttern,这可能会导致类似的错误。
-
使用适当的库,可以将 JSON“流式传输”到文件中,这是一种内存高效的方式来写出大型 JSON 结构,而不是在内存中转换整个 JSON。我在小小的 Raspberry Pi 中编写节点应用程序,所以我必须考虑这种事情。
-
您正在使用一个非常缓慢的承诺实现。考虑将 bluebird 用于性能敏感的承诺工作。
-
@BenjaminGruenbaum 我肯定会改用蓝鸟,我会更新它的进展情况。
标签: javascript node.js memory-management closures promise