前些天看到 pmq20 的文章 介绍了node 8错误堆栈的解决方案,在项目中也经常遇到堆栈不完整难以debug的问题,于是研究了一下,看看有没有奇淫技巧。
先引一下问题
下面这段代码会抛异常,异常结果如图所示。异常的error.stack只指出了异常最初出现的地方,而我们期望stack能给给出完整的调用堆栈信息。 代码截图,带行号: 打出的错误堆栈:
可以看到只打到调用JSON.parse调用的地方,其他的都是无用信息。但如果干掉代码中的setTimeout ,就可以得到完整的调用堆栈,是谁谁谁调用了谁谁谁,然后出了错,错误路径一目了然。 截图如下:
不仅setTimeout ,所有的异步操作都会导致栈丢失。
解决办法
既然是因为异步调用导致的栈丢失,那么在异步调用之前,也就是还是同步调用的时候保存一下栈帧,最终去复原不就ok了么。这个solution貌似可行, 在之前写的zco模块上做下强化,得到下面的测试结果. 测试代码: 打出的堆栈:
结果符合预期,再用co 试试:
测试代码: 打出的堆栈:
并不符合预期。
关于性能
维护调用栈是一个 昂贵的工作,在开启栈跟踪的情况下,zco的运行速度降了一半。即使这样同其他模块比较,性能并不坏,平时使用应该没问题。
性能测试结果如下:
带co前缀的都属于协程模块,在禁用栈跟踪的情况下测试zco。
results for 20000 parallel executions, 1 ms per I/O op ,2017-06-03
name timecost(ms) memory(mb) score(time+memory)
callback.js 96 30.23828125 46.5068
[email protected] 146 48.59765625 30.2967
[email protected] 509 84.8828125 10.1153
[email protected] 579 88.9609375 9.1068
[email protected] 721 117.109375 7.1949
[email protected] 712 122.5859375 7.1672
[email protected] 895 124.79296875 6.0711
[email protected] 916 131.3515625 5.8794
async_await_es7_with_native_promise.js 964 166.82421875 5.2861
promise_native.js 949 179.29296875 5.2457
[email protected] 1107 163.2421875 4.8229
[email protected] 1112 173.63671875 4.719
async_await_es7_with_bluebird_promise.js 1183 191.41796875 4.3899
[email protected] 3695 242.4296875 2
开启栈跟踪的测试结果:
name timecost(ms) memory(mb) score(time+memory)
callback.js 92 31.1015625 49.8332
[email protected] 166 47.7109375 28.3802
[email protected] 510 85.125 10.4324
[email protected] 716 122.328125 7.3841
[email protected] 789 117.17578125 6.9716
[email protected] 884 126.046875 6.2992
[email protected] 883 131.0234375 6.231
[email protected] 1181 94.42578125 5.8436
promise_native.js 999 170.3125 5.2953
async_await_es7_with_native_promise.js 1022 161.47265625 5.2862
[email protected] 1089 162.99609375 5.0394
async_await_es7_with_bluebird_promise.js 1165 188.90625 4.6036
[email protected] 1231 173.71875 4.5379
[email protected] 3867 242.61328125 2
Platform info:
Windows_NT 10.0.14393 x64
Node.JS 7.7.3
V8 5.5.372.41
Intel(R) Core(TM) i5-5200U CPU @ 2.20GHz × 4
这样子最大的影响因素就是性能吧,毕竟绝大多数情况下是不发生错误的
@hyj1991 是啊,所以功能上提供,可供选择。 从测试结果来看,还是ok的,毕竟性能比es7的async await还好