增加浏览器中的堆栈大小
Posted
技术标签:
【中文标题】增加浏览器中的堆栈大小【英文标题】:Increasing stack size in browsers 【发布时间】:2016-05-24 16:30:26 【问题描述】:简短的问题:我有一个非常深入递归的 javascript。如何增加堆栈大小以便我可以执行它(在 Unix 系统中类似于“ulimit -s unlimited”)?
长话短说:我必须绘制一个图表,我使用 Cytoscape JS (http://js.cytoscape.org/) 和 Dagre 布局扩展 (https://github.com/cytoscape/cytoscape.js-dagre)。绘图算法深入递归,我最终在 Chrome 中得到“未捕获的 RangeError:超出最大调用堆栈大小”,在 Firefox 中得到“递归过多”。如何将堆栈大小设置为无限制或非常大(例如 Unix 系统中的“ulimit -s unlimited”)以便绘制图形?
谢谢!
【问题讨论】:
你确定你的算法是正确的吗?您是否计算过堆栈空间不足时的嵌套调用次数?这是一个合理的数字吗? 是的,算法是正确的。问题是图有点大,绘图算法深入递归。但是,使用其他绘图算法(不使用递归),我能够相当快地绘制它......所以我假设如果我可以将堆栈大小增加到相当大的大小,我将能够绘制它.我搜索了,但找不到任何答案...在最坏的情况下,我需要修改 Dagre 算法以将其从递归更改为迭代...但我想检查是否有任何设置堆栈的方法浏览器javascript引擎的大小限制。 添加更多上下文,在这里您可以找到几个浏览器的堆栈大小限制:***.com/questions/7826992/…。我只需要增加这个限制。 但是,您能否报告一下您在内存不足之前的嵌套调用次数? 你好。我正在使用第三方库,并且有几个函数深入递归。其中一个进行了大约 3000 个级别,但是为此更改整个库对我来说是不切实际的。我现在有一个解决方法,它涉及通过使用 --js-flags="--stack_size x" 命令行参数调用它来更改 Google Chrome 的堆栈大小,并带有一个大 x。非常感谢您的帮助。 【参考方案1】:尝试更改您的算法,以便在函数的每次迭代中不使用尽可能多的堆栈空间。例如:
不使用时将局部变量设置为空。 尽可能使用全局变量进行临时计算。这样,该临时变量就不会在堆栈中。 在递归函数中使用更少的变量。在函数的不同部分对不同的事物重复使用相同的变量。 将递归函数分解为多个函数。其中一些函数不会是递归的,因此当递归函数调用自身时,这些函数中的局部变量不会继续运行。 创建要执行的全局数组并将项目添加到此列表中,而不是递归调用函数。使用 array() 对象的 push 和 pop 方法。 递归函数的参数更少。而是传递一个对象。我希望这些想法对你有所帮助。
【讨论】:
你好。谢谢你的回答。这些事情我有想过,但你的清单确实更完整!但是,如果我尽一切可能最小化每个函数调用的堆栈空间,但算法本身在递归中过于深入并且我无法更改为迭代算法,该怎么办? IE。我真的需要增加堆栈大小吗?我只是不能在现代浏览器中做到这一点?因此,我是否应该将我的脚本重新编码为桌面应用程序以便能够拥有较大的堆栈大小? 我曾经在 Windows 中使用 C 语言进行编程,并且有一个非常大的二叉树。我写了一个递归函数来在函数完成后删除树。递归函数会崩溃。我不得不将递归函数重写为迭代函数。我认为更改语言或扩展堆栈不会解决您的算法问题。如果将堆栈大小增加一倍或三倍,您可能仍然会遇到同样的问题。 你好。我正在使用第三方库,并且有几个函数深入递归。为此改变整个图书馆对我来说是不切实际的。我也同意并且更喜欢以迭代方式编写代码而不是递归,但有时递归在算法上更简洁。在 UNIX 系统中,有时我们有这个,一个 ulimit -s unlimited 解决了这个问题。我现在有一个针对 js 的解决方法,它涉及通过使用 --js-flags="--stack_size x" 命令行参数调用它来更改 Google Chrome 的堆栈大小,并带有一个大 x。非常感谢您的帮助。 在 dagre repo 中发布一个 Github 问题是个好主意,因为这是递归发生的地方:github.com/cpettitt/dagre【参考方案2】:您无法在浏览器中更改堆栈大小,但您可以使用名为trampolining 的技巧。
您可以在此处找到有效的代码解决方案:
How to understand trampoline in JavaScript?
【讨论】:
问题是“如何将堆栈大小设置为无限制或非常大?”这没有回答问题。 @Clément ...即使它已被选为接受的答案?? :O 答案暗示这是不可能的,只是没有明确说明。 感谢您的编辑。你确定这实际上是不可能的吗? cmets 中提到的 OP 的标志似乎确实增加了堆栈大小(这种效果不能通过 javascript 实现,但它仍然可以从命令行工作)。【参考方案3】:Chrome 对此有一个标志:
chromium-browser --js-flags="--stack-size 2048"
不过,您还需要在运行上述命令之前运行 ulimit -s unlimited
:否则,您的深度递归 Javascript 代码将使 Chrome 崩溃。
【讨论】:
可以使用--js-flags="--help"
找到可用的V8标志。以上是关于增加浏览器中的堆栈大小的主要内容,如果未能解决你的问题,请参考以下文章