在现代 Node.js 中更新错误对象的性能影响

Performance hit of newing up Error object in modern Node.js

提问人:Timothy C. Quinn 提问时间:2/10/2016 最后编辑:Mr ListerTimothy C. Quinn 更新时间:2/18/2016 访问量:1914

问:

在某些用例中,需要新建 Error 对象才能检索堆栈跟踪,例如用于日志记录引擎或内联调试。

当首次创建 Error 对象时,或者当开发人员调用 <Error>.stack 属性时,聪明的 V8 开发人员想出按需展开堆栈时,现代节点的性能是否会受到严重影响.js。

从我对工具的探索来看,我认为在访问 <Error>.stack 之前不会执行堆栈跟踪展开,这似乎是一种常识性的设计方法。

任何人都可以阐明这一点或提出验证方法,而不是调试原生 V8 代码?

节点.js 性能 堆栈跟踪 v8

评论

0赞 jfriend00 2/10/2016
为什么不创建一个基准测试和测量呢?
0赞 Timothy C. Quinn 2/12/2016
@jfriend00 - 刚刚完成这个。我将在下面用结果回答我的问题。

答:

21赞 Timothy C. Quinn 2/12/2016 #1

我构建了一个基准测试并将其发布到我的 github 存储库。我的测试结果证实,node.js 背后的 V8 引擎在创建任何 Error 对象(包括 Error 的子类)时捕获堆栈信息。

我的测试相当复杂,但我想确保我绕过了 V8 中的任何优化来展开调用堆栈。我通过在每次测试迭代中生成一个随机调用堆栈来实现这一点。我还尝试了调用 Error.stack 而不调用 Error.stack,其影响可以忽略不计。

有趣的是,性能对 Error 的构造造成了影响,展开长度刚刚超过 10 步的堆栈并将堆栈跟踪作为字符串拉动仅花费了大约 87 微秒。构造一个泛型对象的成本约为 21 微秒。

我还在 V8 Github 存储库 Stack Trace API 页面上找到了一个注释:

请注意,自定义 prepareStackTrace 函数在创建错误对象时会立即调用(例如,使用 new Error())。

评论

0赞 jfriend00 2/12/2016
看来你得到了答案!