前些天看到 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
async-neo@1.8.2.js 146 48.59765625 30.2967
promise_bluebird@2.11.0.js 509 84.8828125 10.1153
co_zco_yyrdl@1.3.2.js 579 88.9609375 9.1068
co_when_generator_cujojs@3.7.8.js 721 117.109375 7.1949
async_caolan@1.5.2.js 712 122.5859375 7.1672
co_tj_with_bluebird_promise@4.6.0.js 895 124.79296875 6.0711
co_when_generator_cujojs_with_bluebird@3.7.8.js 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
co_tj_with_native_promise@4.6.0.js 1107 163.2421875 4.8229
co_when_generator_cujojs_with_native_promise@3.7.8.js 1112 173.63671875 4.719
async_await_es7_with_bluebird_promise.js 1183 191.41796875 4.3899
co_coroutine_bluebird@2.11.0.js 3695 242.4296875 2
开启栈跟踪的测试结果:
name timecost(ms) memory(mb) score(time+memory)
callback.js 92 31.1015625 49.8332
async-neo@1.8.2.js 166 47.7109375 28.3802
promise_bluebird@2.11.0.js 510 85.125 10.4324
async_caolan@1.5.2.js 716 122.328125 7.3841
co_when_generator_cujojs@3.7.8.js 789 117.17578125 6.9716
co_tj_with_bluebird_promise@4.6.0.js 884 126.046875 6.2992
co_when_generator_cujojs_with_bluebird@3.7.8.js 883 131.0234375 6.231
co_zco_yyrdl@1.3.2.js 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
co_tj_with_native_promise@4.6.0.js 1089 162.99609375 5.0394
async_await_es7_with_bluebird_promise.js 1165 188.90625 4.6036
co_when_generator_cujojs_with_native_promise@3.7.8.js 1231 173.71875 4.5379
co_coroutine_bluebird@2.11.0.js 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还好