Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Netzwerke (https://www.delphipraxis.net/14-netzwerke/)
-   -   Delphi Indy-Test optimieren (https://www.delphipraxis.net/180134-indy-test-optimieren.html)

stahli 25. Apr 2014 00:38

Indy-Test optimieren
 
Liste der Anhänge anzeigen (Anzahl: 3)
Hallo zusammen,

nachfolgendes ist nur etwas für Leute mit starken Nerven - bzw. mit Kenntnissen von Indy und ausreichend Tagesfreizeit ;-)

Also: Ich habe ein kleines Testprojekt (XE3)...


Server:
Ein Server verwaltet ein Integer-Array und stellt die Werte als Linien in einem Bitmap dar, das über einen Timer in das Formular kopiert wird.
Die Werte werden durch das Array geschoben, um einen optischen Effekt zu haben.
Klick in das Formular dreht die Darstellung jeweils um 90 Grad.

Das Array und der Turn(Dreh)-Wert sind einfach mal global verwaltet und reine Integer, damit es keine Syncro-Probleme gibt.


Clients:
Die Clients haben die gleiche Datenstruktur und Darstellung.
Aber über Indy werden nacheinander zyklisch alle Zahlenwerte und der Turn-Wert abgerufen.
Dieser Abruf läuft in einem Thread, damit das Formular "bedienbar" bleibt.
Ein Formular-Click sendet in dem Fall einen Dreh-Auftrag an den Server.


Die Werte-Übertragung läuft über Streams (mit Umweg über eine StringList), damit optional auch Umlaute übertragen werden könnten.


Im Grunde funktioniert das soweit - ABER!
Das ist natürlich recht langsam und die Clients bleiben gelegentlich auch hängen.


Ich weiß, dass ich in dem Testprojekt VIELES falsch mache. Aber zumindest das globale Array bitte ich hier mal großzügig zu übersehen.
Mir geht es hier darum, den Datenaustausch zwischen Server und Client zu optimieren und stabil zu gestalten.

Real soll der Server eine Menge von Daten verwalten, von denen sich die Clients nach Bedarf einige abrufen bzw. auch Aufträge den Server senden.
Über einen abzurufenden Zeitstempel können die Clients prüfen, ob der Server über neue Daten verfügt. Wenn nicht, werden gepufferte Daten genutzt.
Hier im Beispiel will ich diese Prüfungen vernachlässigen.

Wenn es gelingt, die Grafik in den Clients flüssig aktualisieren zu lassen wäre ich schon sehr zufrieden.

Bei Indy würde ich eigentlich gern bleiben, da man so ja auch noch andere Möglichkeiten wie eMail usw. hätte.
Es wäre aber auch ein genereller Wechsel möglich, wenn das etwas bringen würde.


Drei Hinweise noch:
- natürlich will ich nicht das Bitmap vom Server an die Clients schicken
- und die Clients können nicht wissen, welche Werte sich auf dem Server geändert haben.
- Die realen Daten können auch Sonderzeichen und Umlaute enthalten


Wäre super, wenn sich das jemand mal anschauen könnte...

Anbei
- Video
- XE3-Projekt
- Exen (in den Ini´s müsstet Ihr am besten Eure IP eintragen)

(Sorry, ist halt ziemliches Stückelwerk.)

Sir Rufo 25. Apr 2014 01:01

AW: Indy-Test optimieren
 
Was hast du denn für ein Problem mit den Strings und Umlauten und Streams? :gruebel:

Dafür gibt es Hilfsklassen (z.B. Delphi-Referenz durchsuchenTStreamWriter/Delphi-Referenz durchsuchenTStreamReader) und schwupps sind die Daten im Stream und wieder aus dem Stream.

stahli 25. Apr 2014 10:38

AW: Indy-Test optimieren
 
(ich muss das jetzt mal aus der Erinnerung zusammen fassen)

Socket.Writeln(' Text mit é ') führte immer zu einer Verstümmelung. Je nachdem welche Textart ich angegeben habe (UTF8 o.ä.) wurden auch Umlaute verstümmelt. Eine fehlerfreie Textübertragung mit Sonderzeichen und Umlauten habe ich nicht hin bekommen.

Daher der Weg über Streams.

TStreamReader und TStreamWriter waren mir nicht mehr geläufig.
Andererseits hatte ich auch überlegt, die Anweisung und Parameter ohnehin als StringList zu übertragen:
Zitat:

Anweisung
Param1
Param2
Param3
So hätte man dann leichteren Zugriff auf die einzelnen Parameter.

Meine wichtigere Frage wäre aber die Gestaltung des Datenaustausches gewesen. Das ist sicher noch sehr suboptimal, insbesondere wenn mehrere Clients Daten abrufen.

Wie machen das denn Onlinespiele?
Im Grunde könnte man ja die laufenden Linien als Spielfiguren ansehen und die Clients rufen ab, welche Linie (oder Figur) jetzt wo und wie gezeichnet werden muss.

Meine Lösung ist einfach viel zu langsam und ich weiß nicht, wie man das besser gestalten könnte.

Union 25. Apr 2014 11:26

AW: Indy-Test optimieren
 
Was ist denn nun genau langsam? Der Server, die Clients oder was? Ich habe mir jetzt nur den Server angeschaut. Da kann man schon Einiges optimieren. Aber das wäre ehe "Feintuning". Versuch doch mal herauszufinden, in welchen Routinen / Zeilen am meisten Zeit verbaten wird.
Als erstes würde ich aber auf das Ganze auf UDP umstellen, da Du sonst den ganzen Protokoll-Ballast mitschleppst. Es sein denn Du willst mal irgendwas tunneln oder es womöglich als http tarnen.

Sir Rufo 25. Apr 2014 12:28

AW: Indy-Test optimieren
 
Bei einem Online-Spiel können die Daten extrem reduziert werden.

Ein Objekt (Spieler, Rakete, Baum) ist vom Aussehen und Verhalten klar definiert und wird wenn nötig am Anfang des Spiels einmal übertragen (Farben, Polygone, Texturen, ...)

Bei Änderungen werden nur noch Position und Status übertragen und nicht das gesamte Objekt.

z.B. Rakete fliegt mit folgendem Bewegungsvektor [x,y,z] von Position [x,y,z]
und nur weil die Rakete weiterfliegt, werden keine neuen Daten übertragen, denn das Flugverhalten ist bekannt und kann ohne weitere Daten von jedem Client berechnet werden.

stahli 25. Apr 2014 12:47

AW: Indy-Test optimieren
 
@Sir Rufo

Ja aber ich habe im Beispiel auch nur 300 Zahlenwerte.


@Union

Was genau so langsam ist habe ich noch nicht gecheckt. Ist im Zusammenspiel zwischen Server und Clients wohl auch nicht ganz so einfach.
Vielleicht ist das zeitliche Verhalten ja auch in Ordnung und gar nicht mehr gravierend zu verbessern. Dann wäre mein ursprüngliches Ziel auf dem Wege wohl nicht zu erreichen.
Es hätte natürlich auch sein können, dass mein Server oder die Clients grundsätzlich falsch aufgebaut sind.

UDP ist ja offenbar eine fehleranfälligere Übertragungsform. Fehler müssten dann also explizit geprüft und ausgebessert werden.
Würde das deutliche Geschwindigkeitsvorteile bringen?

Eigentlich muss die Datenübertragung zuverlässig im lokalen Netz und evtl. auch über Internet funktionieren. Genauere Anforderungen habe ich derzeit nicht.

Union 25. Apr 2014 15:38

AW: Indy-Test optimieren
 
Warum versuchen denn sämtliche Programme, die schnell und viele Daten übertragen müssen, unbedingt alles auf UDP umbiegen (z.b. Skype)? Das bringt gewaltige Vorteile im Bereich der Übertragung. Im lokalen Netzwerk macht es sich nicht ganz so gravierend bemerkbar.

Noch mal mein Vorchlag: Die Teile sind ja momentan noch winzig. Also hast Du gute Chancen die Bremsen zu finden durch exakte Messung. Schau Dir mal System.Diagnostics an.

mjustin 25. Apr 2014 16:21

AW: Indy-Test optimieren
 
Zitat:

Zitat von Union (Beitrag 1256953)
Warum versuchen denn sämtliche Programme, die schnell und viele Daten übertragen müssen, unbedingt alles auf UDP umbiegen (z.b. Skype)?

Weil diese Programme (Skype, Videostreams) keine Probleme haben wenn mal ein Paket nicht ankommt - ein Ruckler oder ein Knacksen aufgrund eines fehlenden Datensatzes stört nicht so sehr, dass man deswegen die Übertragung sofort stoppen und die fehlende Millisekunde noch mal vom Server anfordern muss.

Union 25. Apr 2014 16:34

AW: Indy-Test optimieren
 
Man braucht die Pakete für die Clients nur durchnumerieren. Die dann zu implementierende Prüfungslogik ist trival. Aber stahli sollte das trotzdem zunächst mal profilen - unabhängig vom Übertragungsprotokoll.

mjustin 25. Apr 2014 20:31

AW: Indy-Test optimieren
 
Nun, die erste Optimierungsmöglichkeit die auffällt ist:

anstatt für jeden einzelnen Integerwert eine Verbindung zu Server aufzubauen, einen Request zu senden, den Integerwert abzuholen (mit S := ReadText(IdTCPClient1, '?' + IntToStr(Index));) und dann die TCP Verbindung zu schliessen, nur einmal pro Zyklus die Verbindung aufbauen und einen kompletten Datenblock (300 Integerwerte) abrufen. Und die Verbindung nur nach einem Datenblock schliessen, oder nur bei Fehlern und beim Programmende.

Ein potentieller Störfaktor ist das "fForm.Caption := DateTimeToStr(Now);", das ist ein nicht-threadsicherer Zugriff auf ein Objekt der Oberfläche.


Alle Zeitangaben in WEZ +1. Es ist jetzt 02:31 Uhr.
Seite 1 von 2  1 2      

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz