vin*_*ent 7 optimization profiling garbage-collection node.js
目前正在致力于优化库的速度。我已经通过 Webstorm 使用V8 CPU 和内存分析大幅缩短了执行时间。这主要是通过将核心方法从递归改为迭代来实现的。
现在自我时间分布分解为
我假设第一个条目“节点”正在计时内部函数调用,这很棒。其他条目也有道理。我是 Nodejs 分析的新手,但 GC 的 31.6% 似乎很高,所以我决定进行调查。
我现在已经通过 Webstorm 创建了一个堆转储,但不幸的是,这并没有给我提供太多信息。
这些似乎主要是系统内部存储器引用。再次单步查看核心迭代代码逻辑,似乎也没有很多显式分配内存的地方(以此作为参考)。
问题
设置说明
如果有人想尝试调试这个,我将提供设置说明。
下载或克隆对象扫描并运行
yarn install --frozen-lockfile
yarn run test-simple --verbose
Run Code Online (Sandbox Code Playgroud)
test.js现在在项目根目录中创建一个包含此内容的文件,并运行node --trace_gc test.js或通过 Webstorm 运行它以进行高级分析。
在 Javascript 和 v8(节点)中,尤其是垃圾收集所花费的时间取决于堆中存储的数据量,但这只是众多因素之一。
在 v8 引擎中,GC 有两种主要“类型”:次要(scavenge)和主要(mark-sweep/mark-compact)。您可能会在启用的控制台中看到测试期间发生的 GC 类型--trace-gc。在不同的情况下,一种类型可能比另一种类型“吃”更多的时间,反之亦然。因此,在优化之前,您应该确定哪个 gc 花费更多时间。
优化主要 GC 的选项并不多,因为它受到内存中“长时间”保留的数据量(实际上在这种情况下,长时间意味着对象在清理 GC 中幸存下来)的影响很大。这些数据存储在堆中所谓的“旧空间”中。主要 GC 处理这个空间,它应该扫描所有内存并标记不再有任何引用的对象以进行进一步清理。
在您的情况下,您正在加载的测试数据量会转到旧空间。因此,它会影响整个测试期间的主要GC。在这种情况下,主要 GC 不会清除太多,因为您正在使用测试对象,但它仍然消耗时间来扫描整个旧空间。因此,您可以考虑通过启动具有 gc 特定标志的节点来阻止 v8 这样做,例如:(--nouse-idle-notification --expose-gc --gc_interval=100500其中 100500 是分配数量,它可以取较高的值,这将阻止在整个测试通过之前运行 gc),这将允许触发垃圾手动采集。使用这种方法测试您的代码,看看主要 GC 如何影响它,尝试使用您提供给函数的不同数据量进行测试。如果影响非常高,您可以尝试重构代码,尽量减少长期存在的变量、闭包等。
如果您发现 Major GC 对性能没有太大影响,那么 scavenge GC 会花费大部分时间。与Major GC 不同的是,它在堆中使用所谓的“新空间”进行操作。这是存储所有新对象的空间。如果这些物体在清理中幸存下来,那么它们就会被转移到旧空间。新空间的大小比旧空间小得多(您可以通过设置来控制它--max_semi_space_size,注意:)new space size = 2 * semi space size,并且您分配的新对象和变量会更多,并且会发生更多清理GC运行。如果此 GC 过多地提高性能,您可以考虑重构代码以减少新的分配。但是,如果您重用变量,它也可能会降低性能,并且这些对象将进入旧空间,并可能成为“主要 GC”部分中描述的问题。
此外,v8 GC 并不总是在程序运行的同一线程中工作。它也在后台做了一些工作,但我不知道 Webstorm 在你的案例中显示了什么。如果只计算 GC 所花费的总时间,可能不会产生太大的影响。您可以在这篇博文中找到有关 v8 GC 的更多详细信息。
长话短说:
GC开销可以减少吗?
这个分配量是预期的吗?
是否可以获得更好的内存分析信息?
| 归档时间: |
|
| 查看次数: |
6065 次 |
| 最近记录: |