2012-09-03 26 views
7

Actualizar a la publicación original: Un colega me señaló lo que estaba haciendo mal. Daré la explicación en la parte inferior de la publicación, ya que podría ser útil para otros.límites de tasa udp en python?


estoy tratando de obtener una comprensión básica de los límites de rendimiento de la red de los programas en Python y se han topado con una anomalía. El fragmento de código

while 1: 
    sock.sendto("a",target) 

envía paquetes UDP a una máquina de destino, tan rápido como el host enviará. Mido una tasa de envío de poco más de 4000 paquetes por segundo, o 250 us por paquete. Esto parece lento, incluso para un lenguaje interpretado como python (el programa se ejecuta en un opteron AMD de 2 GHz, Linux, versión 2.6.6 de python). He visto un rendimiento mucho mejor en python para TCP, así que esto me parece un poco raro.

Si funciono esto en el fondo y la parte superior corro, me parece que está utilizando Python sólo el 25% de la CPU, lo que sugiere que pitón puede ser retrasar artificialmente la transmisión de paquetes UDP.

¿Alguien más ha experimentado algo similar? ¿Alguien sabe si python limita la velocidad de transmisión de paquetes, y si hay una forma de desactivar ?

BTW, un programa similar de C++ puede enviar más de 200,000 paquetes por segundo, , por lo que no es un límite intrínseco de la plataforma o el sistema operativo.


Por lo tanto, resultó que cometí un error novato tonto. Me olvidé de llamar a gethostbyname explícitamente. En consecuencia, la dirección de destino en el comando sendto contenía un nombre simbólico. Esto desencadenaba una resolución de nombre cada vez que se enviaba un paquete a . Después de arreglar esto, mido una tasa de envío máxima de aproximadamente 120,000 p/s. Mucho mejor.

+2

Todavía sorprendente, habría pensado que la resolución del nombre se almacenaría en caché. Debe seguir adelante y proporcionar su resolución como respuesta. –

Respuesta

0

Es posible que desee publicar un ejemplo de código más completo para que otros puedan repetir su punto de referencia. 250 μs por iteración de ciclo es demasiado lento. Sobre la base de la experiencia diaria con la optimización de Python, esperaría que la parte superior del intérprete de Python estuviera muy por debajo de 1 μs en una máquina moderna. En otras palabras, si el programa C++ está enviando 200k paquetes por segundo, esperaría que Python estuviera en el mismo orden de magnitud de velocidad.

(En vista de lo anterior, las sugerencias de optimización habituales, tales como mover la búsqueda de atributos de sock.sendto fuera del circuito no se aplican aquí porque la lentitud proviene de otra fuente.)

Un buen primer paso a ser para usar strace para verificar qué está haciendo realmente Python. ¿Es un programa de subproceso único o una aplicación multiproceso que podría estar perdiendo tiempo esperando en el GIL? ¿Es sock un socket Python normal o es parte de una API más elaborada? ¿Ocurre lo mismo cuando llama directamente al os.write en el fileno del zócalo?

1

¿Ha intentado primero hacer una connect(), luego usando send() en lugar de sendto()? (UDP connect() simplemente establece la dirección de destino, en realidad no hace una "conexión".) Estoy oxidado con esto, pero creo que Python hace más interpretación en el parámetro de dirección que los sockets C, que podrían estar agregando sobrecarga.