2009-06-08 10 views
5

Quiero comprimir los resultados de las consultas de la base de datos antes de agregarlas a la memoria caché.Cómo comprimir una instancia de objeto .net usando gzip

Quiero ser capaz de comprimir cualquier tipo de referencia.

tengo una versión de trabajo de esta para la compresión de cuerdas .. la idea basada en la entrada del blog de Scott Hanselman 's http://shrinkster.com/173t

alguna idea para comprimir un objeto .NET?

Sé que será una de sólo lectura caché ya que los objetos en la memoria caché sólo será matrices de bytes ..

Respuesta

20

Esto no funcionará para cualquier tipo referencia. Esto funcionará para tipos serializables. Conectar un BinaryFormatter a una corriente de compresión que se canaliza a un archivo:

var formatter = new BinaryFormatter(); 
using (var outputFile = new FileStream("OutputFile", FileMode.CreateNew)) 
using (var compressionStream = new GZipStream(
         outputFile, CompressionMode.Compress)) { 
    formatter.Serialize(compressionStream, objToSerialize); 
    compressionStream.Flush(); 
} 

Se puede usar un MemoryStream para almacenar el contenido en la memoria, en lugar de escribir en un archivo. Sin embargo, dudo que esta sea realmente una solución efectiva para un caché.

+1

gracias esto ha sido muy útil, ¿cómo se vería la descompresión ... nunca antes se había usado BinaryFormatter? –

+0

Gracias por hacer esto fácilmente copiar + pastable en mi código. Formateo las cosas con la suficiente frecuencia que esto es ahora solo un fragmento que puedo encontrar fácilmente en Google. +1 –

3

¿Qué tipo de objetos está poniendo en el caché? ¿Son objetos tipeados? O cosas como DataTable? Para DataTable, entonces quizás almacene como xml comprimido a través de GZipStream. Para objetos tipeados (entidades), probablemente necesite serializarlos.

Usted podría utilizar BinaryFormatter y GZipStream, o usted podría utilizar algo como protobuf-net serialización (gratuito), que ya es muy compacto (añadiendo GZipStream normalmente hace que los datos más grande - que es típico de la densa binario). En particular, la ventaja de cosas como protobuf-net es que obtiene el tamaño reducido sin tener que pagar el costo de descompresión de la CPU durante la deserialización. En some testsantes de agregando GZipStream, era 4 veces más rápido que BinaryFormatter. Agregue el tiempo extra en BinaryFormatter para GZip y debe ganar por un margen considerable margen.

2

Acabo de agregar compatibilidad con GZipStream para mi aplicación hoy, así puedo compartir algunos códigos aquí;

serialización:

using (Stream s = File.Create(PathName)) 
{ 
    RijndaelManaged rm = new RijndaelManaged(); 
    rm.Key = CryptoKey; 
    rm.IV = CryptoIV; 
    using (CryptoStream cs = new CryptoStream(s, rm.CreateEncryptor(), CryptoStreamMode.Write)) 
    { 
     using (GZipStream gs = new GZipStream(cs, CompressionMode.Compress)) 
     { 
      BinaryFormatter bf = new BinaryFormatter(); 
      bf.Serialize(gs, _instance); 
     } 
    } 
} 

Deserialización:

using (Stream s = File.OpenRead(PathName)) 
{ 
    RijndaelManaged rm = new RijndaelManaged(); 
    rm.Key = CryptoKey; 
    rm.IV = CryptoIV; 
    using (CryptoStream cs = new CryptoStream(s, rm.CreateDecryptor(), CryptoStreamMode.Read)) 
    { 
     using (GZipStream gs = new GZipStream(cs, CompressionMode.Decompress)) 
     { 
      BinaryFormatter bf = new BinaryFormatter(); 
      _instance = (Storage)bf.Deserialize(gs); 
     } 
    } 
} 

NOTA: si utiliza CryptoStream, es poco importante que la cadena de (des) compresión y (de) crypting derecha de esta manera, porque querrás perder tu entropía ANTES de que el cifrado genere ruido a partir de tus datos.

Cuestiones relacionadas