Ich arbeite an einer MUD-Engine und möchte es ein wenig anders machen als alle MUD-Spiele, die ich gespielt habe. Ich finde ein "Fahrrad" -System sehr langweilig. Eine der Ideen, die ich hatte, war, dass jeder Client-Socket in seinem eigenen Thread funktioniert. Ich bin mir bewusst, dass es nicht mit Hunderten von Spielern enden wird, aber ich würde gerne wissen, ob es Probleme gibt, "eine Menge" Threads in einem einzigen Prozess zu erstellen.
Oder welche andere Strategie könnte ich verwenden, wenn ich es (z. B. Kämpfe) in "Echtzeit" machen möchte.
Ich hoffe ihr versteht die Frage.
Vielen Dank.
quelle
Tut mir leid wegen der Thread-Nekromantie, aber dieses Problem ist mein LIEBLINGS-Haustierprojekt zum Lernen und Lehren von Parallelitätsmodellen und Frameworks!
Das Ausführen jedes Clients / Mobs in einem eigenen Thread ergibt eine natürliche Unterteilung, aber wie mehrere angemerkt haben, sind Threads teuer, wenn Sie mehr davon verwenden als Sie CPU-Kerne haben. Wenn dies kein zwingender Grund ist, es nicht in Ihrem MUD zu verwenden, ist es dennoch ein guter Grund, einen besseren Weg zu lernen.
Das Ausführen aller Clients in einer einzigen Spielschleife mit fester Zeit und Aktionen, die einige Schleifen umfassen, ist eine bekannte Methode aus der Welt der grafischen Spiele. Es bindet alles auf der Welt an denselben Zeitzyklus, obwohl eine ausreichende Feinkörnung der Schleifen dies maskieren kann. Der Hauptnachteil dieser Methode ist meines Erachtens, dass sie nicht von Natur aus parallelisierbar ist. Jemand bemerkte, dass Sie Threads erstellen können, um das Erstellen / Parsen / Transceiving von E / A, das Ausführen von KI usw. auf andere Threads zu verlagern. Die Parallelisierung der Hauptspiellogik erfordert jedoch eine grundlegende Änderung und viel Arbeit, um die Thread-Sicherheit zu gewährleisten.
Wenn Sie all diese Arbeiten erledigt hätten, hätten Sie wahrscheinlich etwas Ähnliches wie meinen aktuellen Favoriten, das Actor-Modell ( http://en.wikipedia.org/wiki/Actor_model ). Das Actor-Modell ist eine Time-Sharing-Strategie, die ziemlich genau dem entspricht, was Sie mit der One-Thread-per-Client-Idee vorgeschlagen haben. Wenn Sie es verwenden, codieren Sie Ihre "Akteure" wie eigenständige Threads, mit einigen Einschränkungen: Sie müssen ereignisgesteuert sein und können nur durch Weiterleiten von Nachrichten mit dem Rest des Systems kommunizieren (was anders, aber einfach ist). Das ereignisgesteuerte Bit bietet Platz für Ihr wirklich unabhängiges Timing, indem aktorspezifische Ereignisse so geplant werden, dass sie zu bestimmten Zeiten ausgelöst werden, z. B. wenn eine Aktion abgeschlossen ist oder mit einer bestimmten Client-Häufigkeit.
Unter der Haube verwendet die Implementierung eine Warteschlange (oder Warteschlangen) von Nachrichten, die von allen Akteuren generiert werden, und einen Pool von Threads, die Ihrer Anzahl von CPU-Kernen entsprechen. Die Threads ziehen Nachrichten aus den Warteschlangen und rufen die Nachrichtenbehandlungsmethoden des Empfängerakteurs auf, um sie zu verarbeiten. Sie werden im Kontext dieses Akteurs ausgeführt, bis die Nachricht "verarbeitet" wird. Aus Ihrer Sicht erhält jeder Akteur seinen eigenen Thread, wann immer er tatsächlich ausgeführt wird. Aus Sicht des Systems gibt es jedoch nur so viele Threads wie CPUs, um sie auszuführen.
Es gibt einige großartige Actor-Frameworks, nämlich Erlang / OTP und Akka, aber die Grundidee ist so einfach, dass Sie sie in jeder Sprache ohne den zusätzlichen Aufwand eines Frameworks implementieren können.
Der Vollständigkeit halber ist das Actor-Modell eigentlich nur die Kombination aus Nachrichtenübermittlung für die Thread-Sicherheit, ereignisgesteuerter Programmierung für die Parallelität und einem Thread-Dispatching-Mechanismus. Wenn Sie die Thread-Dispatch-Bits entfernen würden, hätten Sie ein "reaktives" System, das derzeit für die Skalierbarkeit im Allgemeinen sehr beliebt ist (siehe http://www.reactivemanifesto.org/ ). Sie können die Ausführung dann mehreren Computern in einer Cloud oder was auch immer zuordnen ... Sie haben die Idee ... was alles bedeutet, dass Ihr MUD-Programmierprojekt Ihnen möglicherweise marktfähige Programmierkenntnisse vermittelt. Hurra!
quelle
Sie können Kampfbefehle beim Eingang zulassen und dann nach Befehlen eine Zeitverzögerung hinzufügen, die davon abhängt, wie lange die Ausführung dauern würde.
Dragonrealms verwendet diese Methode für den Kampf sowie für viele andere Aktionen. Dort wird sie Roundtime genannt. Schwerere Waffen haben eine längere Zeit und Sie können sie reduzieren, aber nicht mit Stärke und Beweglichkeit eliminieren.
quelle
Die Vernetzung ist ohnehin serieller Natur (zumindest bis Sie in Glasfaserleitungen mit mehreren Tbit / s einsteigen). Es ist sinnvoll, einen Thread für Netzwerk-E / A getrennt von der Spielelogik und möglicherweise einige autonome Agent-Threads zu haben. Alles andere ist übertrieben.
quelle