GC 占用预期运行时间的 32%?

GC taking 32% of runtime expected?

目前正在优化库以提高速度。我已经大大减少了执行时间,使用 V8 CPU and Memory Profiling through Webstorm. This was achieved mainly by changing the core method from recursive to iterative.

现在自拍时间分布分解为

我假设第一个条目 "node" 是计时内部函数调用,这很好。其他条目也有意义。我是 Nodejs 分析的新手,但 GC 的 31.6% 似乎很高,所以我决定调查一下。

我现在已经通过 Webstorm 创建了一个堆转储,但不幸的是,这并没有给我太多信息。

这些好像主要是系统内存引用。步步走核心iteration code logic again, there also don't seem to be a lot of places where memory is explicitly allocated (using this作为参考)。

问题

设置说明

如果有人想尝试调试它,我会提供安装说明。

下载或克隆 object-scan 和 运行

yarn install --frozen-lockfile
yarn run test-simple --verbose

现在在项目根目录中创建一个文件test.js包含this content和运行node --trace_gc test.js或运行它通过Webstorm进行高级分析。

在 Javascript 和 v8(节点)中,特别是垃圾收集所花费的时间取决于堆中存储的数据量,但这只是众多因素之一。

在 v8 引擎中有两个主要的 "types" GC:minor (scavenge) 和 major (mark-sweep/mark-compact)。您可能会在启用 --trace-gc 的控制台中看到测试期间发生的 GC 类型。在不同的情况下,一种类型可能比另一种类型 "eat" 更多时间,反之亦然。所以在优化之前你应该确定哪个gc需要更多的时间。

没有太多优化主要 GC 的选项,导致它受保留在内存中 "long"(实际上在这种情况下很长意味着对象在清除 GC 中幸存)期间的数据量的影响很大。此类数据存储在堆中所谓的 "old space" 中。主要 GC 使用此 space,它应该扫描所有内存并标记不再有任何引用的对象以供进一步清除。

在您的情况下,您正在加载的测试数据量变为旧 space。因此,它会影响整个测试期间的主要 GC。在这种情况下,主要 GC 不会清除太多,因为你正在使用你的测试对象,但它仍然会消耗时间来扫描整个旧 space。因此,您可以考虑通过启动带有 gc 特定标志的节点来防止 v8 执行此操作,例如:--nouse-idle-notification --expose-gc --gc_interval=100500(其中 100500 是分配数量,它可以采用高值来防止 运行 gc 在整个测试将通过),这将允许手动触发垃圾收集。使用这种方法测试你的代码,看看主要的 GC 是如何影响它的,尝试使用你提供的不同数据量进行测试。如果影响不大,您可以尝试重构您的代码,尽量减少长期变量、闭包等。

如果你会发现major GC对性能影响不大,那么scavenge GC占用的时间最多。与主要 GC 不同,它在堆中使用所谓的 "new space" 进行操作。这是一个 space 存储所有新对象的地方。如果这些对象在清除后幸存下来,那么它们将被移动到旧 space。新 space 的大小(您可以通过设置 --max_semi_space_size 来控制它,注意:new space size = 2 * semi space size)比旧的 space 和更多的新对象和变量分配更多的清除 GC 运行会发生。如果此 GC 过度加热性能,您可以考虑重构您的代码以减少新分配。但是,如果您将重用变量,它也可能会降低性能,并且这些对象将变旧 space 并可能成为 "major GC" 部分中描述的问题。

此外,v8 GC 并不总是在您的程序运行的同一线程中工作。它也在后台做一些工作,但我不知道 Webstorm 在你的案例中显示了什么。如果它只计算在 GC 上花费的总时间,可能只是没有那么大的影响。 您可以在 blog post.

中找到有关 v8 GC 的更多详细信息

长话短说:

Can the GC overhead be reduced?

  • 是的,但首先您应该按照上述步骤发现应该优化的内容。

Is this amount of allocation just expected here?

  • 这可以通过比较不同的方法来发现。没有绝对数字可以限制 "bad" 的 "good" 数量,因为它取决于很多因素,包括输入数据的数量。

Is it possible to get better memory profiling information?

  • 您可能会找到一些不错的工具 here, but in general you may use Chrome dev tools which could provide a bit more details 而不是 Webstorm。