簡體   English   中英

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向我展示了“分配大小溢出”錯誤,這意味着該字符串必須小於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

PS:我四處尋找答案,但我發現的最新話題是2011年,所以我正在尋找更新的信息。

字符存儲在16位

當您看到字符串中包含256*2**20字符時,這並不意味着分配了256 MB的內存。 JavaScript將每個字符存儲在兩個字節上(因為它是由規范進行的utf16編碼)。

關於繩索的一個詞

今天的瀏覽器(甚至是IE)以高級方式存儲字符串,最常用的是使用繩索數據結構

  • 繩索不需要分配連貫的存儲區域
  • 甚至可以進行重復數據刪除的子串,這意味着s+s不一定使用內存的兩倍作為s
  • 連接速度非常快
  • 元素訪問速度有點慢

通過檢查IE和Chrome中的一些運行,我會說他們都對字符串使用了一些懶惰的評估,並會嘗試偶爾擴展它們。 運行以下代碼段后,沒有一個瀏覽器使用的內存比以前多。 但是如果我試圖在控制台中操縱存儲的window.LONGEST_STRING ,IE會拋出一個內存不足錯誤,並且chrome會凍結一段時間,並消耗大量內存(> 2 GB)。

ps:在我的筆記本電腦上,IE11的最大字符串大小為4 GB,Chrome的容量為512 MB

瀏覽器行為

IE11

IE11

Chrome47

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); 

鉻跟蹤器的錯誤報告有這樣的評論:

... 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 產生影響 ,因為之前的鏈接是關於運行到toString()限制的NodeJS工具。

內部實現可以使用UCS2或UTF16。 正如@hege_hegedus建議的那樣,至少Firefox使用Rope結構( https://dxr.mozilla.org/mozilla-central/search?q=%2Btype-ref%3ARopeBuilder )。 代碼給出了以下結果:

CHROME VERSION 39.0.2171.95 OS VERSION Linux:3.13.0-43-generic

Firefox 34.0

Chrome輸出(來自@@ hege_hegedus代碼):最大字符串長度為:268435440字符536870880字節511.9999694824219兆字節存儲最長字符串嘗試讀取第一個字符a嘗試讀取最后一個字符a嘗試讀取長度268435440

Firefox輸出(來自OP代碼):“最大字符串長度為268435455”

存檔於http://gpupowered.org/string_js.txt

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM