Entwickler-Ecke
Internet / Netzwerk - TCP Geschwindigkeit
08/15 - Di 16.05.06 11:09
Titel: TCP Geschwindigkeit
Hallo Leute,
Hab hier nen kleinen Testaufbau stehen und eine Platine der Firma BECK@IPC versuche ich nun möglichst schnell mit dem Rechner reden zu lassen.
Eine Verbindung ist vorhanden, Leitung auf 100 Full Duplex und ich kann Daten senden und empfangen ... kein Problem soweit. Ich erzeuge nun dummydaten auf dem Chip und sende möglichst große Pakete and den Rechner per TCP/IP. Nur liegt mein Problem nun darin die Daten schnellstmöglich vom Socket zu bekommen. Ich komm bei meiner Zeitnahme ( passiert mit nem Hr timer auf dem chip ) auf gerade mal 1/10 der erforderlichen Bandbreite. Ich poste mal meinen Quellcode soweit hier und wollte Fragen ob ich was Grundlegendes übersehen hab dass meine Daten so langsam ankommen.
Achso ich hab auch schon per Udp vom Chip die Daten einfach mal ins Nirvana gejagt ... und dabei kommt ich auf das 9 Fache der geschwindigkeit gegenüber TCP. Also liegts an meinem Programm im Delphi. Ich nutz Delphi 7 :)
Achso und die Daten die kommen sind 120000 Bit und sollen ein 300*200 großes Bitmap befüllen.
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77:
| private FClientSock : TClientSocket; FRecvBuffer : Pointer; FRecvCount : Integer; FBitmap : TBitmap;
procedure TfImpulsform.FormCreate(Sender: TObject); begin FClientSock := TClientSocket.Create( Self ); FClientSock.ClientType := ctNonBlocking; FClientSock.Host := edtIP.Text; FClientSock.Port := 7; FClientSock.OnRead := Receiver;
FBitmap := TBitmap.Create; FBitmap.PixelFormat := pf16bit; FBitmap.Width := 300; Fbitmap.Height := 200;
AllocMemoryN( FRecvBuffer, 300*200*sizeof( Word ) + 1000 ); FRecvCount := 0; end;
procedure TfImpulsform.Button2Click(Sender: TObject); var intReturnCode : integer; pch : array[0..240] of Char; aPWs, aPWd : PWord; yy : Integer; begin if FClientSock.Active then begin FRecvCount := 0; StrPCopy( pch, edSend.Text );
intReturnCode := FClientSock.Socket.SendBuf( pch, Length(edSend.Text)); if intReturnCode > 0 then begin StatBar( 0, 'Send' ); StatBar( 1, IntToStr(FClientSock.Socket.RemotePort) ); while FRecvCount < FBitmap.Width * FBitmap.Height * 2 do begin Application.ProcessMessages; end; aPWs := FRecvBuffer; for yy := 0 to FBitmap.Height-1 do begin aPWd := FBitmap.ScanLine[yy]; CopyMemory( aPWd, aPWs, 600 ); Inc(aPWs, 300 ); end; Image1.Picture.Bitmap := FBitmap; end else MessageDlg('No answer from server', mtError, [mbOk], 0); end; StatBar(1, 'Ready' ); end;
procedure TfImpulsform.Receiver(Sender: TObject; aSocket: TCustomWinSocket ); var cnt : integer; pW : PByte; begin cnt := aSocket.ReceiveLength; mmoReceived.Lines.Add( 'cnt: ' + IntToStr( cnt ) ); if cnt > 0 then begin pW := FRecvBuffer; Inc( pW, FRecvCount ); aSocket.ReceiveBuf( pW^, cnt ); Inc( FRecvCount, cnt ); StatBar(3, IntToStr( FRecvCount ) ); end; end; |
Für Hilfe währe ich sehr dankbar weil erklären kann ich mir das ganze nicht :gruebel: oder ist es besser die TUdpSockUtil libary zu nutzen aus dem Forum hier ... aber vom Prinzip müsste doch TCP gut klappen.
Vielen Danke schonmal
Andreas
Narses - Di 16.05.06 11:43
Moin und :welcome: im Forum!
08/15 hat folgendes geschrieben: |
| Ich erzeuge nun dummydaten auf dem Chip und sende möglichst große Pakete and den Rechner per TCP/IP. |
Möglichst große Pakete korrelieren nicht mit hoher Übertragungsrate, weit verbreiteter Irrtum. ;) Meistens ist es wesentlich klüger, knapp unter MTU zu bleiben... :?
08/15 hat folgendes geschrieben: |
| Ich komm bei meiner Zeitnahme ( passiert mit nem Hr timer auf dem chip ) auf gerade mal 1/10 der erforderlichen Bandbreite. |
Sag doch mal Zahlen, relative Angaben helfen praktisch nicht. :gruebel: ;)
08/15 hat folgendes geschrieben: |
| ich hab auch schon per Udp vom Chip die Daten einfach mal ins Nirvana gejagt ... und dabei kommt ich auf das 9 Fache der geschwindigkeit gegenüber TCP. Also liegts an meinem Programm im Delphi. Ich nutz Delphi 7 :) |
Das ist möglicherweise nicht schlüssig bewiesen, s.o. ;)
Wenn du wirklich so nah am Grenzwert mit dem Timing hantierst (kann ich mir nur schwer vorstellen), dann solltest du sowieso besser einen Receiver-Thread abspalten und mit blocking-Sockets arbeiten, dass ist am schnellsten.
Weiterhin: der WSA-Buffer ist AFAIK 8kb gross, wenn du mehr am Stück sendest und mit asynchronen Ereignissen arbeitest, dann handelst du dir da möglichweise fett Wartezeiten ein.
cu
Narses
08/15 - Di 16.05.06 12:01
Hehe danke für den Willkommensgruß
Ich hab in der Tat die Anbsicht die Daten so schnell wie möglich rüberzubekommen. Ich messe zur Zeit beim raussenden auf meinem chip 1190 CPU ticks was 1,19 sec entspricht. Bei 120000 / 1190 komme ich au 100,8 kB/s ... schaffen sollte das Protokoll laut hersteller in idealer Testumgebung aber 1085 kB/s. Das das nicht ganz zu erreichen ist erscheint mir logisch aber 10% von diesem Richtwert ist mir zu wenig :D
Die sache mit der Blockgröße ist so das ich wenn ich im OnReceive Ereignis in meine Quellcode bei maximaler Geschwindigkeit 1460er Blöcke eintrudeln ... das ganze 82 mal und noch ein kleiner 280er Block damit die 120000 komplett sind. Es kommt auch alles wie gewünscht an ... also die Daten sind stimmig. Wenn ich nun noch ein Sleep in OnReceive einfüge bekomm ich auch die maximalgröße von 8192 :) ... und ebenfalls verlustfrei alle Daten.
Wo verursach ich meine Wartezeit? Hab ich etwas nicht bedacht?
Danke für die schnelle Antwort
Gruß
Andreas
Edit: Wichtig ist auch das komplett alle Daten ankommen. Also fand ich TCP eher geeignet als wenn ich UDP nutze. Ich bin mit der überlegung rangegangen das ich die Puffer auf dem Chip vollschreib und dann rausschicke komplett ... so das sich das TCP protokoll schon darauf einstellt. Ich kann am Chip noch die Größe der Datenpackete einstellen oder verändern ... von 8192 auf 4096 oder noch geringer ... das bringt je kleiner diese werden jedoch nur nachteile in der Geschwindigkeit. Delphi scheint die 8192 als Standardwert irgendwo integriert zu haben wie mir scheint :gruebel:
Edti2: ( schnell noch ein Edit ;) ) Also die MTU liegt bei mir bei 1500 und ich hab nun meine Senddatenpakete auf 1024 gestellt ... die Geschwindigkeit ist konstant "langsam" ;) geblieben.
Narses - Di 16.05.06 13:54
Moin!
08/15 hat folgendes geschrieben: |
| Ich messe zur Zeit beim raussenden auf meinem chip 1190 CPU ticks was 1,19 sec entspricht. Bei 120000 / 1190 komme ich au 100,8 kB/s ... schaffen sollte das Protokoll laut hersteller in idealer Testumgebung aber 1085 kB/s. Das das nicht ganz zu erreichen ist erscheint mir logisch aber 10% von diesem Richtwert ist mir zu wenig :D |
Ist das so ein embedded-device-server? Die sind nicht immer sooo schnell... Sicher, dass du die Doku korrekt verstanden hast (da die Werte ca. eine 10er-Potenz auseinanderliegen)? :mrgreen: (nicht aufregen bitte, wer nicht schonmal auf rtfm reingefallen ist, werfe den ersten Stein... ich hab hier nur Sand... ;))
08/15 hat folgendes geschrieben: |
| Wo verursach ich meine Wartezeit? Hab ich etwas nicht bedacht? |
Das AsyncSelect der WSA, was hinter den Ereignissen steckt, ist jetzt nicht gerade der Turbo... allerdings Faktor 10 Verlust wäre jetzt schon etwas sehr viel... :gruebel:
08/15 hat folgendes geschrieben: |
| Wichtig ist auch das komplett alle Daten ankommen. Also fand ich TCP eher geeignet als wenn ich UDP nutze. |
Hm, bei Bildern müssen wirklich immer alle Zeilen ankommen? :? Wenn du Einfluss auf das Protokoll hast, hätte ich sonst mal folgendes vorgeschlagen:
- nimm UDP (z.B. TUdpSockUtil ;))
- Bau die Pakete so auf: AppID | PictureID | LineNo | Data, also praktisch immer eine Image-Zeile pro UDP-Paket
- Rest (reassembling usw.) machste im Empfänger (Delphi)
- wenn was nicht angekommen sein sollte (kannste ja über die IDs rausfinden), forderst du diese Zeilen nochmal an
Zumindest einen Test wert, oder? ;)
08/15 hat folgendes geschrieben: |
| Delphi scheint die 8192 als Standardwert irgendwo integriert zu haben wie mir scheint :gruebel: |
Nicht Delphi, die WSA. ;)
cu
Narses
08/15 - Di 16.05.06 17:01
Danke für die kompetente Hilfe ... mein Fehler lag aber doch am Chip.
Der ist aber dermaßen trivial das ich mich net traue den hier zu sagen ;)
Also nochmal dickes Dankeschön
Gruß
Andreas
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2026 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!