Forum: PC-Programmierung C++ Boost Asio TCP/IP gute Chunksize?


von AsioPP (Gast)


Lesenswert?

Hallo,

wenn man größere Datenmengen beispielsweise 10 GB aufgeteilt in mehreren 
Chunks von A nach B senden will, gibt es da eine empfehlenswerten 
Chunkgrößenbereich auch im Hinblick auf übliche Netzwerkkarten und OS?
5MB, 10MB, 50MB, 100MB, 500MB... ?

Gefühlt würde ich irgendwas zwischen 5MB-50MB nehmen. Ich Frage mich 
eben was ist im Hinblick auf die Übertragung besser, eher größere Chunks 
oder kleinere oder ist es am Ende völlig egal?

Im Netz konnte ich dazu nichts konkretes finden nur das Leute nach der 
maximalen Buffer Größe gefragt haben wo aber auch nicht beantwortet 
wurde wo eigentlich das limit für den read buffer ist:
https://stackoverflow.com/questions/31999875/c-boostasio-whats-the-maximum-buffer-size-i-can-use-for-tcp-sockets

Mir geht es aber auch nicht darum die maximal möglichen Buffergrößen 
auszunutzen sondern einen ungefähren allgemein guten Größenbereich für 
Chunks zu definieren.

Involviert sind ja neben den Programmen auch Netzwerkkarte und OS daher 
würde mich interessieren ob es in dieser Hinsicht aus der Praxis da 
einen Größenbereich in MB gibt der zu empfehlen ist welcher mit 
Netzwerkkarte und OS gut harmoniert? Wie groß würdet ihr persönlich 
solche Chunks ungefähr machen?

Es geht um diese Funktionen:

https://www.boost.org/doc/libs/1_75_0/doc/html/boost_asio/reference/write/overload1.html

https://www.boost.org/doc/libs/1_75_0/doc/html/boost_asio/reference/read/overload1.html

Grüße

von Oliver S. (oliverso)


Lesenswert?


von AsioPP (Gast)


Lesenswert?

Naja die 1500 Bytes beantworten nicht so richtig meine Frage. Das ist ja 
low level mit dieser MTU habe ich ja durch die Nutzung von boost asio 
nichts zu tun.
Asio wird ja vermutlich intern die Daten entsprechend dieser MTU 
irgendwie selbst fragmentieren aber darum muss (und will) ich mich als 
Anwender der Library nicht kümmern.
https://www.boost.org/doc/libs/1_75_0/doc/html/boost_asio.html

Meine Frage bezog sich auf selbst gewählte Chunkgrößen in MB Bereich als 
Sende/Empfangs-buffer der boost asio Funktionen write() und read().

von Andreas M. (amesser)


Lesenswert?

AsioPP schrieb:
> Asio wird ja vermutlich intern die Daten entsprechend dieser MTU
> irgendwie selbst fragmentieren aber darum muss (und will) ich mich als

asio macht da gar nichts. Der IP Stack ist normalerweise Bestandteil des 
Betriebssystems. Das gesamte IP Protokoll wird darin bearbeitet. Im 
Endeffekt wird es auch nur ein write() bzw send() auf dem Filehandle des 
Sockets ausführen.

Das Ziel von asio ist es auch nicht eine besonders hohe Performance zu 
erreichen sondern die Umsetzung von Event-Basierten 
Softwarearchitekturen zu vereinfachen/vereinheitlichen. Im Wesentlichen 
versteckt es das Verhalten der verschiedenen verfügbaren Socket APIs 
hinter einer einheitlichen, eventbasierten Schnittstelle.

von Oliver S. (oliverso)


Lesenswert?

AsioPP schrieb:
> Das
> ist ja
> low level mit dieser MTU habe ich ja durch die Nutzung von boost asio
> nichts zu tun.

Deine Frage oben bezog sich ja nun ausdrücklich auf Netzwerkkarten.

Du planst also ein völlig eigenes Protokoll über Netzwerkkarten, für 
zwei direkt per Kabel verbundenen Rechnern?

Ansonsten, wenn’s doch udp o.ä. ist, kannst du „high Level“ so große 
Blöcke definieren, wie auch immer du willst. Der Netzwerkstack wird die 
in MTU-große Blöcke aufteilen. Größer geht halt nicht.

Oliver

: Bearbeitet durch User
von AsioPP (Gast)


Lesenswert?

Ok ich versuche es nochmal, meine Frage ist: wenn man bei write()/send() 
die Buffersize selbst definiert (weil man zb 10-20 GB Daten in Teilen 
übertragen will) wie groß würdet ihr diese Buffer-/Chunksize wählen?

Beispiel A:
10 GB Daten mit Chunksize 10MB:
-> bedeutet 1000x write() aufrufen und jeweils 10MB Chunk senden.

Beispiel B:
10 GB Daten mit Chunksize 50MB:
-> bedeutet 200x write() aufrufen und jeweils 50MB Chunk senden.

Beispiel C:
10 GB Daten mit Chunksize 250MB:
-> bedeutet 40x write() aufrufen und jeweils 10MB Chunk senden.

Welche Chunksize in MB ist sinnvoll, welche nicht sinnvoll?
Wenn ihr euch zwischen A B C entscheiden müsstet, welches würdet ihr 
wählen und warum?

von AsioPP (Gast)


Lesenswert?

Oliver S. schrieb:
> Du planst also ein völlig eigenes Protokoll über Netzwerkkarten, für
> zwei direkt per Kabel verbundenen Rechnern?
Nein ich will nur Große Datenmengen (zB 10-20 GB) als mehrere Häppchen 
verschicken. Also mehrmaliger Aufruf von write() mit jeweils einem 
Häppchen. Meine Frage ist wie groß würdet ihr die Häppchen machen in MB?

> Ansonsten, wenn’s doch udp o.ä. ist, kannst du „high Level“ so große
> Blöcke definieren, wie auch immer du willst. Der Netzwerkstack wird die
> in MTU-große Blöcke aufteilen. Größer geht halt nicht.
Es ist TCP/IP wie im Titel. Also Häppchengröße am Ende völlig egal? oder 
gibt es nicht für größere oder kleinere Häppchen ein für oder wieder?

von AsioPP (Gast)


Lesenswert?

AsioPP schrieb:
> Beispiel C:
> 10 GB Daten mit Chunksize 250MB:
> -> bedeutet 40x write() aufrufen und jeweils 10MB Chunk senden.
sollte natürlich heißen "250MB Chunk senden."

von Johannes S. (Gast)


Lesenswert?

kommt doch darauf an wieviel Speicher man hat und wieviel man für einen 
Buffer spendieren will.
Letztendlich wird write in einer Schleife aufgerufen und es meldet 
zurück wieviel geschrieben wurde, bei TCP schon unabhängig von der MTU 
size. Das zieht man von der gesamt Anzahl ab und setzt den Zeiger im 
Sendebuffer um die Anzahl weiter. Solange bis alles weg ist.
Das passiert intern, da muss man sich dann nicht drum kümmern. Die 
Chunks hat dann Asio eingeführt. Bekommt man ein Event wenn ein Chunk 
gesendet wurde? Das macht Sinn wenn man einen neuen bereitstellen muss.

von AsioPP (Gast)


Lesenswert?

Johannes S. schrieb:
> Bekommt man ein Event wenn ein Chunk
> gesendet wurde? Das macht Sinn wenn man einen neuen bereitstellen muss.
ja also die Asio Funktion write() blockiert bis alles raus ist und dann 
gehts weiter. genau umsetzung so bisschen wie schleife also daten 
akkumulieren sich beim sender rein solange bis chunksize ausreicht und 
dann wird verschickt an empfänger.


> kommt doch darauf an wieviel Speicher man hat und wieviel man für einen
> Buffer spendieren will.
Ok also dann klingt es ja etwas wie als wäre es egal wieviel MB man pro 
Chunk wählt und man guckt einfach das der RAM Verbrauch der Programme 
nicht "zu hoch" wird.

von Johannes S. (Gast)


Lesenswert?

von 'Chunks' steht da in der Doku ja nichts. Wenn du den Datenblock als 
10 GB am Stück im RAM liegen hast, dann kann man den ja direkt als 
Buffer nehmen. Wenn die Daten sowieso erstmal Häppchenweise gelesen 
werden, dann reichen ein paar MB oder weniger als Buffer. Das die write 
Funktion dann mehrmals aufgerufen wird, wird nicht messbar sein.
Beim write kann man mehrere Buffer angeben, aber das macht Sinn für 
Scatter Gather IO, also z.B. wenn man Header und Nutzdaten bekommt, dann 
lassen die sich mit einem Aufruf schon getrennt übertragen.

Und andere Überladungen erlauben schon eine completion_condition zu 
übergeben, ein callback der aufgerufen wird wenn die Übertragung 
komplett ist. Sonst würde 'Asio' auch keinen Sinn machen.
Damit sind kleine Blöcke sinnvoll, wenn z.B. die Daten von der Platte 
geladen werden oder man einen Fortschritt aktualisieren will.

von Sheeva P. (sheevaplug)


Lesenswert?


von Johannes S. (Gast)


Lesenswert?

aber die magst du doch nicht, oder war es A.K.?

Die MTU spielt aber keine Rolle, bei TCP wird solange rausgefeuert wie 
der Gegner eine window size >0 anbietet und seine ACKs schickt.

von Irgend W. (Firma: egal) (irgendwer)


Lesenswert?

AsioPP schrieb:
> Es ist TCP/IP wie im Titel. Also Häppchengröße am Ende völlig egal? oder
> gibt es nicht für größere oder kleinere Häppchen ein für oder wieder?

Ganz egal nicht. Für jede Datei fällt ja auch noch ein nicht 
unerheblicher Overhead im Filesystem. Auf der einen Datei die Datei 
suchen und öffnen, auf der anderen diese erstmal anzulegen, den Inhalt 
hinzuzufügen, das Filesystem aktualisieren usw.

Kopiere als Test einfach mal per SMB eine Große Datei und einmal die 
gleiche Datenmenge in vielen Minidateien von einem Rechner auf einen 
anderen.

Und die TCP-Paketgröße hat durchaus auch eine Bewandtnis. Damit bekommst 
ja nicht immer jedes Packt voll und es kommt auf die genauen 
Einstellungen deines OS und deiner NIC an ob da noch auf weitere Daten 
gewartet wird oder das so gesendet wird. Und für jede Datei kommen 
dazwischen ja auch noch Datenpackete für das Datei Handling. Insgesamt 
bekommst du damit zu kleinen Dateien ganz schnell einen recht großen 
Overhead und auch Latenzen rein.

Wobei deiner Konstellation genau der Punkt ist wo der durch jede Dateien 
verursachte Overhead gegenüber der Zeit für die Datenübertragung nicht 
mehr wirklich ins Gewicht fällt musst du Ausprobieren...

Im Extrem mit noch kleineren Dateien. Ich hatte es schon gehabe das es 
sinnvoller war über 1Mio. Dateien mit 1-5KB erst zu einer Datei zu 
packen, diese eine Datei dann zu übertragen und im Ziel wieder 
Auszupacken. Das war einige Stunden schnelle als jede Datei einzeln zu 
übertragen.

von AsioPP (Gast)


Lesenswert?

Johannes S. schrieb:
> von 'Chunks' steht da in der Doku ja nichts.
mit "chunks" meinte ich nur die häppchen des ganzen.

> Das die write
> Funktion dann mehrmals aufgerufen wird, wird nicht messbar sein.
Ok das ist gut zu wissen!
Dann ist es ja im Bezug auf OS/Netzwerkkarte/usw tatsächlich wohl echt 
völlig egal ob ich Daten in Asio an einem Stück oder aufgeteilt in 
mehreren Teilen verschicke. Kann man dann je nach Anwendungsfall 
entscheiden. Fazit für mich dann jetzt: 10GB Daten via Asio in 5MB 
Chunks oder komplett in einem Rutsch ist also am Ende völlig egal :-)

von Johannes S. (Gast)


Lesenswert?

AsioPP schrieb:
> Fazit für mich dann jetzt: 10GB Daten via Asio in 5MB
> Chunks oder komplett in einem Rutsch ist also am Ende völlig egal :-)

mach doch einfach einen Test und stoppe die Zeit in beiden Fällen, da 
sind ja nur ein paar Zahlen zu ändern.

Anders ist es bei vielen ganz kleinen Päckchen, wenn du dem Gegner immer 
nur ein paar Byte schicken willst, dann sammelt der Sender die Daten 
üblicherweise und sendet die verzögert (Nagle Algorithmus). Und wenn man 
das abschaltet kann der Gegner immer noch sagen 'das sind mir zuviele 
kleine Störungen' und schickt sein Ack verzögert. Also relativ große 
Brocken (zig kb) mögen die Rechner heute lieber.

von AsioPP (Gast)


Lesenswert?

Irgend W. schrieb:
> Für jede Datei fällt ja auch noch ein nicht
> unerheblicher Overhead im Filesystem.

Mir ging es bei der Frage in erster Linie um die reine Übertragung von 
Programm zu Programm mit dem laden/schreiben auf Platte kam erst als 
Beispiel durch Johannes. Der Aspekt mit den Dateien ist aber interessant 
für Anwendungsfälle wo die Speicherung und so eine Rolle spielt, danke 
für den Hinweis werde das im Hinterkopf behalten vor diesem Hintergrund 
da die "Chunks" eher groß zu halten.

von AsioPP (Gast)


Lesenswert?

Johannes S. schrieb:
> mach doch einfach einen Test und stoppe die Zeit in beiden Fällen, da
> sind ja nur ein paar Zahlen zu ändern.
ja richtig, Zeit stoppen macht da am meisten Sinn

> Also relativ große
> Brocken (zig kb) mögen die Rechner heute lieber.
ok super dann weiß ich bescheid danke für die Infos

von foobar (Gast)


Lesenswert?

> 10GB Daten via Asio in 5MB Chunks oder komplett in einem Rutsch ist
> also am Ende völlig egal

Asio brauchst du nicht (das korrekt hinzubekommen ist nen ziemliches 
Gewürge).  Die Daten, die eh im Speicher sind, kannst du in einem Stück 
raushauen.  Wenn du abwechselt von Platte liest, auf Netz schreibst, 
würd ich eher bei kleineren Größen (4-128kB) bleiben - dann kann das 
Betriebssystem das durch prefetch/buffer ganz gut parallelisieren, ohne 
dass du Hand anlegen musst.

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.