Stefano Albrecht: Bild ständig aktualisieren

Beitrag lesen

Servus Daniel,

erstmal ganz locker mit dem ganzen Geflame von wegen Schwachsinn und Bullshit. Ich gehe das der Reihe nach durch.

1.) Wir sprechen hier von einer Java-Applikation, welche die Bilder erstellt...
Es wird ja nicht gesagt, was die tut, aber 2-8 Bilder / Sekunde erzeugen und wegschreiben sollte erst mal gehen.

Hast Du jemals intensiver mit Java gearbeitet? Vermutlich nicht. Ich nehme an, dass der Host für die finale Bildverarbeitung die JIMI-Bibliothek verwendet. Damit lassen sich die Images, oder die seltsamerweise langsameren BufferedImages (im Gegensatz zu String und BufferedString) in dem gewünschtem Format abspeichern. Während diese Bibliothek mittlerweile eine gewisse Reife in Bezug auf Sicherheit errungen hat, so kann man immer noch nicht von vergleichbarer Leistung zu entsprechenden C/C++-Anwendungen sprechen (Achtung: Leistung ist Arbeit durch Zeit, nicht Arbeit). Wieso? Lass uns auf den Punkt Sicherheit zurück kommen. JIMI prüft das Produkt rekursiv über Prüfsummen (CRC32). Stimmten die Prüfsumme vom Objektimage und Dateiimage überein, ist alles inordnung. Andernfalls wird eine tödliche Exception geworfen. Ignorieren? Vielleicht, es handelt sich immerhin um ein Video. Fazit für den kompletten Verlauf: Das Java-Programm erstellt ein Bild, das geht mit BufferedImage relativ fix. Aber moment.... neeeiiin! Was haben wir vergessen? Stimmt! JFrame! Will der Host anspruchsvollere Aktionen, beispielsweise pixelorintierte Manipulation vornehmen, so muss er das Image-Objekt zuvor über die Instanzmethode "createImage" von JFrame kopieren, und einem BufferedImage übergeben! Und wofür steht das "J" in JFrame? Genau, für die Java Foundation Classes (Swing)! Und das ist, mit aller Liebe zu java, eine verdammt langsame und zudem speicherfressende Angelegenheit! Dies jedoch nur nebenbei. Wenn das Bild schießlich erstellt wurde, muss JIMI das Ganze in eine Datei konventieren. Siehe oben, das kann dauern. Insgesamt ist das eine durchaus schaffbare Sache, auch, wenn es 5, 10, oder gar 20 Mal in der Sekunde gemacht werden soll. Aber dann soll noch ein Client per HTTP darauf zugreifen. Mhhhh schafft der das auch 8 mal in der Sekunde? Und was ist mit 100 Clients?

2.) Du willst die Angelegenheit per HTTP lösen. Dieses *Anwendungsprotokoll* verwendet jedoch das *Netzwerkprotokoll* TCP, und TCP ist durch den Three-Way-Handshake bekanntermaßen relativ langsam.
Das ist Bullshit.

Ahja. Gehen wir das mal ganz langsam durch. Hätte ich gewusst, dass das zu einer Erbsenzählerei wird, hätte ich den ganzen Roman schon zuvor verfassen können... Um es vorweg zu nehmen: Der Handshake ist bei Weitem nicht alles. Das hätte ich wohl vorher sagen sollen.

Der Handshake passiert beim Verbindungsauf- und -abbau.

In der Tat.

Ansonsten erreicht man mit TCP sehr guten Durchsatz weswegen die meisten Protokolle, die dazu verwendet werden, große Datenmengen zu übertragen, auf TCP basieren (HTTP, FTP, ...).

Wieso verwenden HTTP und FTP TCP?
Überlegung: Beide Protokolle senden oft sensible Daten (natürlich, es gibt auch SSL und die entsprechenden Implementationen wie HTTPS und SCPY, ich weiß...). Zumindest möchten beide Protokolle, dass ihre Datentransfers korrekt sind. HTTP u.a. wegen der korrekten Darstellung, FTP wegen der schlichtweg korrekten Datei (Stichwort "file is corrupt..."), was man ja mindestens verlangen kann. Kommen wir zu TCP. Dieses Protokoll bietet hierzu einige Meschanismen. Zunächst gibt es Sequenznummern, die versichern sollen, dass die Daten in korrekter Reihenfolge zusammengesetzt werden (... Sprung ...) Dann gibt es die CRC32-Prüfsummen, die versichern sollen, dass der Datentransfer die Integritäten erfüllt. Ob ICMP während dessen beim Clienten mitläuft, um Fehlerbehandlung vorzunehmen, sei außen vor gelassen. Insgesamt scheint TCP jedoch Einiges zu tun zu haben, bis die Daten gesendet oder erhalten sind, im Gegensatz zu UDP, bei dem diese Meschanismen fehlen. Bestimmt habe ich noch andere wichtige und zeitintensive Kriterien von TCP vergessen.

UDP ist interessant, wenn man sehr kleine Datenmengen übertragen will

Allerdings. Und Bildchen, die die Maße von 500 x 500 wohl nicht übertreffen, zudem vermutlich noch als JPG vorliegen, sind keine großen Datenmengen. Also haben wir ja einen Idealfall!

könnte evtl. für Streaming interessant sein, wenn man vermeiden will, dass verlorene Pakete nochmals geschickt werden o.ä.

Du sagst es!

Du willst also nicht eine Codierung für Video oder Bilddaten (mpeg, jpeg, ...) verwenden, sondern Du willst tatsächlich Java-Objekte serialisieren mit allem, was da so dran hängt? Und statt ein bewährtes Protokoll wie TCP zu verwenden, um diese Daten dann zu übertragen, willst Du das selber mit UDP implementieren?

Wahrscheinlich hast Du auch keine Erfahrung mit Serialisierung in Java. Attribute lassen sich als "transient" (etwa temporär) deklarieren. Methoden werden natürlich nicht serialisiert. In BufferedImage sind über 60% der Attribute als transient deklariert. Es werden nur das Array für die Bitweise Verarbeitung der Pixel (setRGB usw.) und einige Statusflags (z.B. Ladestatus, wieso auch immer...) mit gesendet. Insgesamt ist das eine wesentlich kleinere Datenmenge, als das ganze Bild zu senden. Ein Videostream bietet sich durchaus an! Nur habe ich keine Ahnung, wie ich in MPEG usw. konventiere! Und ich nehme an, dem Host geht es genauso.

Eine optimale Lösung wäre vermutlich, direkt aus der Javaanwendung heraus einen Videostream zu erzeugen (mittels passender Bibliothek und evtl. Streamingserversoftware. Ich kenne mich da allerdings nicht aus). Diesen Stream könnte man dann direkt bereitstellen und/oder mit einem Flashplayer auf der Webseite darstellen.

Ist prinzipiell nicht anderes, als mein Vorschlag. Für den Videostream würde ich gerne eine entsprechende Bibliothek sehen.

Zum Schluss noch mal zur "Pauschalität" von langsamen Java-Applikationen (mit Bezug auf die Antwort der Hosts). Mir ist sehrwohl bewusst, dass Java in vielen Bereichen immer schneller wird, allerdings nicht sämtlichen. Sun selbst schätzt den Geschwindigkeitsverlust im Vergleich zu "nativen" Compiliersprachen um bis zu 10% ein. Und das ist immer noch beträchtlich. Persönliche Erfahrungen sind zum Beispiel:
1.) Iterieren durch eine ArrayList mit 1.000.000 Einträgen ist etwa 15 % langsamer, als ein vergleichbares Konstrukt in C++, dass ich selbst erstellt habe (ebenfalls ArrayList getauft). Und dabei hätte das durchaus performanter sein können!
2.) Mein persönlicher Vergleich zu Javas ServerSocket + Socket (TCP-Sockets) und dem WinSock in C/C++ ergab, dass die nahezu identisch aufgebauten Java- und C++-Applikationen Geschwindigkeitsdifferenzen von bis zu 400 Millisekunden hatten (Java war langsamer)! Und das ist enorm!

usw...

Zu guter Letzt würde ich gerne einen halbwegs anspruchsvollen Videostream von Dir sehen, der tatsächlich TCP zur Übertragung verwendet. Und wenn Du das getan hast, dann bezeichne is das als "Bullshit" und "Schwachsinn", denn wieso werden Videos auf Datenintegrität und Sequenzreihenfolge geprüft? Werden etwa Passwörter über ein Video gesendet?

Hoffentlich habe ich in meinem ganzen Brainstorming nichts vergessen zu erwähnen... Ansonsten wird nachgeliefert ;~)

Freundliche Grüße
Stefano Albrecht

--
Sancta Simplicitas!