JavaScriptに文字列を強制的にディープコピーさせる方法は?
質問
私は次のようないくつかのjavascriptのコードを持っています。
var myClass = {
ids: {}
myFunc: function(huge_string) {
var id = huge_string.substr(0,2);
ids[id] = true;
}
}
その後、この関数はいくつかの大きな文字列(100MB以上)で呼び出されます。私は、各文字列で見つけた短い ID だけを保存したいのです。しかし、Google Chrome の部分文字列関数 (私のコードでは実際には正規表現) は、元の文字列を参照する "sliced string" オブジェクトを返すだけです。そのため、一連の
myFunc
の一連の呼び出しの後、私のクロームタブはメモリ不足になり、一時的な
huge_string
オブジェクトがガベージコレクションされないためです。
文字列のコピーを作成するには
id
を参照できるようにするには、どうすればよいでしょうか。
huge_string
は維持されず
huge_string
はガベージコレクションできるのか?
どのように解決するのですか?
JavaScript の ECMAScript の実装はブラウザによって異なりますが、Chrome では、多くの文字列操作 (substr、slice、regex など) が、文字列のコピーを作成するのではなく、単に元の文字列への参照を保持するだけです。これは Chrome の既知の問題です ( バグ番号: #2869 ). 文字列のコピーを強制的に行うには、以下のコードが有効です。
var string_copy = (' ' + original_string).slice(1);
このコードは、文字列の前にスペースを追加することで動作します。この連結は、Chromeの実装では文字列のコピーになります。そして、スペースの後の部分文字列を参照することができます。
この問題の解決方法は、こちらで再現されています。 http://jsfiddle.net/ouvv4kbs/1/
警告: 読み込みに長い時間がかかります。Chrome デバッグ コンソールを開いて、進行状況のプリントアウトを確認してください。
// We would expect this program to use ~1 MB of memory, however taking
// a Heap Snapshot will show that this program uses ~100 MB of memory.
// If the processed data size is increased to ~1 GB, the Chrome tab
// will crash due to running out of memory.
function randomString(length) {
var alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
var result = '';
for (var i = 0; i < length; i++) {
result +=
alphabet[Math.round(Math.random() * (alphabet.length - 1))];
}
return result;
};
var substrings = [];
var extractSubstring = function(huge_string) {
var substring = huge_string.substr(0, 100 * 1000 /* 100 KB */);
// Uncommenting this line will force a copy of the string and allow
// the unused memory to be garbage collected
// substring = (' ' + substring).slice(1);
substrings.push(substring);
};
// Process 100 MB of data, but only keep 1 MB.
for (var i = 0; i < 10; i++) {
console.log(10 * (i + 1) + 'MB processed');
var huge_string = randomString(10 * 1000 * 1000 /* 10 MB */);
extractSubstring(huge_string);
}
// Do something which will keep a reference to substrings around and
// prevent it from being garbage collected.
setInterval(function() {
var i = Math.round(Math.random() * (substrings.length - 1));
document.body.innerHTML = substrings[i].substr(0, 10);
}, 2000);
関連
-
[解決済み] 配列から特定の項目を削除するにはどうすればよいですか?
-
[解決済み] JavaScriptで "use strict "は何をするのか、その根拠は?
-
[解決済み] JavaScriptで文字列が部分文字列を含むかどうかを確認する方法は?
-
[解決済み] あるJavaScriptファイルを他のJavaScriptファイルにインクルードするにはどうすればよいですか?
-
[解決済み] JavaScriptでオブジェクトをディープクローンする最も効率的な方法は何ですか?
-
[解決済み】JavaScriptで文字列の出現箇所をすべて置換する方法
-
[解決済み】オブジェクトからプロパティを削除する(JavaScript)
-
[解決済み] WebStormで未解決の変数が大量にある場合の警告に対処する方法は?
-
[解決済み] JavaScriptを使用してHTML要素に属性を追加/更新するには?
-
[解決済み] <ng-content>が空かどうかを確認する方法は?(これまでのAngular 2+で)
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] ジェスト あるクラスの特定のメソッドをモックする方法
-
[解決済み] チェックボックスが選択されているかどうかを確認するjQuery
-
[解決済み] Angularjs - 現在の日付を表示する
-
[解決済み] 無効になっている入力フィールドの値を送信する
-
[解決済み] JavaScriptで文字列を数値に変換する最速の方法は何ですか?
-
[解決済み] AJAX Mailchimp サインアップフォームの統合
-
[解決済み] $.ajax実行中にローディングイメージを表示する
-
[解決済み] 各オブジェクトに?重複
-
[解決済み] jQueryを使用して、すべてのクリックイベントハンドラを削除するにはどうすればよいですか?
-
[解決済み] JavaScriptの文字列プリミティブとStringオブジェクトの違いは何ですか?