Pregunta

Así que tengo una cantidad "grande" de archivos ASCII "muy grandes" de datos numéricos (gigabytes en total), y mi programa necesitará procesarlos en su totalidad de forma secuencial al menos una vez.

¿Algún consejo sobre almacenar/cargar los datos?He pensado en convertir los archivos a binario para hacerlos más pequeños y cargarlos más rápido.

¿Debo cargar todo en la memoria de una vez?
Si no es así, ¿abrir es una buena forma de cargar los datos parcialmente?
¿Cuáles son algunos consejos de eficiencia relevantes para Java?

¿Fue útil?

Solución

Entonces, ¿qué pasa si el procesamiento requiere saltar entre los datos de múltiples archivos y múltiples buffers?¿La apertura y cierre constante de archivos binarios resultará costosa?

Soy un gran fan de 'E/S asignada en memoria', también conocido como 'búferes de bytes directos'.En Java se llaman Búfers de bytes asignados son parte de java.nio.(Básicamente, este mecanismo utiliza el sistema de paginación de memoria virtual del sistema operativo para 'mapear' sus archivos y presentarlos mediante programación como buffers de bytes.El sistema operativo gestionará el movimiento de bytes hacia/desde el disco y la memoria de forma automática y muy rápida.

Sugiero este enfoque porque a) funciona para mí y b) le permitirá concentrarse en su algoritmo y permitirá que la JVM, el sistema operativo y el hardware se encarguen de la optimización del rendimiento.Con demasiada frecuencia, ellos saben qué es mejor mejor que nosotros, los humildes programadores.;)

¿Cómo usarías los MBB en tu contexto?Simplemente cree un MBB para cada uno de sus archivos y léalos como mejor le parezca.Sólo necesitarás almacenar tus resultados..

POR CIERTO:¿Con cuántos datos estás tratando, en GB?Si tiene más de 3-4 GB, entonces esto no funcionará para usted en una máquina de 32 bits, ya que la arquitectura de la plataforma defiende la implementación de MBB en el espacio de memoria direccionable.Una máquina y un sistema operativo de 64 bits le llevarán a 1 TB o 128 TB de datos asignables.

Si está pensando en el rendimiento, entonces conozca a Kirk Pepperdine (un gurú del rendimiento de Java algo famoso). Él está involucrado en un sitio web, www.JavaPerformanceTuning.com, que tiene más detalles sobre MBB: Consejos de rendimiento de NIO y otras cosas relacionadas con el rendimiento de Java.

Otros consejos

Quizás quieras echar un vistazo a las entradas en el Proyecto de amplio buscador (haz una búsqueda en google para "buscador amplio" java).

El buscador amplio implica leer muchas líneas en archivos de registro, así que mire las implementaciones de Java y vea qué funcionó y qué no funcionó allí.

Puede convertir a binario, pero luego tendrá más de 1 copia de los datos, si necesita conservar el original.

Puede resultar práctico crear algún tipo de índice sobre los datos ascii originales, de modo que si necesita revisar los datos nuevamente, pueda hacerlo más rápido en ocasiones posteriores.

Para responder a sus preguntas en orden:

¿Debo cargar todo en la memoria de una vez?

No si no es necesario.para algunos archivos, es posible que pueda hacerlo, pero si solo está procesando secuencialmente, simplemente haga algún tipo de lectura en búfer de los elementos uno por uno, almacenando lo que necesite a lo largo del camino.

Si no es así, ¿abrir es una buena forma de cargar los datos parcialmente?

BufferedReaders/etc es lo más simple, aunque puede profundizar en FileChannel/etc para usar E/S asignadas en memoria para recorrer ventanas de datos a la vez.

¿Cuáles son algunos consejos de eficiencia relevantes para Java?

¡Eso realmente depende de lo que estés haciendo con los datos en sí!

Sin ninguna idea adicional sobre qué tipo de procesamiento está ocurriendo, aquí hay algunas ideas generales de cuando hice un trabajo similar.

  1. Escriba un prototipo de su aplicación (tal vez incluso "una para desechar") que realice alguna operación arbitraria en su conjunto de datos.Mira lo rápido que va.Si la cosa más simple e ingenua que se te ocurra es aceptablemente rápida, ¡no te preocupes!

  2. Si el enfoque ingenuo no funciona, considere preprocesar los datos para que las ejecuciones posteriores se ejecuten en un período de tiempo aceptable.Mencionas tener que "saltar" bastante en el conjunto de datos.¿Hay alguna manera de preprocesar eso?O bien, un paso de preprocesamiento puede ser generar aún más datos (datos de índice) que proporcionen información de ubicación con precisión de bytes sobre secciones críticas y necesarias de su conjunto de datos.Luego, su ejecución de procesamiento principal puede utilizar esta información para saltar directamente a los datos necesarios.

Entonces, para resumir, mi enfoque sería probar algo simple ahora mismo y ver cómo se ve el rendimiento.Quizás todo esté bien.De lo contrario, considere procesar los datos en varios pasos, guardando las operaciones más costosas para un preprocesamiento poco frecuente.

No "cargue todo en la memoria".Simplemente realice accesos a archivos y deje que la memoria caché de la página del disco del sistema operativo decida cuándo puede extraer cosas directamente de la memoria.

Esto depende mucho de los datos del archivo.Los grandes mainframes han estado realizando procesamiento de datos secuencial durante mucho tiempo, pero normalmente no utilizan el acceso aleatorio a los datos.Simplemente lo dibujan en una línea a la vez y lo procesan mucho antes de continuar.

Para el acceso aleatorio, suele ser mejor crear objetos con contenedores de almacenamiento en caché que sepan en qué parte del archivo se encuentran los datos que necesitan construir.Cuando es necesario, leen esos datos y los construyen ellos mismos.De esta manera, cuando la memoria es escasa, puedes empezar a eliminar cosas sin preocuparte demasiado por no poder recuperarlas más tarde.

Realmente no nos has dado suficiente información para ayudarte.¿Necesita cargar cada archivo en su totalidad para poder procesarlo?¿O puedes procesarlo línea por línea?

Es probable que cargar un archivo completo a la vez dé como resultado un rendimiento deficiente incluso para archivos que no son muy grandes.Su mejor opción es definir un tamaño de búfer que funcione para usted y leer/procesar los datos un búfer a la vez.

He descubierto que Informatica es una herramienta de procesamiento de datos excepcionalmente útil.La buena noticia es que las versiones más recientes incluso permiten transformaciones de Java.Si se trata de terabytes de datos, podría ser el momento de adquirir las mejores herramientas ETL.

Supongo que quieres hacer algo con los resultados del procesamiento aquí, como almacenarlos en algún lugar.

Si sus datos numéricos se muestrean regularmente y necesita realizar un acceso aleatorio, considere almacenarlos en un árbol cuádruple.

Recomiendo aprovechar fuertemente las expresiones regulares y buscar en el "nuevo" paquete IO nio para una entrada más rápida.Entonces debería ir tan rápido como se pueda esperar de manera realista que se vayan los Gigabytes de datos.

Si es posible, introduzca los datos en una base de datos.Luego podrá aprovechar toda la indexación, el almacenamiento en caché, la fijación de memoria y otras funciones disponibles allí.

Si necesita acceder a los datos más de una vez, cárguelos en una base de datos.La mayoría de las bases de datos tienen algún tipo de utilidad de carga masiva.Si todos los datos caben en la memoria y no necesita guardarlos ni acceder a ellos con tanta frecuencia, probablemente pueda escribir algo simple en Perl o su lenguaje de programación favorito.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top