2012-04-09 16 views
6

Tengo un programa que genera una gran cantidad de datos y los pone en una cola para escribir, pero el problema es que genera datos más rápido de lo que estoy escribiendo actualmente (lo que hace que la memoria sea máxima y empiece a ralentizarse). El orden no importa ya que planeo analizar el archivo más tarde.¿Cuál es la forma más rápida de escribir una gran cantidad de datos de la memoria en un archivo?

Miré un poco y encontré algunas preguntas que me ayudaron a diseñar mi proceso actual (pero todavía lo encuentro lento). Aquí está mi código hasta ahora:

//...background multi-threaded process keeps building the queue.. 
FileWriter writer = new FileWriter("foo.txt",true); 
     BufferedWriter bufferWritter = new BufferedWriter(writer); 
     while(!queue_of_stuff_to_write.isEmpty()) { 
      String data = solutions.poll().data; 
      bufferWritter.newLine(); 
      bufferWritter.write(data); 
     } 
     bufferWritter.close(); 

estoy bastante nuevo en la programación, así que tal vez la evaluación de este mal (tal vez un problema de hardware ya que estoy usando EC2), pero hay una volcar muy rápidamente los resultados de cola en un archivo o si mi enfoque está bien, ¿puedo mejorarlo de alguna manera? Como el orden no importa, ¿tiene más sentido escribir en múltiples archivos en múltiples unidades? ¿El enhebrado lo hará más rápido?, Etc. No estoy seguro de que el mejor enfoque y cualquier sugerencia sean geniales. Mi objetivo es guardar los resultados de la cola (lo siento, no enviar a/dev/null :-) y mantener el consumo de memoria lo más bajo posible para mi aplicación (no estoy 100% seguro, pero la cola llena 15gig, por lo que estoy asumiendo que será un archivo de 15gig +).

Fastest way to write huge data in text file Java (escritor se dio cuenta de que debo usar tamponada) Concurrent file write in Java on Windows (me hizo ver que escribe tal multi-threading no fue una gran idea)

+0

Entiendo la velocidad de la CPU> la velocidad del disco duro, por lo que la escritura probablemente siempre perderá en el procesamiento, solo estoy tratando de descubrir cómo ayudar a que la velocidad hd se acerque un poco más a su manejo. –

+0

Mucho depende de lo que sea el cuello de su botella. Sospecho que si maximizas el ancho de banda de tu disco IO (que parece ser tu pregunta) puedes maximizar tu cuenta también (en términos de costo) Estoy de acuerdo en que la escritura múltiple no ayudará mucho. –

+0

Un cálculo aproximado es que 15 GB le costará $ 4 cada vez. –

Respuesta

2

Al mirar ese código, una cosa que me viene a la mente es la codificación de caracteres. Estás escribiendo cadenas, pero en última instancia, son bytes los que van a las transmisiones. Un escritor de codificación de carácter a byte bajo el capó, y lo está haciendo en el mismo hilo que maneja la escritura. Eso puede significar que hay un tiempo dedicado a la codificación que retrasa las escrituras, lo que podría reducir la velocidad a la que se escriben los datos.

Un simple cambio sería el uso de una cola de byte[] en lugar de String, hacer la codificación en los hilos que empujan en la cola, y tienen el código IO utilizar un BufferedOutputStream en lugar de un BufferedWriter.

Esto también puede reducir el consumo de memoria, si el texto codificado ocupa menos de dos bytes por carácter en promedio. Para texto latino y codificación UTF-8, esto generalmente será cierto.

Sin embargo, sospecho que es probable que simplemente esté generando datos más rápido de lo que su subsistema IO puede manejarlo.Tendrá que hacer que su subsistema IO sea más rápido, ya sea usando uno más rápido (si está en EC2, tal vez alquilando una instancia más rápida, o escribiendo en un backend diferente - SQS vs EBS vs disco local, etc.), o mediante la agrupación varios subsistemas IO juntos en paralelo de alguna manera.

0

supongo, siempre y cuando usted produce sus datos de cálculos y hacer no cargues tus datos de otra fuente de datos, escribir siempre será más lento que generar tus datos.

Puede intentar escribir sus datos en varios archivos (no en el mismo archivo -> debido a problemas de sincronización) en varios hilos (pero supongo que eso no solucionará su problema).

¿Es posible que espere a que la parte de escritura de su aplicación termine su operación y continúe con sus cálculos?

Otro enfoque es: ¿Vacía la cola? ¿Soluciona solutions.poll() la cola de soluciones?

0

escribiendo en diferentes archivos usando múltiples hilos es una buena idea. Además, debería considerar configurar el tamaño del buffer BufferedWriters, que puede hacer desde el constructor. Intente inicializar con un búfer de 10 Mb y vea si eso ayuda

+0

¿Lo es? Escribir dos archivos en paralelo con el mismo disco duro mecánico llevará mucho más tiempo que escribir el primero y luego el otro. –

1

Sí, escribir archivos múltiples en múltiples unidades debería ayudar, y si nada más está escribiendo en esas unidades al mismo tiempo, el rendimiento debería escalar linealmente con el número de unidades hasta que ya no sea el cuello de botella. También podría probar algunas otras optimizaciones para aumentar el rendimiento aún más.

Si está generando archivos de gran tamaño y el disco simplemente no puede mantener el ritmo, puede usar un GZIPOutputStream para reducir la salida, lo que a su vez reducirá la cantidad de E/S del disco. Para texto no aleatorio, generalmente puede esperar una relación de compresión de al menos 2x-10x.

//...background multi-threaded process keeps building the queue.. 
    OutputStream out = new FileOutputStream("foo.txt",true); 
    OutputStreamWriter writer = new OutputStreamWriter(new GZIPOutputStream(out)); 
    BufferedWriter bufferWriter = new BufferedWriter(writer); 
    while(!queue_of_stuff_to_write.isEmpty()) { 
     String data = solutions.poll().data; 
     bufferWriter.newLine(); 
     bufferWriter.write(data); 
    } 
    bufferWriter.close(); 

Si va a dar salida a los datos normales (es decir, repetitivas), también puede ser que desee considerar el cambio a un formato de salida diferente - por ejemplo, una codificación binaria de los datos. Dependiendo de la estructura de sus datos, podría ser más eficiente almacenarlos en una base de datos. Si está generando XML y realmente quiere apegarse a XML, debe buscar en un formato Binary XML, como EXI o Fast InfoSet.

Cuestiones relacionadas