Problema de rendimiento de Java con LinkedBlockingQueue -- java campo con performance campo con multithreading campo con queue camp Relacionados El problema

Java performance problem with LinkedBlockingQueue


15
vote

problema

Español

Este es mi primer post en StackOverFlow ... Espero que alguien pueda ayudarme

Tengo una gran regresión de rendimiento con Java 6 fighter fight_number win 0 A 1 0 1 A 2 0 2 A 3 1 3 A 4 1 4 B 1 1 5 B 2 1 6 B 3 0 7 C 1 1 8 C 2 1 9 . En el primer hilo genero algunos objetos que presiono a la cola. En el segundo hilo saco estos objetos. La regresión de rendimiento se produce cuando el método grouper = (df.win != df.win.shift()).cumsum() df['streak'] = df.groupby(grouper).cumsum() 0 del grouper = (df.win != df.win.shift()).cumsum() df['streak'] = df.groupby(grouper).cumsum() 1 se llama con frecuencia. Monitoreé todo el programa y el método product22 reclamó la mayor cantidad de tiempo en general. Y el rendimiento va de ~ 58mb / s a ​​0.9mb / s ...

La cola POP y tome métodos llamados AR con un método estático de esta clase

  grouper = (df.win != df.win.shift()).cumsum() df['streak'] = df.groupby(grouper).cumsum() 3  

¿Cómo puedo sintonizar el método product24 para realizar al menos 25 MB / s, o si hay otra clase que pueda usar, que bloqueará cuando la "cola" esté llena o vacía.

Amable Saludos

bart

P.s.: Lo siento por mi mal inglés, soy de Alemania;)

Original en ingles

this is my first post on stackoverflow... I hope someone can help me

I have a big performance regression with Java 6 LinkedBlockingQueue. In the first thread i generate some objects which i push in to the queue In the second thread i pull these objects out. The performance regression occurs when the take() method of the LinkedBlockingQueue is called frequently. I monitored the whole program and the take() method claimed the most time overall. And the throughput goes from ~58Mb/s to 0.9Mb/s...

the queue pop and take methods ar called with a static method from this class

public class C_myMessageQueue {      private static final LinkedBlockingQueue<C_myMessageObject> x_queue = new LinkedBlockingQueue<C_myMessageObject>( 50000 );      /**      * @param message      * @throws InterruptedException      * @throws NullPointerException      */     public static void addMyMessage( C_myMessageObject message )             throws InterruptedException, NullPointerException {         x_queue.put( message );     }      /**      * @return Die erste message der MesseageQueue      * @throws InterruptedException      */     public static C_myMessageObject getMyMessage() throws InterruptedException {         return x_queue.take();     } } 

how can I tune the take() method to accomplish at least 25Mb/s, or is there a other class I can use which will block when the "queue" is full or empty.

kind regards

Bart

P.S.: sorry for my bad english, I'm from Germany ;)

           
       
       

Lista de respuestas

17
 
vote
vote
La mejor respuesta
 

El hilo de su productor simplemente pone más elementos que el consumidor consume , por lo que la cola finalmente llega a su límite de capacidad, por lo que el productor espera.

Consolidando mi respuesta original ya que ahora tenemos básicamente la imagen completa:

  • Usted presiona el límite de rendimiento inherente del LinkedBlockingQueue (cada cola tiene una) haciendo un take()s65 S, donde incluso continúe take()s , con cero procesamiento adicional, no puede mantenerse al día. (Por cierto, esto demuestra que en esta estructura, en su JVM y la máquina de todos modos, ponga () s, al menos ligeramente más costosos que las lecturas).
  • Dado que hay una cerradura particular que los consumidores se bloquean, poniendo más hilos de consumo, no podrían ayudar (si su consumidor estaba haciendo un procesamiento y que estaba eliminando el rendimiento, y luego agregar más consumidores ayudaría. Hay mejores implementaciones de colas para Un escenario con más de un consumidor (o productores), podría intentar SynchronousQueue , ConcurrentLinkedQueue , y el próximo TransferQueue de JSR166Y).

Algunas sugerencias:

  • Trate de hacer objetos más gruesos, de modo que la sobrecarga de la cola se equilibra con el trabajo real que se descarga del hilo productor (en su caso, parece que crea mucha comunicación por encima de los objetos que representan importantes insignificantes de trabajo)
  • También podría hacer que el productor ayude al consumidor al descargar algunos trabajos de consumo (no mucho tiempo para esperar cuando haya trabajo por hacer).

/ actualizado después de que John W. le señaló correctamente mi respuesta original fue engañada

 

Your producer thread simply puts more elements than the consumer consumes, so the queue eventually hits its capacity limit, thus the producer waits.

Consolidating my original answer since now we have basically the full picture:

  • You hit the inherent throughput limit of the LinkedBlockingQueue (every queue has one) by doing extremely fast put()s, where even continual take()s, with zero further processing, cannot keep up. (By the way this shows that in this structure, on your JVM and machine anyway, put()s are at least slightly more costly than the reads).
  • Since there is a particular lock that consumers lock, putting more consumer threads could not possibly help (if your consumer was actually doing some processing and that was bounding the throughput, then adding more consumers would help. There are better queue implementations for a scenario with more than one consumers (or producers), you could try SynchronousQueue, ConcurrentLinkedQueue, and the upcoming TransferQueue of jsr166y).

Some suggestions:

  • Try to make more coarse-grained objects, so that the overhead of queueing each is balanced with the actual work that is offloaded from the producing thread (in your case, it seems you create much communication overhead for objects that represent negligible amounts of work)
  • You could also have the producer help the consumer by offloading some consuming work (not much point in waiting idly when there is work to be done).

/updated after John W. rightly pointed out my original answer was misleading

 
 
         
         
5
 
vote

Por lo general, recomendaría no usar un LinkedBlockingQueue en un área de código sensible al rendimiento, use un ArrayBlockingQueue. Le dará un perfil de recolección de basura mucho mejor y es más amigable para el caché que el LinkedBlockingQueue.

Pruebe el ArrayBlockingQueue y mida el rendimiento.

La única ventaja de LinkedBlockingQueue es que puede ser ilimitada, sin embargo, esto rara vez lo desea. Si tiene un caso en el que un consumidor falla y las colas comienzan a hacer una copia de seguridad, habiendo colas limitadas, permite que el sistema se degrade con gracia, en caso de que se produzcan a los hombres que puedan ocurrir si las colas están sin límites.

 

I would generally recommend not using a LinkedBlockingQueue in a performance sensitive area of code, use an ArrayBlockingQueue. It will giving a much nicer garbage collection profile and is more cache friendly than the LinkedBlockingQueue.

Try the ArrayBlockingQueue and measure the performance.

The only advantage of the LinkedBlockingQueue is that it can be unbounded, however this is rarely what you actually want. If you have a case where a consumer fails and queues start backing up, having bounded queues allows the system to degrade gracefully rather risk OutOfMemoryErrors that may occur if queues are unbounded.

 
 
 
 
5
 
vote

Aquí hay un par de cosas para probar:

Reemplace el LinkedBlockingQueue Con un ArrayBlockingQueue . No tiene referencias colgantes y, por lo tanto, se comportan mejor cuando se llena la cola. Específicamente, dada la implementación 1.6 de LinkedBlockingQueue, el GC completo de los elementos no sucederá hasta que la cola realmente se vacía.

Si el lado del productor está constantemente realizando el lado del consumidor, considere usar drain o drainTo para realizar una operación "a granel".

Alternativamente, haga que la cola tome matrices o listas de objetos de mensaje. El productor llena una lista o matriz con objetos de mensaje y cada uno o toma mueve múltiples mensajes con el mismo bloqueo de bloqueo. Piense en ello como una secretaria que le entrega una pila de mensajes "mientras estabas fuera" vs. entregándolos uno a la vez.

 

Here are a couple of things to try:

Replace the LinkedBlockingQueue with an ArrayBlockingQueue. It has no dangling references and so is better behaved when the queue fills up. Specifically, given the 1.6 implementation of LinkedBlockingQueue, full GC of the elements will not happen until the queue actually becomes empty.

If the producer side is consistently out performing the consumer side, consider using drain or drainTo to perform a "bulk" take operation.

Alternatively, have the queue take arrays or Lists of message objects. The the producer fills a List or array with message objects and each put or take moves multiple messages with the same locking overhead. Think of it as a secretary handing you a stack of "While you were out" messages vs. handing them to you one at a time.

 
 
     
     
1
 
vote

Es difícil decir lo que sucede sin saber algo sobre el proceso de llenado.

Si addMyMessage se llama con menos frecuencia, tal vez debido a un problema de rendimiento en una parte diferente de su aplicación, el método take5 tiene que esperar.

De esa manera, se parece a take es el culpable, pero en realidad es la parte de llenado de su aplicación.

 

It's hard to say what happens without knowing something about the filling process.

If addMyMessage is called less frequently - perhaps because of a performance problem in a whole different part of your application - the take method has to wait.

That way it looks like take is the culprit, but actually it's the filling part of your application.

 
 
 
 
1
 
vote

encontrado esta interesante posterior sobre los problemas de rendimiento debido a la cola Tamaño y recolección de basura.

 

Found this interesting post about performance problems due to queue size and garbage collection.

 
 
0
 
vote

no puedo decir nada seguro. Pero puede intentar cambiar BlockingQueue implementación (al igual que un experimento).

Usted establece la capacidad inicial 50k y use LinkedBlockingQueue . Intente ArrayBlockingQueue Con la misma capacidad, también puede jugar con ArrayBlockingQueue0 Parámetro.

 

Can't tell anything for sure. But you can try to change BlockingQueue implementation (just as an experiment).

You set initial capacity 50k and use LinkedBlockingQueue. Try ArrayBlockingQueue with the same capacity, you can also play with fair parameter.

 
 
   
   
0
 
vote

Si la sobrecarga de rendimiento en bruto para poner y tomar objetos de su bloqueo es su cuello de botella (y no el Problema de productor / consumidor lento ), puede obtener enormes mejoras de rendimiento con lotes de objetos: por ejemplo, en lugar de poner o tomar objetos de grano fino, pone o tome listas de grano grueso de objetos. Aquí hay un fragmento de código:

  ArrayBlockingQueue111  

El lote puede aumentar su rendimiento por un orden de magnitud.

 

If the raw performance overhead for putting and taking object from your blockingqueues is your bottleneck (and not the slow-producer/consumer problem), you can get huge performance improvements with batching of objects: For instance, instead of putting or taking fine-grained objects, you put or take coarse-grained lists of objects. Here is a code snippet:

ArrayBlockingQueue<List<Object>> Q = new ArrayBlockingQueue<List<Object>>();  // producer side List<Object> l = new ArrayList<Object>(); for (int i=0; i<100; i++) {     l.add(i); // your initialization here } Q.put(l);  // consumer side List<Object> l2 = Q.take(); // do something  

Batching can boost your performance by an order of magnitude.

 
 
0
 
vote

Podría ser posible que su solicitud se vea afectada por los cambios relacionados con el bloqueo en Java 6, especialmente la característica de "bloqueo sesgado".

Intente deshabilitarlo utilizando el interruptor ArrayBlockingQueue2 y vea si eso hace una diferencia.

Consulte esto para obtener más información: Java SE 6 Rendimiento Libro blanco: Sección 2.1 .

 

It could be possible that your application is affected by the locking related changes in Java 6, especially the "biased locking" feature.

Try disabling it by using the -XX:-UseBiasedLocking switch and see if that makes a difference.

See this for further information: Java SE 6 Performance White Paper: Section 2.1.

 
 
     
     

Relacionados problema

62  Tamaño límite de la cola <t> En .NET?  ( Limit size of queuet in net ) 
Tengo una cola & lt; t & gt; Objeto que me he iniciado a una capacidad de 2, pero obviamente es solo la capacidad y sigue expandiéndose a medida que agrego ar...

1  BOOST :: LockFree :: ¿Se permite la cola Ejemplo de estructura de datos?  ( Boostlockfreequeue allowed data structure example ) 
BOOST :: LockFree :: Queue tiene algunos recursos para que la estructura de datos se coloque Constructor de copia trivial Asignación trivial destructor...

3  ¿Cómo fusiono dos colas en una cola?  ( How do i merge two queues into one queue ) 
Dadas dos colas que soportan las operaciones enula / push_back, dealesue / pop_front, y tamaño Q1: A1 A2 A3 Q2: B1 B2 B3 ¿Cómo los fusionaré en una ter...

149  Ejecutar la tarea PHP de forma asíncrona  ( Run php task asynchronously ) 
trabajo en una aplicación web algo grande, y el backend está principalmente en PHP. Hay varios lugares en el código donde necesito completar alguna tarea, per...

7  ¿Terminología / convención de nombramiento para operaciones de cola / APIs?  ( Terminology naming convention for queue operations apis ) 
La "cola", o FIFO, es una de las estructuras de datos más comunes y tiene implementaciones nativas en muchos idiomas y marcos. Sin embargo, parece haber poco ...

3  AUDIOQUESTART INFORME INFORME FORMATO NOPPORTADO  ( Audioqueuestart reporting unsupported format ) 
Estoy tratando de obtener la cola de audio que trabaja en una aplicación de iPhone, y cada vez que se llama Audioquestart, le da la "FMT?" código de resultado...

0  Uiactivityindicatorview no gira inmediatamente  ( Uiactivityindicatorview does not spin immediately ) 
Estoy enfrentando un problema extraño sobre la animación de la UIACTUYINGATORVIEWVIEW. Tengo un SplitViewController donde tengo una vista uitable en el lado...

0  PRODUCTOR DE PRODUCTOR SOLO CONSUMIDOR CERRADO GRATUITA C  ( Single producer single consumer lock free queue c ) 
Me pregunto por qué sería incorrecto implementar este tipo de cola de la manera ingenua: #include <stdlib.h> #include <stdio.h> #include <pthread.h> #inclu...

-4  ¿Cómo obtener la suma de todos los elementos aquí?  ( How to get the sum of all the elements in here ) 
def isempty(qu): if qu==[]: return True else: return False def push(qu,item): qu.append(item) if len(qu)==1: front=r...

3  Cola FIBO FIEJO DE FOBERT ET AL: ¿Múltiples consumidores y productores?  ( Fober et al lock free fifo queue multiple consumers and producers ) 
Me preguntaba si la cola FIFO presentaba en el papel de Fober et al. http: // Nedko. arnaudov.name/soft/l17_fober.pdf fue un consumidor múltiple y producir ...




© 2022 respuesta.top Reservados todos los derechos. Centro de preguntas y respuestas reservados todos los derechos