Pregunta

¿Alguien puede recomendar si debería hacer algo como:

os = new GzipOutputStream(new BufferedOutputStream(...));

o

os = new BufferedOutputStream(new GzipOutputStream(...));

¿Qué es más eficiente? ¿Debo usar BufferedOutputStream en absoluto?

¿Fue útil?

Solución

  

¿Qué orden debo utilizar GzipOutputStream y BufferedOutputStream

Para las corrientes de objetos, me encontré con que envolver la corriente tampón alrededor de la corriente gzip tanto de entrada como de salida era casi siempre significativamente más rápido. El más pequeño de los objetos, el mejor este hecho. Mejor o igual en todos los casos, entonces no hay flujo de buffer.

ois = new ObjectInputStream(new BufferedInputStream(new GZIPInputStream(fis)));
oos = new ObjectOutputStream(new BufferedOutputStream(new GZIPOutputStream(fos)));

No obstante , para el texto y flujos de bytes consecutivos, me pareció que era un cara o cruz - con la corriente gzip alrededor de la corriente tamponada siendo sólo un poco mejor. Pero mejor en todos los casos a continuación, sin corriente tamponada.

reader = new InputStreamReader(new GZIPInputStream(new BufferedInputStream(fis)));
writer = new OutputStreamWriter(new GZIPOutputStream(new BufferedOutputStream(fos)));

Me encontré con cada versión de 20 veces y corté la primera pasada y promedió el resto. También probé tamponada con gzip-tamponada, que fue ligeramente mejor para los objetos y peor para el texto. No jugué con tamaños de búfer en absoluto.


Para los flujos de objetos, he probado 2 archivos de objetos serializados en los años 10 de megabytes. Para el archivo más grande (38MB), era 85% más rápido en la lectura (0,7 frente al 5,6 segundos), pero en realidad un poco más lento para escribir (5,9 y 5,7 segundos). Estos objetos tenían algunos grandes conjuntos en los que puede haber significado escrituras más grandes.

method       crc     date  time    compressed    uncompressed  ratio
defla   eb338650   May 19 16:59      14027543        38366001  63.4%

En el archivo más pequeño (18mb), que era el 75% más rápido para leer (1,6 frente a 6,1 segundos) y un 40% más rápido para escribir (2,8 frente a 4,7 segundos). Contenía un gran número de pequeños objetos.

method       crc     date  time    compressed    uncompressed  ratio
defla   92c9d529   May 19 16:56       6676006        17890857  62.7%

En el texto de lectura / escritura he utilizado un archivo de texto CSV 64mb. La corriente de gzip alrededor de la corriente tamponada era 11% más rápido para la lectura (950 frente a 1070 milisegundos) y ligeramente más rápido cuando la escritura (7,9 frente a 8,1 segundos).

method       crc     date  time    compressed    uncompressed  ratio
defla   c6b72e34   May 20 09:16      22560860        63465800  64.5%

Otros consejos

GZIPOutputStream ya viene con una memoria intermedia incorporada. Por lo tanto, no hay necesidad de poner un BufferedOutputStream justo al lado de la cadena. excelente respuesta de gojomo ya proporciona una guía sobre dónde colocar el búfer.

El tamaño de búfer predeterminado para GZIPOutputStream está a sólo 512 bytes, por lo que tendrá que aumentar la cantidad hasta 8K 64K o incluso a través del parámetro constructor. El tamaño de búfer predeterminado para BufferedOutputStream es 8K, por lo que se puede medir una ventaja cuando se combina el valor por defecto GZIPOutputStream y BufferedOutputStream. Esta ventaja también se puede lograr mediante adecuadamente dimensionado memoria intermedia integrada del GZIPOutputStream.

Así que, para responder a su pregunta: "? ¿Debo usar BufferedOutputStream en absoluto" → No, en su caso, no debería usarlo, pero en su lugar establecer el búfer de la GZIPOutputStream a por lo menos 8K.

El búfer ayuda cuando el destino final de los datos es mejor lectura / escrito en trozos más grandes que su código de otro modo empujarlo. Por lo que generalmente quiere que el almacenamiento temporal sea lo más cerca de la más grandes trozos-lugar-que-quiere-. En sus ejemplos, esa es la elididas "...", por lo envuelven BufferedOutputStream con el GZIPOutputStream. Y, ajustar el tamaño del búfer BufferedOutputStream para que coincida con lo que las pruebas muestran que funciona mejor con el destino.

Dudo BufferedOutputStream en el exterior ayudaría mucho, en todo caso, a lo largo sin almacenamiento temporal explícita. Por qué no? El GZIPOutputStream hará su escritura () s de "..." en los trozos del mismo tamaño si el búfer fuera está presente o no. Así que no hay optimización de "..." posible; le pegan con qué tamaños GZIPOutputStream escritura () s.

Tenga en cuenta también que está utilizando la memoria de manera más eficiente por la precarga de los datos comprimidos en lugar de los datos sin comprimir. Si sus datos a menudo acheives compresión 6X, el buffer 'interior' es equivalente a un buffer de 'fuera' 6X tan grande.

Normalmente quieren una memoria intermedia cerca de su FileOutputStream (suponiendo que es lo que representa ...) para evitar demasiadas llamadas en el sistema operativo y el acceso al disco frecuente. Sin embargo, si usted está escribiendo un montón de pequeños trozos a la GZIPOutputStream que podría beneficiarse de un buffer alrededor GZIPOS también. La razón es que el método de escritura en GZIPOS está sincronizado y también lleva a algunas otras llamadas sincronizados y un par de nativa (JNI) llama (para actualizar el CRC32 y hacer la compresión real). Estos se suman sobrecarga adicional por llamada. Así que en ese caso, yo diría que se beneficiará de las dos memorias intermedias.

Le sugiero que pruebe un punto de referencia fácil de medir el tiempo que tarda en comprimir un archivo de gran tamaño y ver si se hace mucha diferencia. GZIPOutputStream tiene buffering, pero es un búfer más pequeño. Haría el primero con un buffer de 64 K, pero puede encontrarse con que hacer las dos cosas es mejor.

Lee el javadoc, y descubrirá que el BIS se utiliza para amortiguar bytes leídos desde alguna fuente original. Una vez que obtenga los bytes sin formato que desea comprimir ellos por lo que envuelve BPI con un SIG. No tiene sentido para amortiguar la salida de un GZIP, porque uno tiene que pensar qué pasa con GZIP de amortiguación, que va a hacer eso?

new GzipInputStream( new BufferedInputStream ( new FileInputXXX
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top