node.js - GC 占用了预期运行时间的 32%?

标签 node.js optimization garbage-collection profiling

目前正在致力于优化库的速度。我已经使用 V8 CPU and Memory Profiling 大大减少了执行时间通过网络 Storm 。这主要是通过改变recursive to iterative中的核心方法来实现的。 .

现在自拍时间分布分割为

enter image description here

我假设第一个条目“Node ”正在计时内部函数调用,这很棒。其他条目也有道理。我是 Nodejs 分析的新手,但 GC 的 31.6% 似乎很高,因此我决定进行调查。

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

enter image description here

这些似乎主要是系统内部内存引用。逐步深入核心iteration code logic同样,似乎也没有很多地方显式分配内存(使用 this 作为引用)。

问题

  • 是否可以减少 GC 开销?
  • 这个分配量是否符合预期?
  • 是否可以获得更好的内存分析信息?

设置说明

如果有人想尝试调试这个,我将提供设置说明。

下载或克隆object-scan并运行

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

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

最佳答案

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

在 v8 引擎中,GC 有两种主要“类型”:次要(scavenge)和主要(mark-sweep/mark-compact)。您可能会在启用了 --trace-gc 的情况下在控制台中看到测试期间发生的 GC 类型。在不同的情况下,一种类型可能比另一种类型“吃”更多的时间,反之亦然。因此,在优化之前,您应该确定哪个 gc 花费更多时间。

优化Major GC的选项并不多,因为它很大程度上受到内存中“长时间”保留的数据量的影响(实际上在这种情况下,“长”意味着对象在清理GC中幸存下来)。这些数据存储在堆中所谓的“旧空间”中。主要 GC 处理这个空间,它应该扫描所有内存并标记不再有任何引用的对象以进行进一步清理。

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

如果您发现Major GC 对性能没有太大影响,那么scavenge GC 会花费大部分时间。与Major GC 不同的是,它在堆中使用所谓的“新空间”进行操作。这是存储所有新对象的空间。如果这些物体在清理中幸存下来,那么它们就会被转移到旧空间。新空间的大小比旧空间小得多(可以通过设置--max_semi_space_size来控制,注意:新空间大小 = 2 * 半空间大小)比旧空间小得多,新对象更多并且你分配的变量会发生更多的清理GC运行。如果此 GC 过多地提高性能,您可以考虑重构代码以减少新的分配。但是,如果您重用变量,它也可能会降低性能,并且这些对象将转到旧空间,并可能成为“主要 GC”部分中描述的问题。

此外,v8 GC 并不总是在程序运行的同一线程中工作。它也在后台做了一些工作,但我不知道 Webstorm 在你的案例中显示了什么。如果只计算 GC 所花费的总时间,可能不会产生太大的影响。 您可以在 blog post 中找到有关 v8 GC 的更多详细信息.

TL;博士:

Can the GC overhead be reduced?

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

Is this amount of allocation just expected here?

  • 这可以通过比较不同的方法来发现。没有某个绝对数字可以限制“好”金额与“坏”金额,因为它取决于很多因素,包括条目数据的金额。

Is it possible to get better memory profiling information?

  • 您可能会发现一些不错的工具 here ,但一般来说,您可以使用 Chrome 开发工具,它可以提供更多信息 details而不是 Webstorm 所做的。

关于node.js - GC 占用了预期运行时间的 32%?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55985405/

相关文章:

java - 返回表达式总是被计算出来,还是可以被编译器优化掉?

node.js - 全文搜索的想法 MongoDB 和 node.js

javascript - 如何从 mac 中完全删除 Ionic 和 Cordova 安装?

python - 如果我的目标函数是非线性(也是指数解释)函数,我应该使用什么求解器? python 壁虎

java - Android - 带有指向 WebView 指针的 Javascript 接口(interface) - 如何在没有 memleak 的情况下实现它

java - java中的垃圾收集器方法有什么用?

node.js - 实例化 mongoose 模型时应用程序速度变慢

javascript - 使用 Bluebird promise

matlab - Matlab优化工具箱中的非线性等式和不等式约束

java - 优化变量声明原语与空对象