Prueba de cuota de tamaño de almacenamiento web

Para obtener una introducción al almacenamiento web, consulte mi publicación anterior .

¡Mira la versión de producción en GitHub !

El almacenamiento web es una característica clave en mi proyecto actual, que implica el almacenamiento en búfer de video. Pero cada navegador no admite la misma cantidad de almacenamiento web, y algunos incluso difieren en la cantidad de almacenamiento local y almacenamiento de sesiones disponibles.

Un sitio agrega datos basados ​​en cada navegador para proporcionar una línea de base para cada navegador. Esta es información útil, pero tengo serias reservas sobre su uso en un entorno de producción. Principalmente porque la detección del agente de usuario del lado del cliente es defectuosa en el mejor de los casos y hay una gran cantidad de navegadores y versiones diferentes en la naturaleza. La única opción real era desarrollar una prueba rápida para cada navegador, o vivir de forma peligrosa y manejar las excepciones que surgen al agregar demasiados datos (para navegadores que no son IE). Encontré un par de bibliotecas, pero esperar 2 segundos para determinar el tamaño de la caché sería inaceptable. Así que escribí el mío, reduciendo el tiempo de ejecución en 10 veces.

Primero, determino si el navegador es IE. Una vez más, la detección de agentes de usuario no es el mejor medio. IE es el único navegador que admite .remainingSpace y no lanza cuando se excede el tamaño. Este bool es importante para una puerta lógica cuando se agrega a Web Storage.

//remaining space is only available in MSIE
var isIE = localStorage.remainingSpace !== 'undefined';

A continuación, se debe crear la matriz de cadenas de prueba. Estas cadenas son de diferentes longitudes y evitan una penalización costosa de copiar cadenas debido a la concatenación.

//create the array of different sized objects. hold the length to prevent costly calls to array length property
var arr = buildArray();
var length = arr.length;

function buildArray()
{
//build array, these will be the values that will be added to the web storage
var b1 = "0";
var b10 = increaseLength(b1, 10);
var b100 = increaseLength(b10, 10);
var kb1 = increaseLength(b100, 10);
var kb10 = increaseLength(kb1, 10);
var kb100 = increaseLength(kb10, 10);
var mb1 = increaseLength(kb100, 10);
var mb10 = increaseLength(mb1, 10);

//return array of various sizes, ordered smallest to largest
return [b1, b10, b100, kb1, kb10, kb100, mb1, mb10];
}

function increaseLength(string, times)
{
var temp = [];
while (times--)
temp
.push(string);
return temp.join('');
}

Ahora que puede comenzar la prueba, esta versión prueba los tres tipos de almacenamiento web. Algunos navegadores tendrán cuotas diferentes para localStorage y sessionStorage. globalStorage está en gran parte obsoleto y ha sido reemplazado por localStorage. Los resultados se publican en un andamio HTML toscamente construido.

//array of the types of Web Storage
var storage_types = ["localStorage", "sessionStorage", "globalStorage"];

//check for web storage
for (i = 0; i < storage_types.length; i++)
{
//verify the browser supports this form of web storage
if (supportsStorage(storage_types[i]))
{
//start the stopwatch to time how long the test takes
var sw = new StopWatch();
sw
.start();

//clear everything from web storage before starting
window
[storage_types[i]].clear();

//iterate to find the maximum amount of data that can be stored
checkSize
(storage_types[i]);

//stop the stopwatch
sw
.stop();

//print the results
document
.getElementById(storage_types[i] + 'support').innerHTML = storage_types[i] + " is supported by your browser over this protocol";
document
.getElementById(storage_types[i] + 'results').innerHTML = storageSize(storage_types[i]) + " Bytes available for " + storage_types[i] + " on this browser";
document
.getElementById(storage_types[i] + 'time').innerHTML = sw.elapsedTime + " [ms] to test browser " + storage_types[i];

//clear everything from web storage before starting next iteration (Firefox fix)
window
[storage_types[i]].clear();
}
else
{
//print the results
document
.getElementById(storage_types[i] + 'support').innerHTML = storage_types[i] + " is not supported by your browser over this protocol";
document
.getElementById(storage_types[i] + 'results').innerHTML = "N/A";
document
.getElementById(storage_types[i] + 'time').innerHTML = "N/A";
}
}

La función de verificación de tamaño es donde está la optimización real. Repite la matriz de cadenas de prueba, comenzando por la más grande primero. Dado que Web Storage arrojará resultados si se excede la cuota de tamaño, comenzar con un valor alto es ventajoso para ocupar grandes cantidades de espacio rápidamente. Se agregará al almacenamiento web hasta que exceda el tamaño, luego pasará a una unidad más pequeña. Hace esto hasta que no hay espacio en el almacenamiento web para agregar incluso otro byte. Dado que algunos navegadores permiten una cuota de almacenamiento “ilimitada”, debe haber algo que evite un bucle infinito. Contar un iterador es mucho menos costoso que verificar la longitud del objeto de almacenamiento web a través de JSON.stringify , por lo que después de 2 adiciones de la cadena de 10 MB, podemos considerarlo “ilimitado”.

function checkSize(type)
{
//create a key for each storage entry
var iterator = 0;

//count the iterations for each entry, this will be used for the "unlimited" cases, which would cause an infinite loop
//the iterator counter eliminates the need to stringify the entire storage on each iteration and will break at ~20MB
var arr_iterator = 0;

//iterate over the array, from largest object to smallest
for (j = length - 1; j >= 0; j--)
{
//reset array iterator
arr_iterator
= 0;

//iterate until the data can no longer be added to the the web storage
while (addData(type, iterator++, arr[j]))
{
//increment the iterator
arr_iterator
++;

//if we have added ~20MB, then this is considered "unlimited"
if (j == length - 1 && arr_iterator >= 2)
return;
}
}
}

El método addData no verifica el tamaño actual (fuera de IE, que no arroja) y solo maneja el error de tamaño excesivo si ocurre.

function addData(type, key, data)
{
//add data to new key, or replace value if the key already exists with new data
try
{
//error isn't thrown in MSIE
if (isIE)
{
if (getRemainingSpace(type) - data.length <= 0)
return false;
}

//add the value to the key, equivalent to localStorage.setItem('key', 'value')
window
[type][key] = data;
return true;
}
catch (e)
{
return false;
}
}

Los métodos auxiliares restantes: getRemaininSpace se utiliza para comprobar el tamaño en IE. El tamaño de almacenamiento utiliza JSON.stringify para obtener el tamaño del objeto de almacenamiento web. Y StopWatch cuenta el número de milisegundos para ejecutar la prueba.

function getRemainingSpace(type)
{
//return the number of bytes still available in localStorage
if (isIE)
//only IE supports this function
return window[type].remainingSpace;
}

function storageSize(type)
{
//use stringify to determine the size of the web storage object
return JSON.stringify(window[type]).length;
}

function StopWatch()
{
//object that will be used to time our tests
this.startTime = false;
this.stopTime = false;
this.elapsedTime = false;

this.start = function()
{
this.startTime = new Date().getTime();
}
this.stop = function()
{
this.stopTime = new Date().getTime();
this.elapsedTime = this.stopTime - this.startTime;
}
}

Esta prueba se ejecuta (en mi máquina) en menos de 200 ms en todos los navegadores que he probado. Los resultados son los mismos que encontré en la Prueba de soporte de almacenamiento web . La verdadera ventaja aquí es la velocidad a la que se reduce el tamaño de la caché y se evitan propiedades costosas o el diccionario.

¡Lecciones importantes!

* No se requiere jQuery.

* IE no arrojará cuando se exceda la cuota de tamaño, pero ofrece una práctica función de espacio restante (ventana [{storageType}]. ResidentSpace).

* Firefox comparte localStorage y sessionStorage, con esto quiero decir que si tiene 4 MB en localStorage, entonces 1 MB está disponible para sessionStorage. Otros navegadores permiten la doble inmersión.

* Algunos navegadores permiten un almacenamiento ilimitado de sesiones, Safari (al menos para Windows) es uno de estos navegadores.

* La detección de agente de usuario no siempre es confiable. Buscar funciones suele ser una mejor opción. Para esta aplicación en particular, solo IE ha tenido un comportamiento extraño.