Javascript 字符串大小限制:对我来说是 256 MB - 所有浏览器都一样吗?
Javascript string size limit: 256 MB for me - is it the same for all browsers?
想知道我在 Javascript 中可以获得的最大字符串长度是多少,我今天在我的 Firefox 43.0.1 上测试了它,运行 在 Windows 7 中。我能够构造一个长度为 2^28 - 1
的字符串,但是当我尝试用一个字符创建一个字符串时,Firebug 向我展示了 "allocation size overflow" 错误,意味着字符串必须小于 256 MB。
这对所有浏览器、所有计算机、所有操作系统都是一样的吗,还是视情况而定?
我创建了以下代码段来找出限制:
(function() {
strings = ["z"];
try {
while(true) {
strings.push(strings[strings.length - 1] + strings[strings.length - 1]);
}
} catch(err) {
var k = strings.length - 2;
while(k >= 0) {
try {
strings.push(strings[strings.length - 1] + strings[k]);
k--;
} catch(err) {}
}
console.log("The maximum string length is " + strings[strings.length - 1].length);
}
})();
如果你是 运行 一个不同的 browser/OS,我想看看你的结果。我的结果是最大字符串长度是268435455。
P.S.: 我四处寻找答案,但我找到的最新主题是从 2011 年开始的,所以我正在寻找更先进的-日期信息。
字符存储在 16 位上
当您看到字符串中有 256*2**20
个字符时,这并不意味着分配了 256 兆字节的内存。 JavaScript 将每个字符存储在两个字节上(因为它是规范编码的 utf16)。
关于ropes
的一句话
当今的浏览器(甚至 IE)以高级方式存储字符串,通常使用 rope datastructure.
- 绳索不需要分配一致的内存区域
- 甚至可以删除重复的子字符串,这意味着
s+s
不一定使用两倍于 s
的内存
- 串联非常快
- 元素访问有点慢
通过检查 IE 和 Chrome 中的一些运行,我会说它们都对字符串使用了一些惰性求值,并且偶尔会尝试扩展它们。在 运行 以下代码段之后,none 的浏览器使用了比以前更多的内存。但是,如果我试图在控制台中操作存储的 window.LONGEST_STRING
,IE 会抛出内存不足错误,并且 chrome 会短暂冻结,并消耗大量内存(>2 GB)。
ps:在我的笔记本电脑上,IE11 的最大字符串大小为 4 GB,Chrome 为 512 MB
浏览器行为
IE11
Chrome47
确定最大字符串大小的更快算法
var real_console_log = console.log;
console.log = function(x) {
real_console_log.apply(console, arguments);
var d = document,b=d.body,p=d.createElement('pre');
p.style.margin = "0";
p.appendChild(d.createTextNode(''+x));
b.appendChild(p);
window.scrollTo(0, b.scrollHeight);
};
function alloc(x) {
if (x < 1) return '';
var halfi = Math.floor(x/2);
var half = alloc(halfi);
return 2*halfi < x ? half + half + 'a' : half + half;
}
function test(x) {
try {
return alloc(x);
} catch (e) {
return null;
}
}
function binsearch(predicateGreaterThan, min, max) {
while (max > min) {
var mid = Math.floor((max + min) / 2);
var val = predicateGreaterThan(mid);
if (val) {
min = mid + 1;
} else {
max = mid;
}
}
return max;
}
var maxStrLen = binsearch(test, 10, Math.pow(2, 52)) - 1;
console.log('Max string length is:');
console.log(maxStrLen + ' characters');
console.log(2*maxStrLen + ' bytes');
console.log(2*maxStrLen/1024/1024 + ' megabytes');
console.log('');
console.log('Store longest string');
window.LONGEST_STRING = alloc(maxStrLen);
console.log('Try to read first char');
console.log(window.LONGEST_STRING.charAt(0));
console.log('Try to read last char');
console.log(window.LONGEST_STRING.charAt(maxStrLen - 1));
console.log('Try to read length');
console.log(window.LONGEST_STRING.length);
Chromium 跟踪器的 bug report 有这样的评论:
... When allocation fails, we create a
Failure pointer encoding the amount requested, as well as some tag and
type bits. This puts a limit on the maximally possible allocation
request in 32-bit versions of 2^27-1. The maximal flat string length is
~2^28 (512MB space), and the maximal string length is 2^29-1...
请注意,这是 2009 年的,所以我想这在当前版本的 V8 中仍然有 consequences,因为之前的 link 是关于 NodeJS 工具 运行 的toString()
.
的限制
内部实现可以使用 UCS2 或 UTF16。正如@hege_hegedus 所建议的,至少 Firefox 使用 Rope 结构(https://dxr.mozilla.org/mozilla-central/search?q=%2Btype-ref%3ARopeBuilder)。这些代码给我以下结果:
CHROME 版本
39.0.2171.95
OS 版本
Linux:3.13.0-43-通用
火狐 34.0
Chrome 输出(来自@@hege_hegedus 代码):
最大字符串长度为:
268435440个字符
536870880 字节
511.9999694824219 兆字节
存储最长的字符串
尝试读取第一个字符
一种
尝试读取最后一个字符
一种
尝试读取长度
268435440
Firefox 输出(来自 OP 代码):
"The maximum string length is 268435455"
想知道我在 Javascript 中可以获得的最大字符串长度是多少,我今天在我的 Firefox 43.0.1 上测试了它,运行 在 Windows 7 中。我能够构造一个长度为 2^28 - 1
的字符串,但是当我尝试用一个字符创建一个字符串时,Firebug 向我展示了 "allocation size overflow" 错误,意味着字符串必须小于 256 MB。
这对所有浏览器、所有计算机、所有操作系统都是一样的吗,还是视情况而定?
我创建了以下代码段来找出限制:
(function() {
strings = ["z"];
try {
while(true) {
strings.push(strings[strings.length - 1] + strings[strings.length - 1]);
}
} catch(err) {
var k = strings.length - 2;
while(k >= 0) {
try {
strings.push(strings[strings.length - 1] + strings[k]);
k--;
} catch(err) {}
}
console.log("The maximum string length is " + strings[strings.length - 1].length);
}
})();
如果你是 运行 一个不同的 browser/OS,我想看看你的结果。我的结果是最大字符串长度是268435455。
P.S.: 我四处寻找答案,但我找到的最新主题是从 2011 年开始的,所以我正在寻找更先进的-日期信息。
字符存储在 16 位上
当您看到字符串中有 256*2**20
个字符时,这并不意味着分配了 256 兆字节的内存。 JavaScript 将每个字符存储在两个字节上(因为它是规范编码的 utf16)。
关于ropes
的一句话当今的浏览器(甚至 IE)以高级方式存储字符串,通常使用 rope datastructure.
- 绳索不需要分配一致的内存区域
- 甚至可以删除重复的子字符串,这意味着
s+s
不一定使用两倍于s
的内存
- 串联非常快
- 元素访问有点慢
通过检查 IE 和 Chrome 中的一些运行,我会说它们都对字符串使用了一些惰性求值,并且偶尔会尝试扩展它们。在 运行 以下代码段之后,none 的浏览器使用了比以前更多的内存。但是,如果我试图在控制台中操作存储的 window.LONGEST_STRING
,IE 会抛出内存不足错误,并且 chrome 会短暂冻结,并消耗大量内存(>2 GB)。
ps:在我的笔记本电脑上,IE11 的最大字符串大小为 4 GB,Chrome 为 512 MB
浏览器行为
IE11
Chrome47
确定最大字符串大小的更快算法
var real_console_log = console.log;
console.log = function(x) {
real_console_log.apply(console, arguments);
var d = document,b=d.body,p=d.createElement('pre');
p.style.margin = "0";
p.appendChild(d.createTextNode(''+x));
b.appendChild(p);
window.scrollTo(0, b.scrollHeight);
};
function alloc(x) {
if (x < 1) return '';
var halfi = Math.floor(x/2);
var half = alloc(halfi);
return 2*halfi < x ? half + half + 'a' : half + half;
}
function test(x) {
try {
return alloc(x);
} catch (e) {
return null;
}
}
function binsearch(predicateGreaterThan, min, max) {
while (max > min) {
var mid = Math.floor((max + min) / 2);
var val = predicateGreaterThan(mid);
if (val) {
min = mid + 1;
} else {
max = mid;
}
}
return max;
}
var maxStrLen = binsearch(test, 10, Math.pow(2, 52)) - 1;
console.log('Max string length is:');
console.log(maxStrLen + ' characters');
console.log(2*maxStrLen + ' bytes');
console.log(2*maxStrLen/1024/1024 + ' megabytes');
console.log('');
console.log('Store longest string');
window.LONGEST_STRING = alloc(maxStrLen);
console.log('Try to read first char');
console.log(window.LONGEST_STRING.charAt(0));
console.log('Try to read last char');
console.log(window.LONGEST_STRING.charAt(maxStrLen - 1));
console.log('Try to read length');
console.log(window.LONGEST_STRING.length);
Chromium 跟踪器的 bug report 有这样的评论:
... When allocation fails, we create a
Failure pointer encoding the amount requested, as well as some tag and
type bits. This puts a limit on the maximally possible allocation
request in 32-bit versions of 2^27-1. The maximal flat string length is
~2^28 (512MB space), and the maximal string length is 2^29-1...
请注意,这是 2009 年的,所以我想这在当前版本的 V8 中仍然有 consequences,因为之前的 link 是关于 NodeJS 工具 运行 的toString()
.
内部实现可以使用 UCS2 或 UTF16。正如@hege_hegedus 所建议的,至少 Firefox 使用 Rope 结构(https://dxr.mozilla.org/mozilla-central/search?q=%2Btype-ref%3ARopeBuilder)。这些代码给我以下结果:
CHROME 版本 39.0.2171.95 OS 版本 Linux:3.13.0-43-通用
火狐 34.0
Chrome 输出(来自@@hege_hegedus 代码): 最大字符串长度为: 268435440个字符 536870880 字节 511.9999694824219 兆字节 存储最长的字符串 尝试读取第一个字符 一种 尝试读取最后一个字符 一种 尝试读取长度 268435440
Firefox 输出(来自 OP 代码): "The maximum string length is 268435455"