Posted at

コールスタック・サイズの最大は? どこまで関数は深く呼び出せるのか? (JavaScript)

More than 1 year has passed since last update.


コールスタック・サイズの最大は?


どこまで関数は深く呼び出せるのか?

例えばこんなコード:

// 深く潜る

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