localStorage スペースの使用量の計算
-
26-09-2019 - |
質問
Bespin エディターと HTML5 の localStorage を使用してアプリを作成しています。すべてのファイルをローカルに保存し、文法を支援し、JSLint やその他の CSS および HTML パーサーを使用してユーザーを支援します。
localStorage の制限がどのくらい使用されているか、そして実際にどれくらいあるのかを計算したいと考えています。 今日はそれが可能ですか? 保存されているビットを単純に計算しないように考えていました。しかし、繰り返しになりますが、自分自身で測定できないことは他に何があるのかわかりません。
解決 2
必要なブラウザーの残りの制限を取得する普遍的な方法は見つかりませんでしたが、制限に達するとエラー メッセージがポップアップ表示されることがわかりました。もちろん、これはブラウザごとに異なります。
それを最大限に活用するために、次の小さなスクリプトを使用しました。
for (var i = 0, data = "m"; i < 40; i++) {
try {
localStorage.setItem("DATA", data);
data = data + data;
} catch(e) {
var storageSize = Math.round(JSON.stringify(localStorage).length / 1024);
console.log("LIMIT REACHED: (" + i + ") " + storageSize + "K");
console.log(e);
break;
}
}
localStorage.removeItem("DATA");
そこから次の情報を入手しました。
グーグルクローム
- DOM例外:
- コード:22
- メッセージ:「「ストレージ」で「setItem」を実行できませんでした:「データ」の値の設定がクォータを超えました。」
- 名前:「クォータ超過エラー」
モジラ Firefox
- DOM例外:
- コード:1014
- メッセージ:「永続ストレージの最大サイズに達しました」
- 名前:「NS_ERROR_DOM_QUOTA_REACHED」
サファリ
- DOM例外:
- コード:22
- メッセージ:「クォータ超過エラー:DOM 例外 22"
- 名前:「クォータ超過エラー」
Internet Explorer、エッジ (コミュニティ)
- DOM例外:
- コード:22
- メッセージ:「クォータ超過エラー」
- 名前:「クォータ超過エラー」
私の解決策
これまでのところ、私の解決策は、ユーザーが何かを保存するたびに追加の呼び出しを追加することです。そして、例外がキャッチされた場合は、ストレージ容量が不足していることを伝えます。
編集:追加したデータを削除する
言い忘れていましたが、これを実際に機能させるには、 DATA
元々設定されていた項目です。変更は上記を使用して反映されます。 削除項目() 関数。
他のヒント
JSON メソッドを使用して localStorage オブジェクト全体を JSON 文字列に変換すると、おおよそのアイデアを得ることができる場合があります。
JSON.stringify(localStorage).length
特に追加のオブジェクトを使用している場合に数バイトのマークアップが追加される場合、それがどの程度バイト精度になるかはわかりませんが、28K だけをプッシュし、代わりに 280K を実行すると考えるよりは良いと思います (またはその逆)その逆も同様)。
IE8 では、 remainingSpace
この目的のためのプロパティ:
alert(window.localStorage.remainingSpace); // should return 5000000 when empty
残念ながら他のブラウザでは利用できないようです。ただし、同様のものを実装しているかどうかはわかりません。
以下の行を使用すると、この値を正確に計算でき、 ここにjsfiddleがあります 使用例を説明するため
alert(1024 * 1024 * 5 - escape(encodeURIComponent(JSON.stringify(localStorage))).length);
今日、テスト中にこの問題に遭遇し(ストレージ割り当ての超過)、解決策を考え出しました。IMO では、制限が何なのか、そして私たちがどのような関係にあるのかを知ることは、クォータを超えて保存を続けるための機能的な方法を実装することよりもはるかに価値がありません。
したがって、サイズ比較や容量チェックを行うのではなく、クォータに達したときに対応し、現在のストレージを 3 分の 1 減らして、保存を再開しましょう。上記の削減が失敗した場合は、保存を停止します。
set: function( param, val ) {
try{
localStorage.setItem( param, typeof value == 'object' ? JSON.stringify(value) : value )
localStorage.setItem( 'lastStore', new Date().getTime() )
}
catch(e){
if( e.code === 22 ){
// we've hit our local storage limit! lets remove 1/3rd of the entries (hopefully chronologically)
// and try again... If we fail to remove entries, lets silently give up
console.log('Local storage capacity reached.')
var maxLength = localStorage.length
, reduceBy = ~~(maxLength / 3);
for( var i = 0; i < reduceBy; i++ ){
if( localStorage.key(0) ){
localStorage.removeItem( localStorage.key(0) );
}
else break;
}
if( localStorage.length < maxLength ){
console.log('Cache data reduced to fit new entries. (' + maxLength + ' => ' + localStorage.length + ')');
public.set( param, value );
}
else {
console.log('Could not reduce cache size. Removing session cache setting from this instance.');
public.set = function(){}
}
}
}
}
この関数はラッパー オブジェクト内に存在するため、public.set は単にそれ自体を呼び出します。これで、ストレージを追加できるようになり、割り当てがどの程度であるか、または割り当てにどれだけ近づいているかを気にする必要がなくなります。1 つのストアが 3 分の 1 を超えた場合、この関数はクォータ サイズでカリングを停止し、保存を終了します。その時点では、とにかくキャッシュすべきではありませんよね。
ブラウザのテスト結果に追加するには:
Firefoxi=22。
サファリ私の Mac のバージョン 5.0.4 はハングしませんでした。Chromeとしてエラー。i=21。
オペラWeb サイトがデータを保存したいが、十分なスペースがないことをユーザーに伝えます。ユーザーは、必要な金額またはその他のいくつかの制限を上限としてリクエストを拒否することも、無制限に設定することもできます。opera:webstorage に移動して、このメッセージが表示されるかどうかを確認してください。i=20。スローされるエラーはChromeと同じです。
IE9標準モードChromeとしてエラー。i=22。
IE8標準モードのIE9コンソールメッセージ「エラー:この操作を完了するには十分なストレージがありません。」i=22
古いモードの IE9オブジェクトエラー。i=22。
IE8テストするコピーはありませんが、ローカル ストレージはサポートされています (http://stackoverflow.com/questions/3452816/does-ie8-support-out-of-the-box-in-localstorage)
IE7以下ローカルストレージはサポートしていません。
これでブラウザをテストできます Webストレージサポートテスト
テストしました Firefox Android タブレットと Windows ラップトップの両方で、 クロム Windowsの結果:
Firefox(ウィンドウズ):
- ローカルストレージ:5120k文字
- セッションストレージ:5120k文字
- ローカルストレージ:*サポートされていません
Firefox(アンドロイド):
- ローカルストレージ:2560k文字
- セッションストレージ:無制限 (正確には、テストは最大 10240k 文字 == 20480k バイトまで実行されます)
- ローカルストレージ: サポートされていません
クロム(ウィンドウズ):
- ローカルストレージ:5120k文字
- セッションストレージ:5120k文字
- ローカルストレージ: サポートされていません
アップデート
Google Chrome バージョン 52.0.2743.116 m (64 ビット) の制限では、制限が少し低くなります。 5101k
文字。つまり、利用可能な最大値はバージョンによって異なる可能性があります。
これをコメントに追加できればいいのですが、十分な担当者ではありません、申し訳ありません。
いくつかのパフォーマンス テストを実行しました。localStorage の占有率が大きい場合、JSON.stringify(localStorage).length は高価な操作になることが予想されます。
http://jsperf.com/occupied-localstorage-json-stringify-length
確かにその通りです。保存しているものを追跡するよりも約 50 倍のコストがかかり、localStorage がいっぱいになるにつれてコストはさらに悪化します。
この関数は、 ちょうど 利用可能なストレージ / 残りのストレージ:
localStorage 用の便利な関数スイートを作成しました *ここ*
http://jsfiddle.net/kzq6jgqa/3/
function getLeftStorageSize() {
var itemBackup = localStorage.getItem("");
var increase = true;
var data = "1";
var totalData = "";
var trytotalData = "";
while (true) {
try {
trytotalData = totalData + data;
localStorage.setItem("", trytotalData);
totalData = trytotalData;
if (increase) data += data;
} catch (e) {
if (data.length < 2) break;
increase = false;
data = data.substr(data.length / 2);
}
}
localStorage.setItem("", itemBackup);
return totalData.length;
}
// Examples
document.write("calculating..");
var storageLeft = getLeftStorageSize();
console.log(storageLeft);
document.write(storageLeft + "");
// to get the maximum possible *clear* the storage
localStorage.clear();
var storageMax = getLeftStorageSize();
これはそれほど高速ではないため、常に使用しないでください。
これにより、次のこともわかりました。Item-Name はその長さと同じ量のスペースを占め、Item-Value もその長さと同じ量のスペースを占めます。
私が取得した最大ストレージ - すべて約 5M:
- 5000000 文字 - エッジ
- 5242880 文字 - Chrome
- 5242880 文字 - Firefox
- 5000000 文字 - IE
フィドル内にアウトコメント化されたコードがいくつかあり、コンソールで進行状況を確認できます。
作るのに時間がかかりましたが、参考になれば幸いです☺
ストレージがいっぱいになったときにモジュールがどのように動作するかを実際にシミュレートしてテストする必要がありました。そのため、受け入れられた答えではなく、ストレージがいっぱいになったときの正確な精度を取得する必要がありました。その精度は i^2 の割合で失われます。
これが私のスクリプトです。これは、メモリの上限に達したときに常に 10 の精度を生成するはずであり、いくつかの簡単な最適化があるにもかかわらず、かなり迅速に生成されます。編集:スクリプトをより正確かつ正確に改良しました。
function fillStorage() {
var originalStr = "1010101010";
var unfold = function(str, times) {
for(var i = 0; i < times; i++)
str += str;
return str;
}
var fold = function(str, times) {
for(var i = 0; i < times; i++) {
var mid = str.length/2;
str = str.substr(0, mid);
}
return str;
}
var runningStr = originalStr;
localStorage.setItem("filler", runningStr);
while(true) {
try {
runningStr = unfold(runningStr, 1);
console.log("unfolded str: ", runningStr.length)
localStorage.setItem("filler", runningStr);
} catch (err) {
break;
}
}
runningStr = fold(runningStr, 1);
var linearFill = function (str1) {
localStorage.setItem("filler", localStorage.getItem("filler") + str1);
}
//keep linear filling until running string is no more...
while(true) {
try {
linearFill(runningStr)
} catch (err) {
runningStr = fold(runningStr, 1);
console.log("folded str: ", runningStr.length)
if(runningStr.length == 0)
break;
}
}
console.log("Final length: ", JSON.stringify(localStorage).length)
}
これは誰かを助けるかもしれません。Chrome では、必要に応じて、より多くのディスク領域の使用を許可するようにユーザーに要求することができます。
// Request Quota (only for File System API)
window.webkitStorageInfo.requestQuota(PERSISTENT, 1024*1024, function(grantedBytes) {
window.webkitRequestFileSystem(PERSISTENT, grantedBytes, onInitFs, errorHandler);
}, function(e) {
console.log('Error', e);
});
訪問 https://developers.google.com/chrome/whitepapers/storage#asking_more 詳細については。
try {
var count = 100;
var message = "LocalStorageIsNOTFull";
for (var i = 0; i <= count; count + 250) {
message += message;
localStorage.setItem("stringData", message);
console.log(localStorage);
console.log(count);
}
}
catch (e) {
console.log("Local Storage is full, Please empty data");
// fires When localstorage gets full
// you can handle error here ot emply the local storage
}