java multithreading lucene java.util.concurrent

Los subprocesos de Java se ralentizan hacia el final del proceso



multithreading lucene (2)

Tengo un programa Java que toma un archivo de texto que contiene una lista de archivos de texto y procesa cada línea por separado. Para acelerar el procesamiento, uso hilos usando un ExecutorService con FixedThreadPool con 24 hilos. La máquina tiene 24 núcleos y 48 GB de RAM.

El archivo de texto que estoy procesando tiene 2.5 millones de líneas. Encuentro que, durante los primeros 2.3 millones de líneas, las cosas funcionan muy bien con una alta utilización de la CPU. Sin embargo, más allá de cierto punto (en torno a las 2.3 líneas), el rendimiento se degenera con solo una CPU en uso y mi programa casi se detiene.

Investigué una serie de causas, me aseguré de que todos los identificadores de archivo estuvieran cerrados y aumenté la cantidad de memoria suministrada a la JVM. Sin embargo, independientemente de lo que cambie, el rendimiento siempre se degrada hacia el final. Incluso probé con archivos de texto que contienen menos líneas y, una vez más, el rendimiento disminuye hacia el final del procesamiento del archivo.

Además de las bibliotecas de concurrencia estándar de Java, el código también hace uso de las bibliotecas de Lucene para el procesamiento y análisis de texto.

Cuando no envan este código, el rendimiento es constante y no degenera hacia el final. Sé que esta es una toma en la oscuridad y es difícil describir lo que está sucediendo, pero pensé que simplemente vería si alguien tiene alguna idea sobre qué podría estar causando esta degeneración en el rendimiento hacia el final.

Editar

Después de los comentarios que he recibido, he pegado un seguimiento de pila aquí . Como puede ver, no parece que ninguno de los hilos esté bloqueando. Además, al crear perfiles, el GC no estaba al 100% cuando las cosas se ralentizaban. De hecho, tanto la utilización de CPU como de GC estuvieron en 0% la mayor parte del tiempo, con la CPU aumentando ocasionalmente para procesar algunos archivos y luego detenerse nuevamente.

Código para ejecutar subprocesos

BufferedReader read = new BufferedReader(new FileReader(inputFile)); ExecutorService executor = Executors.newFixedThreadPool(NTHREADS); String line; while ((line = read.readLine()) != null) { //index each line Runnable worker = new CharikarHashThreader(line, bits, minTokens); executor.execute(worker); } read.close();


Esto suena como un problema de recolección de basura / memoria.

Cuando se ejecuta la recolección de basura, pausa todos los hilos para que el hilo del GC pueda hacer su análisis de "es esta basura coleccionable" sin que nada cambie en él. Mientras se ejecuta el GC, verá exactamente 1 hilo al 100%, los otros hilos estarán atascados en 0%.

Consideraría agregar algunas llamadas a Runtime.freeMemory () (o usar un generador de perfiles) para ver si se produce el "grind stop" durante GC.

También intenté ejecutar tu programa solo en las primeras 10k líneas de tu archivo para ver si funciona.

También vería si tu programa está creando demasiadas cadenas intermedias cuando debería estar usando StringBuilders.

Me parece que necesita un perfil del uso de la memoria.


Inicialmente pensé que también eran problemas de GC, pero no estoy tan seguro de dar la siguiente información.

Incluso probé con archivos de texto que contienen menos líneas y, una vez más, el rendimiento disminuye hacia el final del procesamiento del archivo.

Mi suposición es que los hilos no han salido, pero están bloqueados de alguna manera. Yo recomendaría tomar un dump dump ( kill -QUIT pid bajo * nix o usando jstack ) y ver dónde están los hilos. Esto te ayudará a identificar si están bloqueados en alguna parte.

Sospecho que su programa comienza con 24 subprocesos en ejecución, pero con el tiempo pierde uno y luego otro. Aunque parece que hay una caída dramática de rendimiento al final, me pregunto si el programa se ha vuelto más y más lento desde el principio.

  • Mire si hay tomas sin conexión adecuada o tiempos de espera de IO.
  • ¿Tal vez algún tipo de contención de bloqueo que bloquea hilos?
  • Tal vez algo que Lucene está haciendo es causar controversia o bloquear tus hilos. Como mencionó @GPI, trataría de comentar las llamadas de Lucene y ver si el problema desaparece. Una vez más, un stack-trace también te mostrará esto.

Una vez que determine dónde están bloqueados los hilos, necesitará resolver los problemas de bloqueo, agregar tiempos de espera a las llamadas de red o solucionar el problema.

Espero que esto ayude.