![]() |
Geschwindigkeit Anonymous Pipes vs Named Pipes vs Mailslots
Ich habe einen Serverprozess mit bis zu ca. 10 Clientprozessen, auf dem selben Computer am laufen. Es soll eine extrem hohe(!) Kommunikation in Form vom Nachrichten von 30-1000 Bytes stattfinden. Alle Prozesse haben KEIN Window.
Ein paar Geschwindigkeitsmessungen auf einem AMD 1,3 Ghz, Windows XP: Windowsmessages von per PostThreadMessage(): ca. 150.000 Messages pro Sekunde ca. 50.000 Messages pro Sekunde mit Warten auf Antwort Faziz: Sehr schnell, kann aber "nur" zwei 32-Bit-Zahlen transportieren Memory Mapped Files(Shared Memory) Es gibt für jede Sprachrichting eine Memory Mapped File, zu sendende Daten werden hinein geschrieben und eine Windowsmessage gesendet mit Offset und Länge des Datenpacketes in der Remote-Datei um den Remoteprozess über ein neues Datenpacket zu benachrichtigen ca. 12.000 Nachrichten(Länge 20-100 Bytes) pro Sekunde mit Warten auf Antwort Wie lange das Senden ohne zu Warten dauert habe ich "vergessen" Problematiken: Die "selbstgeschribene" Pipeline muss regelmäßig rotiert bzw. geleert werden. Anomymous Pipes 2 Pipes, eine für jede Richtung. Auf beiden Seiten wird mit Hilfe von ReadFile() "gelauscht". Eine Zeitmessung habe ich noch nicht durchgeführt. Etwas anderes macht mir da "mehr" Sorgen: Serverseiting wird für jeden Client ein sperater Thread benötigt, da ReadFile() sich auf nur ein File-Handle bezieht. Named Pipes Ist mir ne Nummer zu "hoch", und meine Bedenken sind dass Named Pipes einen zu großen "Overhead" haben. Mail Slots Nachriten basiertes System. Vorteil: Es sind Broatcast-Nachrichten möglich. Nachteil: Es wird NICHT garantiert dass das Packet angekommen ist. In meiner Anwenund gibt es folgende Nachrichtentypen: Send Only Beispiel: Ein Protokollierungseintrag wird abgeschickt, Der Client arbeitet sofort weiter, eine Benachrichtigung ob Erfolgreich ist nicht notwenidg Mein Vorschlag zu Realisierung: Mail Slot oder Anonymouse Pipe in einer Richting. Send And Notify Beispiel: Der Client aktualisiert einen Wert auf dem Server. Als Benachrichtigung nach der Aktualisierung wäre eine Windowsmessage denkbar. GetData Beispiel: Ein Wert wird abgefragt. Die Anfrage wird gestellt(ca. 20-100 Bytes), es wird gewartet bis der Server Antwortet. Mein Vorschlag zur Realisierung: zwei Anoymous Pips oder eine Named Pipe, Mail Slot oder Memory Mapped File mit windowsmessage-Benachrichtigung Die Wahl der Transportmöglichkeit ist durch folgende Dinge zu überlegen: - Transportgeschwindigkeit - Effizienz beim Abfragen der ankommenden Daten Da ich in der Regel immer in 2 Richtiungen kommunizieren muss("Send Only" ist extrem seltend, daher mache ich mir darüber jetzt keine Gedanken) ist die Situation folgende: Die Lösung mit Memory Mapped Files-Lösung benötigt auf der Clientseiete eine MMF und eine Messagequeue, auf Serverseite ebenfalls. Auf Serverseite jedoch könnte ein einziger Thread(MessageQueue) an mehreren Verbindungen lauschen. Für Anomous Pipes wird IMMER pro Sprachrichtung ein Thread zum lauschen benötigt. Named Pipes sind mir ne Nummer zu "hoch" Mit Mailslots habe ich noch nicht gearbeitet. Nächste Problematik wäre dann das Bearbeiten der Packete auf der Serverseite. Ich bin am überlegen ob für jede Anfrage geschaut werden soll wie "zeitaufwendig" sie ist. Ist sie vorraussichtilich "zeitaufwendig" soll sie in einem neuen Thread bzw. in einem Thread im Threadpool ausgeführt werden. Nun, was ist die schnellste und effzienteste Lösung? Mir fehlt es halt ein bisschen an Erfahrung bei der "High Performance" Inter Process Communikation ;) Ist als "Benachrichtiung" ein WaitHandle bzw. Event(per Handle) schneller/effizienter als eine Windowsmessage? Gibt es eigentlich 3rd-Party Lösungen für IPC? |
Re: Geschwindigkeit Anonymous Pipes vs Named Pipes vs Mailsl
Named Pipes sind merklich langsamer. Für Messages mit 4KB Größe hast Du im Schnitt einen Durchsatz von 10.000 Nachrichten je Sekunde bei ca. 80% Prozessorauslastung (Worst-Case-Scenario!). Selbst das sollte aber eigentlich reichen. In Momenten mit solch einem Datendurchsatz sollte man das Design seiner Software überprüfen und mehrere Datenmengen bündeln ;)
Getestet mit folgenden Komponenten: ![]() ...:cat:... |
Re: Geschwindigkeit Anonymous Pipes vs Named Pipes vs Mailsl
Nachtrag: Mail Slots sind ca. 30% schneller als Named Pipes aber haben den von Dir genannten Nachteil, daß die Übertragung der Nachrichten nicht garantiert ist.
...:cat:... |
Re: Geschwindigkeit Anonymous Pipes vs Named Pipes vs Mailsl
Wie steht es mit Performance Anonymous Pipes vs Named Pipes?
Hier gibt es zwar ne Menge Infos, aber leider keine Konkrete Aussage zur Geschwindigkeit: ![]() |
Re: Geschwindigkeit Anonymous Pipes vs Named Pipes vs Mailsl
hallo ,
habe mal was gelesen, das es auch first Class mailslots gibt, die einen garantierten verbindungsorientierten Nachrichtenaustausch machen. nur die second class mailslots garantieren keine nachrichtenübermittlung. :gruebel: raik |
Re: Geschwindigkeit Anonymous Pipes vs Named Pipes vs Mailsl
Kann ich leider auch nicht sagen - mit denen habe ich noch nicht gearbeitet ;) Hilft nur selber testen.
...:cat:... |
Re: Geschwindigkeit Anonymous Pipes vs Named Pipes vs Mailsl
Hm, Mailslots 30% schneller...hört sich gut an. Aber: Wenn ich nun eine eigene Benachrichtiung einbauen würde, würden dann 30% verlohren gehen?
Vorgehensweise:
Code:
Mal ne andere Frage: Kann ein Packet lokal überhaupt verlohren gehen? :mrgreen:
Sendender Thread auf Client:
Packet Senden WaitForSingleObject() Empfangender Thread auf Server: Packet abfragen Client entsperren(Waithandle ist im Packet enthalten) Wieviel Messages(Packete) kann ein Mailslot speichern? Wie fragt man Messages "effizent" ab? Also per Timer schon mal "sehr" schlecht ;) Sollte der Server per WaitHandle informiert werden? Per Windowsmessage? Oder verweilt ReadFile() so lange bis eine neue Nachricht da ist? |
Re: Geschwindigkeit Anonymous Pipes vs Named Pipes vs Mailsl
Zitat:
Zitat:
Zitat:
Zitat:
Zitat:
...:cat:... |
Re: Geschwindigkeit Anonymous Pipes vs Named Pipes vs Mailsl
|
Re: Geschwindigkeit Anonymous Pipes vs Named Pipes vs Mailsl
Zitat:
![]() Also ich muss den Server benachritigen wenn neue Daten da sind um effizent antworten zu können, und der Server muss den Empfang auch noch bestätigen...daher stellt sich die Frage ob Anonymous Pipes bzw. Named Pipes da nicht schneller sind. Zitat:
|
Re: Geschwindigkeit Anonymous Pipes vs Named Pipes vs Mailsl
Ist der Server immer auf dem gleichen Rechner wie die Client-App? Wenn ja, dann mache weiter, ansonsten wird es schon eingeschränkt. Wenn der Server im gleichen Netzwerk ist, dann musst Du mit Named Pipes arbeiten, wenn nicht einmal das der Fall ist (Internetspiele), dann musst Du über UDP bzw. TCP gehen.
...:cat:... |
Re: Geschwindigkeit Anonymous Pipes vs Named Pipes vs Mailsl
Zitat:
Ja, wie an Anfang beschrieben, beide Prozesse sind auf dem selben Rechner. Aber ich hab ne flexible Klassenstruktur, so dass Netzwerkkommunikation hinterher auch kein Problem wäre. Der Ebene Nach: TNetServer - Verwaltet sämtliche Verbindungen des Anwenungssystems TNetListener - Registriert sich beim TNetServer und erstellt auf Serverseite TNetSocket-Instanzen TNetSocket - Transportiert Daten von einem Endpunkt zum nächsten. Z.B. über IPC, TCP, ... In diesem Thema geht es nur um diesen Punkt! TNetTransaction - Bei einem Bytestream-orientiertem Socket werden die Nachrichten präpariert bzw. wieder zerteilt, bei einem Message orientierten Socket werden die Daten 1:1 durchgegeicht. TNetChannal - Kleine Anwenundsprotokollebene wie z.B. die Möglichkeit Anfragen zu stellen und Antworten der Anfrage zuzuordnen(Per MessageID). Ein TnetChannel ist an EINE TNetTransaction gebunden und kann mehrere TNetRequest-Instanzen bereitstellen TNetRequest - Anfragen senden, empfangen. Mehrere Threads/Dienste in der Client-Anwendungen erstellen ein TNetRequest. TNetResponse - Die Möglichkeit auf Serverseite auf eine Anfrage auf Channelprotokollebene zu antworten. Die verschiedenen Threads/Dienste verwenden wiederum ihr eigenes "Protokoll" um Daten abzufragen/Bereitzustellen. Warum das ganz? Meine Anwendung ist sehr Datenlastig. Eine SQL-Datenbank ist zu "langsam" (auch wenn sie optimiert ist). Also lade ich sämtliche Arbeitsdaten in den Arbeitsspeicher(Keine Archivdaten!). Es ist nur eine Frage der Zeit, dann sind 2 GB überschritten. Deshalb müssen die Daten auf mehrere Prozesse verteilt werden(64-Bit System vorrausgesetzt). Außerdem soll wenn eine "Client" Anwendung abschmiert nicht das ganze Anwendung mitgerissen werden, denn es sind größere Skalierungen geplant.
Code:
Jeder "Request" der Spieler ist eine Abfrage und/Oder eine Aktion.
---------------- --
|-----|SQL-Datenbank |-----| | | ---------------- | | | | | | | ---------------- | | |-----| DatenService |-----| | | ---------------- | |-- Webserver | | | | | ---------------- | | | | Logik | | | | ---------------- | | | | | | | ---------------- ---------------- | | WebService | | NetService | | ---------------- ---------------- -- | | -------------------------------------- | Internet | -------------------------------------- | | ---------------- ---------------- -- | Webbrowser | | Win32-App | |-- Spieler-Clients ---------------- ---------------- -- Erläuterung: WebService: Er fragt Daten direkt aus dem Datenservice oder SQL-Datenbank ab(falls Archivdaten) und stellt sie ein einer HTML-Seite bereit(lesender Vorgang). Der WebService weiß was der Spieler sehen darf und was nicht(ganz normale Webseite halt). Beisiel: Frage die Daten für Schiff 25433 ab und zeige sie in einer Webseite an. Es wird NICHT gewährleistet dass die Daten, die der WebSerivice empfängt 100% aktuell sind. Optional wird VORHER eine Aktion ausgeführt. Aktionen, also schreibende Vorgänge(meistens nur kleine Signale) werden an den Logik-Baustein weitergeleitet. Also WebService "LIEST" aus SQL-Datenbank und Datenservice und "SCHREIBT" zum Logikbaustein. So gesehen kann der Webservice nichts "kaputt" machen und schmiert er ab - Pech Nur der Logikbaustein ist in der Lage Daten zu verändern. Beispiel: Aktiviere die Schilde von Schiff 25433. Es wird gewährleistet, dass der Logikbaustein IMMER die aktuellsten Werte kennt/abfragen kann. Schmiert der Logikbaustein ab steht zwar das System, aber die Daten sind nocht nicht verlohren. Alle x Minuten werden nämlich Änderungen im DatenService zur SQL-Datenbank geschrieben. Außedem kann sich eine neue Instanz des Logikbausteins wieder neu verbinden. Es darf nur EINE Instanz des Logikbausteins im gesamten Anwendungssystem existieren. Der NetService ist wie der WebService, nur dass dieser keine HTML-Seiten bereitstellt sondern die Daten in einem speziellen Spieler-Client-Protkoll. Der DatenService ist ähnliche wie eine Relationale Datenbank und kann u.U. auf mehrere Prozess-Instanzen verteilt sein. Intern wird ein DataSet und jede Menge Indizierungen verwendet. Die "SQL-Datenbank" sind im Grunde genommen mehrere Datenbanken, die relationale Tabellen enthält. Eine Datenbank für die Spieldaten(Beispiel Schiffe/Planeten), eine für Archivdaten(Private Nachichten), Protokollierungsdatenbank(zur Multisuche etc) und noch ein paar weitere. In diesem Thema geht es halt um die effiziente Kommunikation von Prozess zu Prozess auf dem selben Computer! ;) |
Re: Geschwindigkeit Anonymous Pipes vs Named Pipes vs Mailsl
Was ist nun? Hat dich der Beitrag umgehauen? :?
|
Re: Geschwindigkeit Anonymous Pipes vs Named Pipes vs Mailsl
Ich muss mal antworten :shock:
Ich denke, daß Du den Ansatz noch einmal überprüfen solltest. Ist es wirklich nötig, immerzu alle Daten abzufragen :gruebel: Andere Online-Games machen dieses doch auch in Intervallen. Es kann nicht immer alles überall gleichzeitig sein - so friert Dir bei mehreren Spielern ganz schnell das gesamte Game ein, weil nur noch Daten ausgetauscht werden. Den Ansatz welchen ich für solche Spiele kenne ist etwas anders - aber, so glaube ich, sinnvoller. Die Daten werden i.A. auf einem Game.Server gehalten. Schmiert dieser ab - Pech ;) Der berechnet auch alle Bedingungen, Computerzüge, etc. Die Clients (Human Player) senden ihre Interaktionen an den Server und der führt die aus. Soll eine Einheit etwas machen, die es gar nicht mehr gibt... Pech, wird einfach ignoriert. Gehört dazu (und passiert selten). Zur Darstellung des Spiels auf dem Client wird immer nur der benötigte Bereich übertragen und dem Client mitgeteilt (zzgl. etwas mehr für flüssiges Scrollen). Ausserdem können allgemeine Stati (Truppenanzahl, Geldvorrat, etc.) regelmäßig an die Clients gesandt werden (UDP, wenns verloren geht: na und ;) ) Hin und wieder wird an alle Clients der gesamte Datenbestand übermittelt, damit es beim Absturz des Servers reibungsfrei weitergehen kann (neuer Server muss ermittelt werden). Dein Ansatz würde einfach die gesamte Rechenpower auf die Kommunikation legen. Sämtliche Restzeit für KI, GFX, Sound, Spielerinteraktion würde einfach zu knapp werden. ...:cat:... |
Re: Geschwindigkeit Anonymous Pipes vs Named Pipes vs Mailsl
Wie ich schon sagate, NUR der Logikbaustein muss die aktuellen Werte haben. Dieser Fragt die Daten von DatenService ab und behält sie kurzfristig in einem Cache.
WebService und NetService beötigen keine aktuellen Werte, wird eine Webseite mit falschen Daten herausgegeben - Pech. Ebenfalls haben die Win32-Spieler-Clients keine aktuellen Werte. Die Werte werden zwischengespeichert und nur "seltend" aktualisiert. Von daher ist mir nicht ganz klar was man da optimieren kann. "Andere" Onlinespiele greifen z.B. permanent und für jede Kleinigkeit auf eine SQL-Datenbank zu, die "Anwendung" in Form einer php.exe mit einem Script gesteuert, nach der Ausführungt wird die Anwndung terminiert und vergisst alles nicht gespeicherte. Gut, ich verwende zwar ASP.NET, aber nenne mir den Unterschied: Ob ich nun z.B. für die Planetenübersicht ein SQL-Befehl an die SQL-Datenbank sende den Datenservice frage......zweites dürfte von der Performance schneller sein, Vorraussetzung ist natürlich eine vernüntige Implementierung der IPC-Sockets. Also noch mal zusammenggefasst: WebServcie und NetService greifen direkt auf die SQL-Datenbank und DatenService zu, wie es jede normale z.B. PHP-Seite auch machen würde. Die Daten brauchen nicht aktuell zu sein. Ab und zu Senden WebService und NetService dem Logikbaustein einen Befehl zu...nichts besonderes. Knackpunkt ist halt die Kommunikation zwischen Logikbaustein und DatenService, aber der Logikbaustein wird eh weniger belastet werden als die Anderen Prozesse, da eine Aktion meistens erst nach 3-5 Webseitenaufrufen oder anch unzähligen Abfragen der Win32-Spieler-Clients stattfindet. Warum nicht alles in einem Prozess lassen so wie es jetzt ist? - Weil die Arbeits-Daten irgendwann größer als 2 GB sein werden. Es ist nur eine Frage der Zeit- - Die Trägheit der Datenbank könnte Cheating ermöglichen. Es sind zwar Sperren auf Datensatz ebene möglich, jedoch zieht das die Performance ernorm herunter, vor allem bei einem MMOG(Massen Multiplayer Online Game) Warum nicht alles in eine Datenbank packen und es wie die klassichen PHP-Seite machen? - Auf die Software zugeschnittene Indizierungen sind wichtig und sparen eine Menge Abfragezeit(zumindest im Moment). Beispiel: Jeder Planet hat eine Oberfläche von 7x10 Feldern + Orbit von 2x10 Feldern. Um nun die Kolonieübersicht anzuzeigen wären folgende Möglichkeiten denkbar: SELECT * FROM Planets WHERE user_id=x; für jeden Planet im Ergebnis: SELECT * FROM fields WHERE field_planet_id=x Sehr langsam. Daher verwende ich z.b. zur Zeit eine HashTable. Key: PlanetID, Value: Array of DataRow (der Fields, sind in der Regel 70 Stück) Die Hashtable speichert die Oberflächen zwischen - Schnellste Möglichkeit oder: SELECT * FROM planets, fields WHERE planet_id=field_planet_id AND planet_user_id=x Es werden zu viel Daten abgefragt oder: Man füge der Tabelle fields eine UserID hinzu: SELECT * FROM Planets WHERE user_id=x; SELECT * FROM fields WHERE field_user_id=x; Sehr schnell, jedoch ist die fields-Tabelle auf eine bestimtme Abfrage optimiert worden. Da fields zu planet gehört und planet den Besitzer kennt ist es grauenvoll in der fields-Tabelle den Besitzer ebenfalls zu speichern. Oder: SELECT * FROM Planets WHERE user_id=x; SELECT * FROM fiels WHERE field_planet_id=y1 OR field_planet_id=y2 OR .... Auch ne Möglichkeit, habe ich aber ehrlichgesagt noch nicht ausprobiert, war bisher ja auch nie nötig. Geschwindigkeitsmessung: Microsoft SQL-Server schafft ca. 500 Planetenoberflächen abzufragen. Ein Spieler könnte aber ca. 100 Planeten haben. Und wenn es nur die Planetenoberflächen wären.....dies war ein Beispiel von vielen. Gemessen auf einem 2 Ghz Celeron. Falls wir uns mißverstanden haben sollten: Der Datenservice stellt ganze Datensäzte bereit, es werden keine Felder in Echtzeit abgefragt(Das wären nämlich "nur" ca. 50.000 Variabelabfragen PRO Webseitenaufruf für einen Spieler der NUR 6 Planeten hat). Der DatenService informiert den WebService und NetService nur bei einer Änderung(Windowsmessage), WebService und NetService müssen dann selber schauen ob sie nun ein Refresh des Datensatzes machen(Wird nur für bestimmte Objekte notwendig sein wie z.B. die Galaxie-Übersicht). Zur Zeit schafft der DatenService ca. 6000 Datensatz in der Sekunde, wenn über die RowID gegangen wird. Ob es nur eine Row ist oder 70, das spielt dabei eine relativ kleine Rolle, die Serialisierung geht sehr schnell, die Datenbank bleibt auch unbedeutend klein. Der DatenService schafft ca. 12.000 Zeilen-Updates, jedoch ohne dass der Client wartet. Gemssen auf einem 1,3 Ghz AMD. Ich schließe natürlich nicht aus dass ich einen Designfehler in meiner Software habe, für Tipps bin ich gern hellhörig ;) |
Re: Geschwindigkeit Anonymous Pipes vs Named Pipes vs Mailsl
Zitat:
Zitat:
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 21:53 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz