# TCP/IP-Kommunikation ist zu langsam



## saez (28. Okt 2008)

Hallo,

beim Prüfen einer Java-Anwendung im Produktionsumfeld ist es zu massiven Performanceproblemen gekommen. Dazu folgende Stats:

-Java-Anwendung mit TCP/IP-Kommunikation als Server, dazu gibt es noch eine C-Komponente für intensive Rechenaufgaben. Diese Anwendung nimmt über einen Port Nachrichten entgegen und soll diese beantworten. Für das Verschicken ist ein Transaktionssystem (TrxSys) verantwortlich, das ist in C geschrieben.

TrxSys hat jedoch schon massive Probleme nur Verbindungen aufzubauen (also ohne Transaktionen zu verschicken), daher musste das Timeout für einen Verbindungsaufbau hochgeschraubt werden, was in Produktion nicht zulässig ist. 
Zum Verbindungsaufbau schickt TrxSys eine 51Byte große Nachricht an den Java-Server, dieser wiederum antwortet zunächst mit der identischen Nachricht.
Aufgefallen ist u.a., dass der Java-Server die Antwort auf 2 Pakete aufteilt, das erste ist nur 2 Byte groß, das zweite dann 48. TrxSys muss das dann zusammensetzen und das dauert wohl. Außerdem vergeht zwischen beiden gesendeten Paketen mindesten 150ms, was an sich schon viel zu lange ist.


Weiterhin:
Es gibt einen auch TrxSys-Simulator in Java, der schickt ebenfalls Nachrichten und wartet auf Antworten. Bringt man beide Java-Anwendungen über Netzwerk (2 Rechner) zusammen, dann schaffe ich 3Trx pro Sekunde. Macht man das Ganze über localhost/die ip-adresse eines Rechers, habe ich hingegen 600Trx/sek. Bei letzter Variante wird die Netzwerkkarte wohl außen vor gelassen, es ist kein Traffic darüber zu erkennen. Offenbar werden die Nachrichten auf einer anderen Schicht ausgetauscht. 

Ersetzt man Sender (Simulator) oder Empfänger (Server) durch ein C-Programm geht die Performance nach oben. Aber die von Java geschickte Nachricht wird jeweils in 2 Pakete aufgeteilt. Sind beide Komponenten in C geht es rasend schnell und es gibt jeweile nur ein Paket pro Nachricht.


Kann jemand damit etwas anfangen?


----------



## tuxedo (28. Okt 2008)

>> Kann jemand damit etwas anfangen?

Ne, absolut nicht. Ich tippe mal auf eine grottenschlechte "TrxSys" Implementierung, oder irgendwelche anderen 3rd Party Abhängigkeiten die das ganze in den Keller ziehen.

Java an sich hat keine Probleme mit "normalen Java IO" eine 100Mbit Netzwerkkarte voll auszulasten (also rund 10MByte/sek).

Auch gibt es keine bekannten Probleme mit vielen gleichzeitigen Clients. Spätestens mit "Java NIO" sind, bei einer guten Servermaschine, 2500 und mehr Clients drin.

Dass das 51 byte große Paket auch noch zerteilt wird kann ich mir nicht erklären. Aber auch hier: Da muss was schlecht implementiert worden sein.

>> TrxSys hat jedoch schon massive Probleme nur Verbindungen aufzubauen (also ohne Transaktionen zu verschicken)

Generell oder nur in Verbindung mit einem Java-Server? Wenn nicht nur zu Java, wird wohl der Fehler in diesem ominösen TrxSys zu suchen sein...

>> Offenbar werden die Nachrichten auf einer anderen Schicht ausgetauscht. 

Jupp. AFAIK geht das nahezu direkt über den RAM Speicher. Aber auch hier sind 600 Trx/Sek a 51 Byte eindeutig zu wenig. Du solltest hier definitiv >10mbyte/sek erreichen _können_. (das wären dann fast 200.000 Trx/Sek ...(falls der Server mit dem verarbeiten der Nachrichten hinterher kommt))

Ohne weiteren Details, am besten mit entsprechenden Codeschnipsel oder noch besser einem compilierbaren Minimalbeispiel kann man nach wie vor nur mutmaßen.

- Alex


----------



## HoaX (28. Okt 2008)

wenn ich das richtig verstehe gehts lokal schnell, aber über zwei rechner langsam? netzwerkkarte mal geprüft/getauscht?


----------



## tuxedo (28. Okt 2008)

lokal: 600 Nachrichten pro Sekunde a 52 byte == schnell (knapp 32kbyte/sek)? Ne, nicht wirklich.

- Alex


----------



## saez (29. Okt 2008)

Das Problem tritt zwischen verschiedenen Rechnern im Netzwerk auf, scheint also kein Problem der Netzwerkkarte zu sein.

Der aktuelle Ansatzpunkt sind die Paketzerstückelungen, die nur auftreten wenn Java der Sender einer Nachricht ist.

PS: TrxSys ist definitiv nicht grottenschlecht programmiert, das hätte wohl jeder von uns schon mal gemerkt 


Ich habe mal ein älteres Tool http://soap-stone.sourceforge.net/ geprüft. Das testet die Netzperformance der VM auf dem Loopback (127.0.0.1). Da komme ich auf Raten von 700MB/s. Aber was sagt das jetzt aus? Leider geht das Tool nicht über Rechnergrenzen hinweg.


----------



## tuxedo (29. Okt 2008)

saez hat gesagt.:
			
		

> Das Problem tritt zwischen verschiedenen Rechnern im Netzwerk auf, scheint also kein Problem der Netzwerkkarte zu sein.



Gut, dann wäre das schonmal ausgeschlossen...



> Der aktuelle Ansatzpunkt sind die Paketzerstückelungen, die nur auftreten wenn Java der Sender einer Nachricht ist.



Ist halt die Frage ob zerstückelt gesendet wird, oder nur zerstückelt gelesen wird... Mit Tools wie Wireshark lässt sich das ja prüfen.



> PS: TrxSys ist definitiv nicht grottenschlecht programmiert, das hätte wohl jeder von uns schon mal gemerkt



"jeder von uns"?? Also ich nicht. Hab seit rund 5 Jahren mit Java zu tun. Aber "TrxSys" war mir bisher nie ein Begriff. 



> Ich habe mal ein älteres Tool http://soap-stone.sourceforge.net/ geprüft. Das testet die Netzperformance der VM auf dem Loopback (127.0.0.1). Da komme ich auf Raten von 700MB/s. Aber was sagt das jetzt aus?



Na dass Java auch Socketebene mit den ganzen Input und Outputstreams auf localhostverbindungen bei dir 700MByte/sek schafft. 

Da deine Anwendung aber nut 600 Nachrichten a 51 Byte pro Sekunde (knapp 30kbyte/sek) via localhost schafft, ist da etwas ganz böse im argen ...



> Leider geht das Tool nicht über Rechnergrenzen hinweg.



??? Auf der Seite steht doch:

------------------
So you just installed a new Gigabit Ethernet network. Or you just installed a WiFi access point for your intranet. It seems fast, but just how fast can you really pump data through your shiny new network? More specifically, how fast can your applications talk various protocols (Sockets, HTTP, RMI, SOAP) one-way and round-trip from inside a Java Virtual Machine?

Soap-Stone is the network benchmark application which can answer these questions for you by putting your network under load and conducting automatic benchmark and recording activities. 

....

*Soap-Stone is delivered as a single Java JAR archive which can act as both client and server in a point-to-point network test.*
------------------

Und die Grafiken auf der Seite zeigen auch etwas anderes ... Sehe keinen grund warum das nicht über Rechnergrenzen hinweg funktionieren soll.

- Alex


----------



## tuxedo (29. Okt 2008)

Okay, ich geb zu. Die Doku ist, gelinde gesagt scheisse. 

Hab auch erst etwas decompilieren müssen bis ich dahinter gekommen bin wie man den Host angibt:

Server:

```
>java -jar soap-stone-full-0.952.jar server -server karclt1105 -protocol raw
soap-stone: Plugin 'http' loaded from .\plugins\http-plugin.jar
soap-stone: Plugin 'soap' loaded from .\plugins\jwsdp-plugin.jar
soap-stone: Plugin 'raw' loaded from .\plugins\raw-plugin.jar
soap-stone: Plugin 'rmi' loaded from .\plugins\rmi-plugin.jar
soap-stone: Server command-line: soap-stone server -server karclt1105 -protocol raw
soap-stone: Server control socket listening at ServerSocket[addr=karclt1105/150.158.180.161,port=0,localport=8001]
```

Client:

```
>java -jar soap-stone-full-0.952.jar client -server karclt1105 -protocol raw
soap-stone: Plugin 'http' loaded from .\plugins\http-plugin.jar
soap-stone: Plugin 'soap' loaded from .\plugins\jwsdp-plugin.jar
soap-stone: Plugin 'raw' loaded from .\plugins\raw-plugin.jar
soap-stone: Plugin 'rmi' loaded from .\plugins\rmi-plugin.jar
soap-stone Client: command-line: soap-stone client -server karclt1105 -protocol raw
soap-stone Client: connecting to control socket: karclt1105/150.158.180.161:8001
+..........
soap-stone Client: size=1500 bytes buffers=1000 avg=93,88 Mbit/sec min=23,64 Mbit/sec max=104,99 Mbit/sec

prefixes=java.runtime.,java.version.,java.vm.,os.,soap-stone. suppress=java.vm.specification
done in 5640 ms
```

"karclt1105" ist der Hostname auf dem ich den Server gestartet habe. Muss man sowohl beim Server als auch beim Client angeben...

- Alex


----------



## saez (29. Okt 2008)

1. Die Paketzerstücklung habe ich schon im Netzwerkanalyse-Tool von Microsoft gesehen
2. Ich finde bei soap-stone keine Optionen, wo man ein andere Ip-Adresse + Port angeben kann weder bei Server noch bei Client.

3. TrxSys ist ein Synonym für ein Transaktionssystem.


----------



## tuxedo (29. Okt 2008)

1) Prima
2) Siehe meinen letzten Post
3) Schön. Ein tolles Wort, dieses "Transaktionssystem". Was dahinter steckt und ob es ggf. einer norm folgt, steht leider noch nicht in diesem Thread. 
4) Java an sich ist nicht schuld für Zerstückelungen und langsame Übertragung von Paketen in deinem "TrxSys" Fall. Entweder die Implementierung ist schlecht (ob C oder Java Seite sei mal dahingestellt), oder, was von einer schlechten Implementierung eigentlich eingeschlossen ist, die Adaption von Datentypen von Java auf C und umgekehrt ist schlecht. 

Gruß
Alex


----------



## saez (29. Okt 2008)

Danke für die Info. Ich hab das Ding auf Rechnern laufen lassen. Ergebnis:

-8MB in 719Sekunden, durchschn. Datenrate: 89Mbit/s (die Rechner sind nur mit 100Mbit verkabelt).

Also über 10 Minuten für 8MB find ich doch etwas viel oder?


----------



## tuxedo (29. Okt 2008)

>> durchschn. Datenrate: 89Mbit/s

Das sind ganz grob 9MegaByte/Sekunde. Was willst du mehr? Bei 100Mbit ist das vollkommen normal.

"8MB in 719 Sekunden" passt rechnerisch gar nicht zu den 89Mbit/s ... Poste doch mal exakt die Ausgabe des Clients .....

- Alex


----------



## saez (29. Okt 2008)

D:\Bin\Soap-Stone>java -jar soap-stone-full-0.952.jar client -server svr1 -pro
tocol raw -size 8mb
soap-stone: Plugin 'http' loaded from .\plugins\http-plugin.jar
soap-stone: Plugin 'soap' loaded from .\plugins\jwsdp-plugin.jar
soap-stone: Plugin 'raw' loaded from .\plugins\raw-plugin.jar
soap-stone: Plugin 'rmi' loaded from .\plugins\rmi-plugin.jar
soap-stone Client: command-line: soap-stone client -server fpsrt2 -protocol raw
-size 8mb
soap-stone Client: connecting to control socket: svr1/10.2.20.215:8001
..........
soap-stone Client: size=8388608 bytes buffers=100 avg=88,85 Mbit/sec min=87,85 M
bit/sec max=89,28 Mbit/sec

prefixes=java.runtime.,java.version.,java.vm.,os.,soap-stone. suppress=java.vm.s
pecification
done in 720941 ms

Mittlerweile hat ein Registry-Eintrag im Windows Server 2003 erhebliche Verbesserung gebracht:
"TcpAckFrequency = 1"


Die angesprochene Paketstückelung gibt es jedoch weiterhin.


----------



## tuxedo (29. Okt 2008)

Die Zeitangabe "done in..." gibt nicht an, dass es SOLANGE gedauert hat lediglich 8MB zu übertragen. Sie gibt an "SOLANGE hat der Test gedauert". 

Von daher seh ich kein Problem darin. Die Ergebnisdaten (avg=88,85 Mbit/sec min=87,85 Mbit/sec max=89,28 Mbit/sec) sehen ja gut aus.

Und damit wäre bewiesen, dass Java allein keine Schuld trifft.

- Alex


----------



## Murray (29. Okt 2008)

Wenn der Java-Server aber wirklich so kleine Pakete verschickt, dann sollte man vielleicht mal einen Blick auf die Implementierung werfen. Kannst Du die relevanten Sourcen posten?


----------

