技术标签: js 参数解构
起源是在写webscoket服务的时候,发现开发工具偶尔报Maximum call stack size exceeded的问题。由于当时没时间,就草草把BUG修复了,并未深究原因。现在复盘工作的时候,又想起这个问题,于是再把这个问题拿出来研究。
出错代码大概是如下:
new Array().push(...Buffer.allocUnsafe(2**17))
一开始看到超出调用栈以为是Buffer的迭代器递归出现了问题,但事实并不是这样。
排查出错原因
由于出错代码是这样的:
/*
* 而且存在临界点,不同机器略有差异
* 本人的机器大于2**17就必报
*/
new Array().push(...Buffer.allocUnsafe(2**17))
当时认为是Buffer的迭代器问题,所以就尝试使用普通数组
/*
* 这段代码在浏览器也报错
* 所以排除nodejs原因,应该是V8造成的
*/
new Array().push(...new Array(2**17).fill(0xff))
发现普通数组也存在类似问题,接下来就是排除迭代器
[...new Array(2**17).fill(0xff)]
发现迭代居然没有异常,难道是push方法?那就换个方法试试
console.log(...new Array(2**17).fill(0xff))
居然log也报错,那真相只有一个,那就是参数超载了
那为什么会报超过最大调用堆栈大小,而不是其它错误?
大家都知道,函数再调用函数的时候,是通过存储在调用栈中来保持执行顺序的,而栈是有一定大小,比如递归上数百万次后也会出现爆栈。
那么是否真的是因为栈不够用了?还是说参数对调用栈也存在一些影响?接下来我们就来逐一排查。首先确定是否是真的因为栈不够用了
# 通过调整栈大小,来判断是否是栈耗尽了,stack-size的单位是KB,默认是984
node --stack-size=2048 -e "new Array().push(...Buffer.allocUnsafe(2**17))"
发现果然运行正常,所以可以确定是栈耗尽了排查参数的数量对栈的影响
function recursionDepth(paramLen) {
let deepth = 0;
function f(...paramList) {
deepth++;
Math.random() + f(...paramList); // 防止尾递归优化
}
try{
f(...Buffer.allocUnsafe(paramLen))
} catch (err) {
console.log(`当参数长度为${paramLen},最大深度则为:${deepth}`)
}
}
recursionDepth(2**4)
recursionDepth(2**8)
recursionDepth(2**12)
recursionDepth(2**16)
recursionDepth(2**20)
输出结果:
当参数长度为16,最大深度则为:3489
当参数长度为256,最大深度则为:455
当参数长度为4096,最大深度则为:30
当参数长度为65536,最大深度则为:1
当参数长度为1048576,最大深度则为:0
所以由此确定参数的数量也是需要暂用调用栈的空间,而当参数长度达到足够长,即使1帧也可以压垮整个调用栈,超出调用栈空间。
转自:https://segmentfault.com/a/1190000015558984并发为了追求更高的计算速度,硬件工程师们将单核cpu扩展为多核cpu,在这样的背景下,而软件行业也为了更充分的利用硬件资源研发出了多线程编程。多线程编程将cpu的计算能力发挥的淋漓尽致,应用程序的性能也得到极大的提升。java并发编程图解J.U.C包简介J.U.C边发包,就是J...
模块是对象,并且所有的模块都有一个内置属性 __name__。一个模块的 __name__ 的值取决于您如何应用模块。如果 import 一个模块,那么模块__name__ 的值通常为模块文件名,不带路径或者文件扩展名。但是您也可以像一个标准的程序样直接运行模块,在这 种情况下, __name__ 的值将是一个特别缺省"__main__"。/////////////////////////////...
1、录制脚本,添加事务,对关注的请求添加事务即可;添加检查点2、回放脚本,如果回放不成功,需要做关联,我验证的脚本,并没有session的关联,但是由于添加的检查点,服务器返回的body是乱码,所以一直回放不成功,这种情况,要么解决乱码的问题,要么用lr转码函数,我使用的后者。用这个函数的时候,还是用到了关联函数,将我要检查的文字给摘取出来。web_reg_save_param_ex(“Pa...
点击上方“小麦大叔”,选择“置顶/星标公众号”福利干货,第一时间送达2022年诺贝尔物理学奖获得者:法国物理学家阿兰·阿斯佩(Alain Aspect)、美国理论和实验物理学家约翰克·劳瑟(John F. Clauser) 和奥地利物理学家安东·塞林格(Anton Zeilinger)今年诺贝尔物理学奖正式揭晓。瑞典斯德哥尔摩当地时间10月4日中午11时45分(北京时间17时45分),瑞典皇家科学...
MFC中Control在浮动窗口中disable的解决方法
To get 32-bit PEB from 32-bit process: BYTE* _teb = (BYTE*)__readfsdword(0x18); PEB32* _peb = *(PEB32**)(_teb + 0x30);To get 64-bit PEB from 64-bit process:...
《一年顶十年》,阅读第三周,读完了这本书,总的感觉是除了一些团队角度的提升观念和作者个性化的内容外,书中很多观点还是能对个人成长起到警醒和指导作用的。
使用基于GAN的超分辨率模型对视频进行超清修复
1,注册表扫描@echo offtitle 注册表扫描中...mode con cols=50 lines=10setlocal enabledelayedexpansion>%temp%\reglist.txt echo %DATE%%time% 注册表扫描报告for /f "tokens=3 delims=\" %%i in ('reg query HKLM\SOFTWARE') do ...
H老师布置作业,要求写一篇关于神经网络的论文,论文格式以国内著名期刊之一为准。我寻思上学期把计算机三大学报(计算机学报、软件学报、计算机研究与发展)的Word格式都练过了,这学期就学习下主流的排版技术Latex。百度了一下国内期刊,《自动化学报》高瞻远瞩地采用latex作为投稿论文的加工模版,而且还是EI检索期刊,CAS果然是学术帝和技术宅的栖息地。 关于latex,我在这里就不赘述了。
1. 首先当然是要有一个GIT账号:github首页2. 然后在电脑上安装一个git:git首页注册和安装这里我就不说了。我相信大家做这个都没有问题。3. 上述两件事情做完了,就登陆到github页面1)首先我们点标注【1】的小三角,进入settings。2)然后我们选择下图圈圈标注的【1】SSH and GPG keys。再点击...
3400: [Usaco2009 Mar]Cow Frisbee Team 奶牛沙盘队题目连接:http://www.lydsy.com/JudgeOnline/problem.php?id=3400Description农夫顿因开始玩飞盘之后,约翰也打算让奶牛们享受飞盘的乐趣.他要组建一只奶牛飞盘队.他的N(1≤N≤2000)只奶牛,每只部有一个飞盘水准指数Ri(1≤Ri≤100000...