2011-08-16 11 views
5

Tengo un servidor retorcido que realiza una tarea "larga" para cada solicitud, por lo que diferimos para enhebrar cada llamada. En cada solicitud, accedo a un recurso común, que se altera durante el proceso. Cada solicitud debe comenzar con los datos originales, por lo que utilizo Deepcopy en el recurso común (mientras invoco una adquisición de bloqueo). Funciona, PERO creo que no es lo suficientemente rápido. Tengo la sensación de que la copia profunda está ralentizando un poco las cosas.Enhebrado trenzado cómo evitar la copia profunda

¿Qué sugerencias tiene cuando se trata de un servidor trenzado con hilos con mutación de recursos?

+0

¿En qué estaba no es lo suficientemente rápido? ¿Su servidor no puede manejar N solicitudes por segundo? ¿A veces una sola solicitud lleva demasiado tiempo? ¿Se vuelve más lento a medida que aumenta el número de solicitudes simultáneas? – stderr

+0

Una sola solicitud no tarda demasiado. No se vuelve más lento ya que aumente el número de solicitudes simultáneas. El tamaño de la agrupación de subprocesos del reactor retorcido está establecido en 25. – Catalin

Respuesta

2

Si lo desea, puede sincronizar el acceso al recurso compartido con threading.Lock tal como lo haría en cualquier otro programa en lugar de copiarlo.

Independientemente, creo que vale la pena comparar su código con y sin la función de profundidad y de otra manera medir para descubrir qué tan bueno/malo es realmente el rendimiento antes de realizar optimizaciones. Quizás la razón por la cual es lenta no tiene nada que ver con la copia profunda.

EDITAR con respecto al uso de bloqueo: Lo que quiero decir es que puede usar un bloqueo de grano más fino alrededor de este recurso. Supongo que tus hilos están haciendo más que acceder a un recurso compartido. Puede tratar de beneficiarse de múltiples hilos de trabajo y luego sincronizar el acceso a la única "sección crítica" que implica escribir en el recurso compartido. También puede investigar haciendo que su recurso compartido sea seguro para los hilos. Por ejemplo, si tiene un objeto compartido, SillyExampleFriendsList:

class SillyExampleFriendsList(object): 
    """Just manipulates a couple lists""" 
    def __init__(self): 
     self._lock = threading.RLock() 
     self._friends = [] 
     self._enemies = [] 

    def unfriend(self, x): 
     # we lock here to ensure that we're never in a state where 
     # someone might think 'x' is both our friend and our enemy. 
     self._lock.acquire() 
     self._friends.remove(x) 
     self._enemies.append(x) 
     self._lock.release() 

El punto aquí es simplemente que el objetivo anterior potencialmente podría ser compartida entre múltiples hilos sin deepcopy por el uso cuidadoso de las cerraduras. No es trivial identificar todos los casos en que esto sea necesario y las estrategias de bloqueo de granularidad fina pueden ser más difíciles de depurar y aún así introducir una sobrecarga.

Dicho esto, es posible que no necesite ningún tipo de subprocesos, bloqueos o deepcopy y sin una evaluación comparativa de su código no está claro si tiene un problema de rendimiento que deba resolverse. Tengo curiosidad por saber qué hace que pienses que tu código debe ser o debe ser más rápido.

+0

Un +1 definitivo para el sentimiento de "referencia y perfil primero". Con demasiada frecuencia las personas optimizan las cosas equivocadas, incluso una vez que saben que algo es realmente lento. – Glyph

+0

Si sincronizo el acceso al recurso con threading.Lock significa que voy a single thread. Benchmarking definitivamente está en TODO. – Catalin

+0

Las operaciones individuales en listas son seguras para hilos en CPython, por lo que 'SharedList' aquí no hace nada útil. –

3

Intente operar con los datos mínimos posibles en sus hilos de trabajo. Pase todos los datos que necesiten como argumentos y tome todos sus resultados como el valor de retorno (el valor con el que se dispara el aplazado) en lugar de como mutaciones a las entradas.

A continuación, integre los resultados en la estructura de datos común en la rosca del reactor.

Esto le permite razonar sobre el trabajo de forma aislada y evitar cualquier bloqueo adicional (lo que genera contención, desacelerando las cosas además de hacerlas más confusas).

+0

¿Tiene algún ejemplo/tutorial para compartir? – Catalin

Cuestiones relacionadas