Python zu langsam? =(

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
jihi
User
Beiträge: 14
Registriert: Montag 29. August 2005, 20:53
Wohnort: Hessen
Kontaktdaten:

Ich hab folgendes Problem:
Hab ein Programm geschrieben, was sich zwischen ein Spiel und den Server schaltet.

Code: Alles auswählen

# -*- coding: cp1252 -*-
from socket import *

# Set the socket parameters
addrc = ("0.0.0.0",23072)
addrs=("84.254.75.8",23110)

hostc="0.0.0.0"
portcl=23072
portcs=23083
hosts="84.254.75.8"
portsl=23082
portss=23110

buf = 1024

# Socket zuständig für Server Verbindung
socks = socket(AF_INET,SOCK_DGRAM)
socks.setblocking(0)
socks.bind(("0.0.0.0",portsl))

# Socket zuständig für Client Verbindung
sockc = socket(AF_INET,SOCK_DGRAM)
sockc.setblocking(0)
sockc.bind((hostc,portcl))

count=0
a=0

## Schleife ################################
while 1:
    datas=0
    datac=0
## Daten von Client an server
    try:
        datac,(hostc,portcs)=sockc.recvfrom(buf)
    except:pass
    if datac:
##        print "CtS:"+datac
        socks.sendto(datac,(hosts,portss))
        count =0
##Daten von Server an Client
    try:
        datas=socks.recv(buf)
    except:pass
    if datas:
##        print "StC:"+datas
        sockc.sendto(datas,(hostc,portcs))
    count+=1
    if count>100000:break
    if count%10000==0:print count,

# Close socket
socks.close()
sockc.close()
Funktioniert auch wunderprächtig, nur lastet Python dann den Computer zu 70% aus, was somit das Spiel völlig ausbremst :(
kann man das irgendwie beschleunigen ?
Oder ist das einfach die Grenze von Python?

(Ich bin mir bewusst, dass Python nicht mit C++, oder Asembler zu vergleichen ist, besonders was Geschwindigkeit angeht. War auch mehr einfach ein Versuch mit Sockets. Aber vielleicht gehts ja doch =)

Edit XT@ngel: Code in Python Tags
mitsuhiko
User
Beiträge: 1790
Registriert: Donnerstag 28. Oktober 2004, 16:33
Wohnort: Graz, Steiermark - Österreich
Kontaktdaten:

Probier mal folgendes:

Code: Alles auswählen

while 1: pass
Lastet deinen Computer perfekt aus ;-)

Zu deinem Problem: Probiers mal mit Threads anstatt einer einfachen While Schleife. Das sollte dann schon flüssiger laufen.
TUFKAB – the user formerly known as blackbird
rayo
User
Beiträge: 773
Registriert: Mittwoch 5. November 2003, 18:06
Wohnort: Schweiz
Kontaktdaten:

Hi

Schau dir mal das modul select an. Da kannst du warten bis der Socket Daten zum lesen oder schreiben hat. Somit sollte die last drastisch sinken.

Code: Alles auswählen

readyForRead, readyForWrite, error = select( [socks,sockc], [socks,sockc], [socks,sockc])

for readingSocket in readForRead:
    print readingSocket.recvfrom(buf)
for writingSocket in readForWrite:
    print writingSocket.sendto(datac,(hosts,portss)) 
Gruss
jihi
User
Beiträge: 14
Registriert: Montag 29. August 2005, 20:53
Wohnort: Hessen
Kontaktdaten:

Das mit den Thread/Threading hab ich leider noch garnicht verstanden :(


Aber:
:?: Hab ich das jetzt richtig verstanden :?:

select wartet, bis Daten ankommen, und gibt dann die Socken zurück, wo Daten vorhanden sind, und wo keine sind, die nicht?

Und wenn ich zwischendurch selber Packets senden möchte, dann muss ich warten, bis bei einem der sockets Daten angekommen sind, oder der Timeout abgelaufen ist?

Ist ja cool :!:
[wenns denn so ist]
[habs noch nicht versuchen können :? ]
ProgChild
User
Beiträge: 210
Registriert: Samstag 9. April 2005, 10:58
Kontaktdaten:

jihi hat geschrieben:Und wenn ich zwischendurch selber Packets senden möchte, dann muss ich warten, bis bei einem der sockets Daten angekommen sind, oder der Timeout abgelaufen ist?
Nein. Select sagt dir auch, welche Sockets zum schreiben bereit sind, wenn du etwas senden möchtest.

Sonst hast du das schon verstanden...
jihi
User
Beiträge: 14
Registriert: Montag 29. August 2005, 20:53
Wohnort: Hessen
Kontaktdaten:

aber wann ist denn ein Socket bereit zum Senden ?
Eigentlich doch immer oder????
Also wenn ich jetzt nicht grade ein Riesen Packet gesendet habe.

Also ist doch der Nutzen von select eigentlich zu Nichte oder?
rayo
User
Beiträge: 773
Registriert: Mittwoch 5. November 2003, 18:06
Wohnort: Schweiz
Kontaktdaten:

wenn du nun z.B. 100kb Daten senden willst, ist er eine Zeit lang nicht bereit zum senden, aber die meiste zeit ist er das eigentlich schon.

Ich würde es über Queues machen, wenn der socket bereit ist zum schreiben holt er die nächste nachricht der queue und schickt diese.

Die Queue ist auch Thread-Safe (sprich aus mehreren Threads ansprechbar ohne probleme).

Code: Alles auswählen

import Queue
writeQueue = Queue.Queue()

while 1:
    readyForRead, readyForWrite, error = select( [socks,sockc], [socks,sockc], [socks,sockc])
    
    for readingSocket in readForRead:
        print readingSocket.recvfrom(buf)
    for writingSocket in readForWrite:
        try:
            data = writeQueue.get(False)
            print writingSocket.sendto(data,(hosts,portss)) 
        except Queue.Empty:
            #keine Daten in der Queue
            pass
Jetzt kannst du irgendwo in einem anderen Thread z.b. writeQueue.put('hallo welt') schreiben und es wird sobald der socket bereit ist abgeschickt.

Gruss
jihi
User
Beiträge: 14
Registriert: Montag 29. August 2005, 20:53
Wohnort: Hessen
Kontaktdaten:

Vielen Dank erstmal =)
hast mir sehr geholfen, werds gleich mal testen :)
jihi
User
Beiträge: 14
Registriert: Montag 29. August 2005, 20:53
Wohnort: Hessen
Kontaktdaten:

:( Leider funktioniert das mit select irgendwie nicht: Obwohl packages ankommen müssten, geht er nicht weiter :?:
Oder funktioniert das ganze nur mit TCP, weil ich benutze UDP :?:

Code: Alles auswählen

# -*- coding: cp1252 -*-
from socket import *
from select import *

# Set the socket parameters
addrc = ("0.0.0.0",23072)
addrs=("84.254.75.8",23110)

hostc="0.0.0.0"
portcl=23072
portcs=23083
hosts="84.254.75.8"
portsl=23082
portss=23110

buf = 1024

# Socket zuständig für Server Verbindung
socks = socket(AF_INET,SOCK_DGRAM)
##socks.setblocking(0)
socks.bind(("0.0.0.0",portsl))

# Socket zuständig für Client Verbindung
sockc = socket(AF_INET,SOCK_DGRAM)
##sockc.setblocking(0)
sockc.bind((hostc,portcl))

count=0
a=0
# Receive messages
while 1:
    ## select soll nur weiter gehn, wenn  Daten ankommen, nicht wenn es bereit zum Senden ist?!
    readyForRead, readyForWrite, error = select([socks,sockc],[], [], 5)
    if readyForRead ==[]: break
    for readingSocket in readyForRead:
        if readingSocket == socks:
            sockc.sendto(readingSocket.recv(buf),(hostc,portcs))
        if readingSocket == sockc:
            datac,(hostc,portcs)=sockc.recvfrom(buf)
            sockc.sendto(datac,(hosts,portss))

# Close socket
socks.close()
sockc.close()
Edit (Leonidas): Code zum zweiten mal in Python-Tags gesetzt (zum ersten mal von XT@ngel), beim nächsten mal selber machen, ok?
rayo
User
Beiträge: 773
Registriert: Mittwoch 5. November 2003, 18:06
Wohnort: Schweiz
Kontaktdaten:

Hi

eigentlich alles ok, nur das ist irgendwie fehl am platz:
if readyForRead ==[]: break

wenn 5s nach programmstart keine daten da sind, bricht er die ganze schleife ab (timeout bei select hast du ja auf 5 gesetzt)

Bist du sicher das auch Daten an den Ports auf UDP ankommen? Also hatte das vor dem Wechsel auf select funktioniert??

Gruss
jihi
User
Beiträge: 14
Registriert: Montag 29. August 2005, 20:53
Wohnort: Hessen
Kontaktdaten:

Ja, vorher hat das einwandfrei funktioniert.
Irgendwie komisch, funktioniert das vielleicht in WinME nicht?

Das

Code: Alles auswählen

if readyForRead ==[]: break
stimmt schon, ist die einfachste Möglichkeit, das Programm mit socket.close() zu beenden.
Oder gibt es da noch was besseres um schleifen zu verlassen(ich glaub da war grad so ein Thread dazu?! mal gucken)
Antworten