代码之家  ›  专栏  ›  技术社区  ›  Pedro A Sindre Sorhus

Javascript字符串大小限制:256 MB(对于我来说)-所有浏览器都一样吗?

  •  16
  • Pedro A Sindre Sorhus  · 技术社区  · 10 年前

    我很好奇我在Javascript中能得到的最大字符串长度是多少,今天我自己在运行Windows 7的Firefox 43.0.1上测试了它 2^28 - 1 ,但当我试图创建一个多了一个字符的字符串时, Firebug 给我看 “分配大小溢出” 错误,这意味着字符串必须小于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);
        }
    })();
    

    如果您运行的是不同的浏览器/操作系统,我希望看到您的结果。我的结果是 最大字符串长度为268435455 .

    附笔。: 我四处寻找答案,但我发现的最新主题是2011年的,所以我正在寻找更新的信息。

    3 回复  |  直到 10 年前
        1
  •  18
  •   Tamas Hegedus    10 年前

    字符存储在16位

    当你看到的时候 256*2**20 字符在字符串中,这并不意味着分配了256兆字节的内存。JavaScript将每个字符存储在两个字节上(因为它是由规范编码的utf16)。

    一句关于 ropes

    现在的浏览器(甚至IE)以高级方式存储字符串,通常使用 rope datastructure .

    • 绳索不需要分配一致的内存区域
    • 甚至可以对子字符串进行重复数据消除,这意味着 s+s 不一定使用两倍于 s
    • 串联非常快
    • 元素访问有点慢

    通过检查IE和Chrome中的一些运行,我可以说它们都对字符串使用了一些懒惰的求值,并且偶尔会尝试扩展它们。运行以下代码段后,没有一个浏览器比以前使用更多的内存。但如果我试图操纵存储的 window.LONGEST_STRING 在控制台中,IE抛出内存不足错误,chrome会短暂冻结,并消耗大量内存(>2GB)。

    ps:在我的笔记本电脑上,IE11的最大字符串大小为4GB,Chrome有512MB

    浏览器行为

    第11页

    IE11

    铬47

    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);
        2
  •  1
  •   Jason    10 年前

    A. 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年的,所以我想这仍然是 consequences 在当前版本的V8中,前面的链接是关于NodeJS工具的 toString() .

        3
  •  1
  •   Prabindh    10 年前

    内部实现可以使用UCS2或UTF16。正如@hege_hegedus所建议的,至少Firefox使用了Rope结构( https://dxr.mozilla.org/mozilla-central/search?q=%2Btype-ref%3ARopeBuilder ). 代码给出了以下结果:

    镀铬版 39.0.2171.95 操作系统版本 Linux:3.13.0-43通用

    火狐34.0

    Chrome输出(来自@@hege_hegedus代码): 最大字符串长度为: 268435440个字符 536870880字节 511.9999694824219兆字节 存储最长字符串 尝试读取第一个字符 一 尝试读取最后一个字符 一 尝试读取长度 268435440

    Firefox输出(来自OP代码): “最大字符串长度为268435455”

    存档时间: http://gpupowered.org/string_js.txt