Hallo,
ich habe mit meinem SAM4E-Xplained Board testweise das "LwIP raw basic
http" Beispiel umgebaut um Daten als Client an den Computer zu senden.
Funktioniert auch, allerdings nur mit 200 bis 300kb/s.
Meine Frage:
1) Ist die Verwendung der Socket API mit einem FreeRTOS darunter
performanter als die Raw API?
2) Ist die Performance des µIP Stacks vergleichbar mit der Raw-API des
LwIP Stacks? (nach angepassten Buffer-Größen)
danke
Zum Unterschied Socket vs. raw kann ich zwar nix sagen, aber ein paar
Erfahrungswerte mit dem LWIP raw API:
STM32F407 (168 MHZ ARM-cortex M4 mit 100MBit Ethernet),
Computer und uC-Board am gleichen (Gigabit-)Switch.
LWIP raw API, FTP-server (eigener code):
Download-Rate von SD-Karte ca. 4 MByte/s. Ersetzt man die Dateizugriffe
im FTP-Server (d.h. läßt man ihn zufaellige Buffer-Daten senden),
erreicht der Download 10MByte/s, also mehr oder weniger die Grenze für
100MBit.
Was mit bei der Implementierung aufgefallen ist:
* Dem LwIP genug Speicher für pbufs geben (also so 10-20kB min.); ist
man zu geizig wird es langsamer.
* Der sendende Code sollte achtgeben, nicht solange mit tcp_write daten
zu schicken, bis kein Speicher mehr für pbufs da ist, sondern selber
mitzaehlen, wieviele Daten gerade unterwegs sind, und nur ein paar kB im
voraus an den Stack geben. Das ist zumindes besser so wenn man mehr als
eine TCP/IP-Verbindung bedienen will. Aber auch mit einer Verbindung
sollte man nicht den kompletten Speicher füllen, sonst werden nacher
noch ACK-Pakete gedropt.
* Die o.g. Geschwindigkeit von 4MByte/s ist im wesentlichen vom
SD-Karten- Interface bestimmt. Ohne riesige Buffergrößen und cleveres
Lesen im Hintergrund per DMA wird es bei einer Class10-Karte nicht
schneller.
* In Netzwerken mit größerer Latenz (WLAN z.B.) bricht die Downloadrate
stark ein, wenn man nicht viel großzügiger mit dem Pufferspeicher ist,
da die Wartezeit auf ACK-Pakete dominierend wird, wenn der Stack nicht
so riesige Datenmengen puffern kann, denn der Stack muß ja alles, wofür
noch kein ACK gekommen ist, im Speicher behalten. Ddann also mehr
Speicher für pbufs nehmen.
* Man sollte sich den Low-Level-Netzwerk-Treiber mal ansehen, ob die
Daten aus den pbufs nochmal kopiert werden, bevor die an die
Netzwerkschnittstelle gehen. Das geht zwar i.a. fix, kostet aber unnötig
CPU-Zeit (je nachdem was die Schaltung sonst noch so machen soll). Wenn
die Hardware scatter-gather-DMA unterstützt, kann man auch die Hardware
die Pakete aus den LWIP-pbuf-chains zusammenbauen lassen
Zu µIP kann ich was sagen.
µIp unterstützt keine Window Size. Daher muss der Empfänger jedes
einzelne Datenpaket mit einem ACK bestätigen. Erst danach sendet µIP das
nächste Datenpaket.
Daher musst du für jedes einzelne Datenpaket die komplette Round-Trip
Zeit einplanen. Wenn die Verbindung Beispielsweise übers öffentliche
Internet geht, wo zweistellige Millisekunden normal sind, reduziert sich
die effektive Datenrate entsprechend. In diesen Fall lohnt es sich sehr,
möglichst große Datenpakete zu senden.
Das Zusammenspiel mit Windows ist bei µIP besonders schlecht, denn
Windows geht einfach davon aus, dass jeder andere Rechner eine gewisse
Windows-Size unterstützt. Windows verzögert die ACK's um satte 200
Millisekunden, un daran kann man nichts ändern. Will sagen, ein µC mit
µIP kann zu einem Windows Rechner über das IP Protokoll nur 5 Pakete pro
Sekunde mit je maximal 4kB übertragen. Bei UDP hast du das Problem
nicht, denn die beantwortet Windows sofort.
Linux verzögert die NAK's auch, aber Linux merkt nach einer Weile, dass
der Mikrocontroller nicht gut kooperiert und reduziert die Verzögerung
nach einer Weile auf schätzungsweise eine Millisekunde.
Sowohl Linux als auch Windows Anwendungen können die Verzögerung über
das Flag TCP_NO_DELAY deaktivieren. Telnet macht das so, die gängigen
Web Browser leider nicht.
lwIP ist von dem gleichen Problem betroffen, wenn man dort Windows-Size
1 hat. Mehr Window-Size erfordert allerdings auch mehr Pufferspecher -
und zwar für jede gleichzeitige Verbindung. µIP braucht nur einen
einzigen Puffer und kann darauf beliebig viele Verbindungen haben.
> 2) Ist die Performance des µIP Stacks vergleichbar mit der Raw-API> des LwIP Stacks? (nach angepassten Buffer-Größen)
Da µIP designbedingt keine Window-Size >1 unterstützt, kann µIP nur
gleich oder schlechter performen.
µIP kann man auf sehr einfache Art beschleunigen, indem man jedes Paket
zweimal unmittelbar hintereinander sendet. Dann kriegt man sofort ein
ACK zurück, statt verzögert.
Stefan U. schrieb:> Bei UDP hast du das Problem> nicht, denn die beantwortet Windows sofort.
UDP Pakete werden allenfalls von der Anwendung beantwortet, nicht aber
vom IP Layer im Betriebssystem.
> µIP kann man auf sehr einfache Art beschleunigen, indem man jedes Paket> zweimal unmittelbar hintereinander sendet. Dann kriegt man sofort ein> ACK zurück, statt verzögert.
Als Seiteneffekt verdoppelt man damit allerdings auch die Auslastung des
Netzwerkes.
Tassilo H. schrieb:> Download-Rate von SD-Karte ca. 4 MByte/s. Ersetzt man die Dateizugriffe> im FTP-Server (d.h. läßt man ihn zufaellige Buffer-Daten senden),> erreicht der Download 10MByte/s, also mehr oder weniger die Grenze für> 100MBit.
Das sind ja beeindruckende Raten. Zeigt mir dass bei mir noch viel im
Argen liegt.
> Was mit bei der Implementierung aufgefallen ist:> * Dem LwIP genug Speicher für pbufs geben (also so 10-20kB min.); ist> man zu geizig wird es langsamer.
Nutzt du eigens definierte memory pools (MEM_USE_POOLS,
MEMP_USE_CUSTOM_POOLS) oder die lwip Standards?
TCP_MSS hab ich auf 1460 (vom http server Beispiel von Atmel
voreingestellt)
TCP_WND = 10 * TCP_MSS
TCP_SND_BUF = 10 * TCP_MSS
Damit sollte der Speicher ausreichend dimensioniert sein.
Hast du bei dir die Checksummen per Software erstellt und überprüft?
> * Der sendende Code sollte achtgeben, nicht solange mit tcp_write daten> zu schicken, bis kein Speicher mehr für pbufs da ist, sondern selber> mitzaehlen, wieviele Daten gerade unterwegs sind, und nur ein paar kB im> voraus an den Stack geben. Das ist zumindes besser so wenn man mehr als> eine TCP/IP-Verbindung bedienen will. Aber auch mit einer Verbindung> sollte man nicht den kompletten Speicher füllen, sonst werden nacher> noch ACK-Pakete gedropt.
das ist ein guter Hinweis, momentan sende ich am laufenden Band Daten
raus, allerdings über nur 1 Verbindung.
Stefan Us schrieb:>Das Zusammenspiel mit Windows ist bei µIP besonders schlecht, denn>Windows geht einfach davon aus, dass jeder andere Rechner eine gewisse>Windows-Size unterstützt. Windows verzögert die ACK's um satte 200>Millisekunden, un daran kann man nichts ändern.
Tatsächlich ist der Empfänger (Server) eine Windows-Applikation. Wobei
ich das TCP_NO_DELAY Flag hier setzen können sollte. Da ich nur eine
Verbindung zwischen Client (µC) und Server (PC) habe, könnte µIP also
vielleicht doch eine gute Wahl sein. Wobei die großen Datenmengen von µC
zu PC gehen und umgekehrt nur Kommandos.
Um dem ganzen etwas Kontext zu geben, das soll als DAQ-Ausgangsbasis für
unterschiedliche Projekte dienen.
Zur Referenz mal die Header mit den Einstellungen fuer lwip. Man kann
sicher noch daran optimieren, aber in meinem Anwendungsfall (immer im
lokalen Netz) lohnt das nicht mehr.
Ach ja: Ethernet-CRC macht die Hardware.
> Tatsächlich ist der Empfänger (Server) eine Windows-Applikation.> Wobei ich das TCP_NO_DELAY Flag hier setzen können sollte.> Da ich nur eine Verbindung zwischen Client (µC) und Server (PC)> habe, könnte µIP also vielleicht doch eine gute Wahl sein.
Ja. Wobei µIP nicht auf EINE Verbindung beschränkt ist. Die maximale
Anzahl kannst du mit einer #define Zeile festlegen. Davon hängt der RAM
Beadarf ab. Aber trotzdem teilen alle Verbindungen sich einen Puffer.
Also hält sich das mit dem RAM Bedarf in Engen Grenzen.
Bei µIP muss der Application Layer jederzeit imstande sein, das letzte
Paket zu wiederholen. Ich denke, dass ist der (neben der Window-Size)
das auffälligste Manko an µIP. Ich nutze es trotzdem gerne.
Was beim Übertragen von Daten auf SD Karte besonders simpel ist, darauf
hat man ja wahlfreien Zugriff.
danke für die Header. Da sich unsere Speichergrößen nicht groß
unterscheiden nehme ich an dass die krasse Geschwindigkeitseinbuße von
der Checksummenberechnung per Software kommt. Das wird beim LwIP Wiki ja
auch als Geschwindigkeitsbremse Nr1 genannt.