2016-06-23 9 views
3

Ich habe ein Python-Programm geschrieben, um große Dateien über UDP zu senden und zu empfangen. Im Moment kann ich Geschwindigkeiten von etwa 0,01 GB/s erreichen, wenn ich zwischen zwei Computern mit einem 10 Gigabit Ethernet-Kabel umziehe. Ich möchte diese Geschwindigkeit deutlich verbessern, bin mir aber nicht sicher, was der beste Ansatz ist.Der beste Weg, UDP-Übertragungsgeschwindigkeiten mit Python zu verbessern?

Für was es wert ist, muss ich UDP für die Übertragung verwenden. Das Programm, das ich geschrieben habe, ist lediglich ein Test für ein größeres Projekt, und das Gerät, das die Daten für dieses Projekt sendet, kann keinen TCP-Stream verwenden. Außerdem konzentriere ich mich in erster Linie auf den besten Weg, Datagramme schnell zu empfangen, oder zumindest den besten Weg, um sicherzustellen, dass der Empfänger nicht dort ist, wo Engpässe auftreten.

Momentan arbeitet mein Programm, indem es eine große Datei in mehrere Teile aufteilt, die zu den Datagrammen werden, die gesendet werden. Diese Datagramme werden gesendet, und dann führt der Empfänger einige Dinge durch, um sicherzustellen, dass er die richtigen Daten erhält und sie entsprechend anordnet.

Senden-Code (abgespeckte zu den Wurzeln)

buf = 32000 #Size of each chunk/packet 
s = socket.socket(socket.AF_INET,socket.SOCK_DGRAM) 
host ="127.0.0.1" 
port = 5005 
addr = (host,port)  

def read_in_chunks(infile, chunk_size=buf): 
"""Chunk the file before we send it. 
Arguments: 
infile -- the file to chunk 
chunk_size -- the size of the chunk in bytes (default 32KB) 
""" 
    while True: 
     chunk = infile.read(chunk_size) 
     if chunk: 
      yield chunk 
     else: 
      # The chunk was empty, which means we're at the end of the file 
      return 

def run(): 
    for chunk in read_in_chunks(f): 
     if(s.sendto(chunk,addr) and s.sendto(id,addr)): 
      #Some acknowledgment stuff - removed for clarity (also noted to not impact performance) 
      local_ID += 1 

-Code empfangen:

UDP_IP = "127.0.0.1" 
UDP_PORT = 5005 
buf = 32000 # Buffer size in bytes for each chunk 
sock = socket.socket(socket.AF_INET, # Internet 
       socket.SOCK_DGRAM) # UDP 
sock.bind((UDP_IP, UDP_PORT)) 

try: 
    while(dataChunk): 
     actualNumChunks += 1 
     f.write(dataChunk) 
     sock.settimeout(2) 
     dataChunk, addr = sock.recvfrom(buf) 
     packID, junkAddr = sock.recvfrom(buf) 
     packIDString = str(packID) 
except socket.timeout: 
    f.close() 
    sock.close() 
    print "File received!" # --KEEP 
    print "A total of " + str(actualNumChunks) +" chunks were received"   --KEEP 

Ich bin nicht sicher, ob mein Code, wenn die Optimierung der Ausgabe ist (noch nicht getestet werden), oder wenn es gibt eine andere (bessere?) Möglichkeit, die Geschwindigkeit für die Dateiübertragung zu erhöhen. Ich entschuldige mich, wenn die Details hier spärlich sind, aber lassen Sie mich wissen, wenn Sie weitere Informationen benötigen.

Danke!

Antwort

0

einige Ansätze, um zu versuchen:

  1. Vielfältige Paketgrößen (je nach MTU, könnte bewirken, dass der Brocken auf mehrere Pakete fragmentiert werden, oder könnte zu klein sein, optimal um das Rohr zu verwenden)
  2. lesen Datei in den Speicher (die Netzwerkgeschwindigkeit kann 10gbps sein, aber die Festplatte ist viel langsamer, besonders wenn es keine SSD ist - typischerweise eine Größenordnung oder langsamer), beginnt mit dem Senden, nachdem alles zwischengespeichert wurde. Sie können versuchen, denselben Datenblock mehrmals zu senden, um zu prüfen, ob dies der Engpass ist.
  3. Komprimierung könnte helfen. ZLIB ist sehr sehr sehr schnell, und bedeuten würde man viel mehr Daten in viel weniger Zeit,

Andere Punkte übertragen könnte:

  • Paketverlust und Bestellung könnte eine ordnungsgemäße Übertragung problematisch machen, auch in eine einfache 1-zu-1-Verbindung. Sie benötigen eine Fehlererkennung/-wiederholung, damit dies funktioniert.
  • Kernel/Benutzermodus Änderungen können Sie langsam nach unten (zu bezweifeln, und das ist super Mikro-Optimierung)
+0

Dank. Eine neue Anmerkung: Ich habe mit Paketgrößen herumgebastelt und die MTU gewechselt, und sie scheinen zu funktionieren, aber als ich das Programm mit der 10GigE Verbindung getestet habe, musste ich eine stark reduzierte Paketgröße (~ 14000 gegenüber der ursprünglichen 32000) verwenden das funktionierte auf dem lokalen 127 IP). Die MTU max beträgt ungefähr 9000 oder so für die NIC, die wir haben. Auch für Punkt 2 meinst du, dass ich die Datei vor dem Senden vollständig einlesen sollte? Könnten Sie den Testansatz, den Sie erwähnt haben, etwas genauer beschreiben? Und schlagen Sie für Punkt 3 vor, die komprimierte Datei als Ganzes zu senden oder komprimierte Stücke zu erstellen? – Swoldier

+0

1. Sie können die MTU sowohl für die Quell- als auch für die Ziel-NICs ändern. 2.Versuchen Sie zu testen, ob dies der Engpass ist, indem Sie einen Datenblock erstellen und in vielen Paketen senden, als ob die Datei aus unendlichen Wiederholungen dieses Datenblocks besteht. Das würde bedeuten, dass Sie die Daten aus dem RAM und nicht von der Festplatte lesen und Ihnen zeigen sollten, ob das der Flaschenhals ist oder ob Sie woanders liegen. 3. Komprimierte Chunks funktionieren wahrscheinlich genauso gut wie die gesamte Datei und würden bedeuten, dass Sie sofort mit dem Senden beginnen können - ich würde also sagen, die Chunks komprimieren. – advance512

+0

Bitte teilen Sie uns Ihre Ergebnisse mit und markieren Sie diese Frage auch als beantwortet, wenn Sie das Gefühl haben, Ihre Antwort zu erhalten. – advance512