Forum: Mikrocontroller und Digitale Elektronik LwIP Sockets API vs. Raw API vs. uIP Stack


von Fred (Gast)


Lesenswert?

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

von Tassilo H. (tassilo_h)


Lesenswert?

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

von Stefan F. (Gast)


Lesenswert?

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.

von (prx) A. K. (prx)


Lesenswert?

µ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.

von (prx) A. K. (prx)


Lesenswert?

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.

von Stefan F. (Gast)


Lesenswert?

> µ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.

von Fred (Gast)


Lesenswert?

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.

von Tassilo H. (tassilo_h)


Angehängte Dateien:

Lesenswert?

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.

von Stefan F. (Gast)


Lesenswert?

> 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.

von Fred (Gast)


Lesenswert?

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.

von Stefan F. (Gast)


Lesenswert?

Ist bei µIP ebenso.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.