异步调用错误堆栈不完整的解决方案
发布于 1 年前 作者 yyrdl 1840 次浏览 来自 分享

前些天看到 pmq20 的文章 介绍了node 8错误堆栈的解决方案,在项目中也经常遇到堆栈不完整难以debug的问题,于是研究了一下,看看有没有奇淫技巧。

先引一下问题

下面这段代码会抛异常,异常结果如图所示。异常的error.stack只指出了异常最初出现的地方,而我们期望stack能给给出完整的调用堆栈信息。 代码截图,带行号: QQ截图20170603203153.png 打出的错误堆栈: QQ截图20170603202532.png

可以看到只打到调用JSON.parse调用的地方,其他的都是无用信息。但如果干掉代码中的setTimeout ,就可以得到完整的调用堆栈,是谁谁谁调用了谁谁谁,然后出了错,错误路径一目了然。 截图如下: QQ截图20170603202912.png QQ截图20170603203052.png

不仅setTimeout ,所有的异步操作都会导致栈丢失。

解决办法

既然是因为异步调用导致的栈丢失,那么在异步调用之前,也就是还是同步调用的时候保存一下栈帧,最终去复原不就ok了么。这个solution貌似可行, 在之前写的zco模块上做下强化,得到下面的测试结果. 测试代码: QQ截图20170603203807.png 打出的堆栈: QQ截图20170603203927.png

结果符合预期,再用co 试试:

测试代码: QQ截图20170603204305.png 打出的堆栈: QQ截图20170603204353.png

并不符合预期。

关于性能

维护调用栈是一个 昂贵的工作,在开启栈跟踪的情况下,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


2 回复

这样子最大的影响因素就是性能吧,毕竟绝大多数情况下是不发生错误的

@hyj1991 是啊,所以功能上提供,可供选择。 从测试结果来看,还是ok的,毕竟性能比es7的async await还好

回到顶部