コールスタック・サイズの最大は?
どこまで関数は深く呼び出せるのか?
例えばこんなコード:
// 深く潜る
function diveDeep(n) {
return diveDeep(n + 1);
}
再帰呼び出しをしているが、終了条件が無いので止まらない。
で、最大でどのくらいまで深く関数を呼べるのか試してみた。
TL;DR 結果は以下の通り
PCの環境の違いとか、ブラウザの実行状況などで、差が出てくるので、
何回か試してみて、一番大きかった数字を書いた。
順位 | ブラウザ | バージョン | 最大コールスタック・サイズ |
---|---|---|---|
1 | Node.js(v8) | v6.9.2-x86 | 31,444 |
2 | Chrome(v8) | 54.0.2807.0 | 31,424 |
3 | Firefox | 50.0 | 15,538 |
4 | Edge | 14.14393 | 11,528 |
5 | IE11 | Trident/7.0 | 10,787 |
6 | jjs(nashorn) | 1.8_60 | 1,187 |
- | Node.js(v8) | v6.9.2-x86 | 31,444 |
- | Node.js(v8) | v6.9.2-x64 | 15,699 |
- | Node.js(v8) | v7.2.1-x86 | 31,412 |
- | Node.js(v8) | v7.2.1-x64 | 15,664 |
- | Chrome Canary | 57.0.2947.0 | 4,638 |
32bit版のv8がダントツ。Google, Mozilla, Microsoftの順って感じ。
64bit版のv8になると半減するね。まぁ、そういうもんか。
Canaryはカナリひどい。
※OS: Windows 10 (64bit), Memory: 16GB (2016/12/11時点)
HTMLのソース
いくつかのブラウザで試してみた。Chrome, Firefox, Edge, IE11 など。
max-call-stack-size.html
<!doctype html>
<meta charset="UTF-8">
<p>Maximum call stack size:</p>
<script src="max-call-stack-size.js"></script>
JavaScriptのソース
ブラウザ以外では、nodeとjjs (nashorn; Javaに付いているやつ) で試してみた。
max-call-stack-size.js
// 深く潜る
function diveDeep(n) {
try {
return diveDeep(n + 1);
} catch (e) {
return {count: n, error: e};
}
}
// メイン
displayVersion(); // バージョンを表示
var result = diveDeep(0); // 深く潜る
// 結果を表示
pr('Maximum call stack size: ' + result.count);
pr('Error: ' + result.error);
var keys = (Object.getOwnPropertyNames || Object.keys)(result.error);
for (var i in keys)
pr('Error.' + keys[i] + ': ' + result.error[keys[i]]);
// ブラウザのバージョン等を表示
function displayVersion() {
pr(typeof navigator !== 'undefined' &&
navigator.userAgent &&
'Browser: ' + navigator.userAgent ||
typeof process !== 'undefined' &&
process.version &&
'Node.js: ' + process.version ||
'other');
}
// 表示
function pr(x) {
if (typeof document !== 'undefined' && document.writeln)
document.writeln((x + '\n\n').split('\n').join('<br/>\n'));
/*else*/ if (typeof console !== 'undefined' && console.log)
console.log(x);
else if (typeof print !== 'undefined')
print(x);
}
実行結果
Node(x86)
Node(x86)
Node.js: v6.9.2
Maximum call stack size: 31444
Error: RangeError: Maximum call stack size exceeded
Error.message: Maximum call stack size exceeded
Error.stack: RangeError: Maximum call stack size exceeded
at diveDeep (xxx/max-call-stack-size.js:6:3)
at diveDeep (xxx/max-call-stack-size.js:4:10)
at diveDeep (xxx/max-call-stack-size.js:4:10)
at diveDeep (xxx/max-call-stack-size.js:4:10)
at diveDeep (xxx/max-call-stack-size.js:4:10)
at diveDeep (xxx/max-call-stack-size.js:4:10)
at diveDeep (xxx/max-call-stack-size.js:4:10)
at diveDeep (xxx/max-call-stack-size.js:4:10)
at diveDeep (xxx/max-call-stack-size.js:4:10)
at diveDeep (xxx/max-call-stack-size.js:4:10)
Chrome
Chrome
Maximum call stack size:
Browser: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36
Maximum call stack size: 31424
Error: RangeError: Maximum call stack size exceeded
Error.stack: RangeError: Maximum call stack size exceeded
at diveDeep (file:///max-call-stack-size.js:6:3)
at diveDeep (file:///max-call-stack-size.js:4:10)
at diveDeep (file:///max-call-stack-size.js:4:10)
at diveDeep (file:///max-call-stack-size.js:4:10)
at diveDeep (file:///max-call-stack-size.js:4:10)
at diveDeep (file:///max-call-stack-size.js:4:10)
at diveDeep (file:///max-call-stack-size.js:4:10)
at diveDeep (file:///max-call-stack-size.js:4:10)
at diveDeep (file:///max-call-stack-size.js:4:10)
at diveDeep (file:///max-call-stack-size.js:4:10)
Error.message: Maximum call stack size exceeded
Firefox
Firefox
Maximum call stack size:
Browser: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:50.0) Gecko/20100101 Firefox/50.0
Maximum call stack size: 15538
Error: InternalError: too much recursion
Error.fileName: file:///max-call-stack-size.js
Error.lineNumber: 3
Error.columnNumber: 1
Error.message: too much recursion
IE11
IE11
Maximum call stack size:
Browser: Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; .NET4.0C; .NET4.0E; .NET CLR 2.0.50727; .NET CLR 3.0.30729; .NET CLR 3.5.30729; InfoPath.1; rv:11.0) like Gecko
Maximum call stack size: 10787
Error: Error: スタック領域が不足しています。
Error.message: スタック領域が不足しています。
Error.description: スタック領域が不足しています。
Error.number: -2146828260
Error.stack: Error: スタック領域が不足しています。
at diveDeep (file:///max-call-stack-size.js:4:3)
at diveDeep (file:///max-call-stack-size.js:4:3)
at diveDeep (file:///max-call-stack-size.js:4:3)
at diveDeep (file:///max-call-stack-size.js:4:3)
at diveDeep (file:///max-call-stack-size.js:4:3)
at diveDeep (file:///max-call-stack-size.js:4:3)
at diveDeep (file:///max-call-stack-size.js:4:3)
at diveDeep (file:///max-call-stack-size.js:4:3)
at diveDeep (file:///max-call-stack-size.js:4:3)
at diveDeep (file:///max-call-stack-size.js:4:3)
Edge
Edge
Maximum call stack size:
Browser: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.79 Safari/537.36 Edge/14.14393
Maximum call stack size: 11528
Error: Error: Out of stack space
Error.message: Out of stack space
Error.description: Out of stack space
Error.number: -2146828260
Error.stack: Error: Out of stack space
at diveDeep (file:///max-call-stack-size.js:4:3)
at diveDeep (file:///max-call-stack-size.js:4:3)
at diveDeep (file:///max-call-stack-size.js:4:3)
at diveDeep (file:///max-call-stack-size.js:4:3)
at diveDeep (file:///max-call-stack-size.js:4:3)
at diveDeep (file:///max-call-stack-size.js:4:3)
at diveDeep (file:///max-call-stack-size.js:4:3)
at diveDeep (file:///max-call-stack-size.js:4:3)
at diveDeep (file:///max-call-stack-size.js:4:3)
at diveDeep (file:///max-call-stack-size.js:4:3)
jjs (nashorn; Java 8)
jjs
>jjs -v
nashorn 1.8.0_60
>jjs max-call-stack-size.js
other
Maximum call stack size: 1187
Error: java.lang.StackOverflowError
max-call-stack-size.js:16 TypeError: java.lang.StackOverflowError is not an Object
Chrome Canary
ChromeCanary
Maximum call stack size:
Browser: Mozilla/5.0 (Windows NT 10.0.14393; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2947.0 Safari/537.36
Maximum call stack size: 4638
Error: RangeError: Maximum call stack size exceeded
Error.stack: RangeError: Maximum call stack size exceeded
at diveDeep (file:///max-call-stack-size.js:6:3)
at diveDeep (file:///max-call-stack-size.js:4:10)
at diveDeep (file:///max-call-stack-size.js:4:10)
at diveDeep (file:///max-call-stack-size.js:4:10)
at diveDeep (file:///max-call-stack-size.js:4:10)
at diveDeep (file:///max-call-stack-size.js:4:10)
at diveDeep (file:///max-call-stack-size.js:4:10)
at diveDeep (file:///max-call-stack-size.js:4:10)
at diveDeep (file:///max-call-stack-size.js:4:10)
at diveDeep (file:///max-call-stack-size.js:4:10)
Error.message: Maximum call stack size exceeded
でっていう
で、何の役にも立たない...
以下の記事を書いた時に気になったので調べただけです。
竹内関数を遅延評価で高速化してみた(JavaScript/Node.js/ES2015/ES6) - Qiita