
Hallo habrozhiteli! Das Buch von Riccardo Terrell enthĂ€lt Anleitungen zur Erstellung wettbewerbsfĂ€higer und skalierbarer Programme in .NET, in denen die Vorteile eines funktionalen Paradigmas hervorgehoben und die geeigneten Tools und Prinzipien bereitgestellt werden, um den Wettbewerb wettbewerbsfĂ€hig und einfach zu halten. Als Ergebnis erhalten Sie mit neuen FĂ€higkeiten das Wissen, das Sie benötigen, um ein Experte fĂŒr die Bereitstellung erfolgreicher Hochleistungslösungen zu werden.
Wenn Sie Multithread-Code in .NET schreiben, kann Ihnen dieses Buch helfen. Wenn Sie ein Funktionsparadigma verwenden möchten, um die wettbewerbsfĂ€hige Programmierung zu vereinfachen und die Anwendungsleistung zu maximieren, ist dieses Buch ein wichtiger Leitfaden fĂŒr Sie. Dies kommt jedem .NET-Entwickler zugute, der wettbewerbsfĂ€hige, reaktive und asynchrone Anwendungen schreiben möchte, die skaliert und sich automatisch an verfĂŒgbare Hardwareressourcen anpassen, wo immer solche Programme funktionieren.
Publikationsstruktur: Roadmap
Die vierzehn Kapitel dieses Buches sind in drei Teile unterteilt. Teil I stellt die funktionalen Konzepte der Wettbewerbsprogrammierung vor und beschreibt die FĂ€higkeiten, die erforderlich sind, um die funktionalen Aspekte des Schreibens von Multithread-Programmen zu verstehen.
- Kapitel 1 beschreibt die grundlegenden Konzepte und Ziele der wettbewerbsfĂ€higen Programmierung sowie die GrĂŒnde fĂŒr die Verwendung der funktionalen Programmierung zum Schreiben von Multithread-Anwendungen.
- In Kapitel 2 werden verschiedene funktionale Programmiertechnologien untersucht, um die Leistung von Multithread-Anwendungen zu verbessern. Der Zweck dieses Kapitels ist es, dem Leser die im Rest des Buches verwendeten Konzepte zu vermitteln und kraftvolle Ideen vorzustellen, die sich aus einem funktionalen Paradigma ergeben.
- Kapitel 3 gibt einen Ăberblick ĂŒber das Funktionskonzept der UnverĂ€nderlichkeit. Es wird erklĂ€rt, wie UnverĂ€nderlichkeit verwendet wird, um vorhersehbare und korrekte Wettbewerbsprogramme zu schreiben und funktionale Datenstrukturen zu implementieren, die threadsicher sind.
In Teil II werden verschiedene Modelle der Wettbewerbsprogrammierung in einem Funktionsparadigma eingehend untersucht. Wir werden Themen wie die Task Parallel Library (TPL) untersuchen und parallele Muster wie Fork / Join, Divide and Conquer und MapReduce implementieren. In diesem Abschnitt werden auch das deklarative Layout, allgemeine Abstraktionen bei asynchronen Operationen, die Agentenprogrammierung und die Semantik der NachrichtenĂŒbertragung erlĂ€utert.
- Kapitel 4 beschreibt die Grundlagen der parallelen Verarbeitung groĂer Datenmengen, einschlieĂlich Vorlagen wie Fork / Join.
- In Kapitel 5 werden komplexere Methoden fĂŒr die parallele Verarbeitung groĂer Informationsmengen vorgestellt, z. B. parallele Aggregation, Datenreduktion und Implementierung einer parallelen MapReduce-Vorlage.
- Kapitel 6 enthĂ€lt detaillierte Informationen zu den Funktionsmethoden fĂŒr die Verarbeitung von Ereignisströmen (Datenströmen) in Echtzeit mithilfe der Funktionsoperatoren höherer Ordnung in .NET Reactive Extensions zur Bildung asynchroner Ereigniskombinatoren. Die untersuchten Methoden werden dann verwendet, um eine wettbewerbsfĂ€hige reaktive Vorlage fĂŒr Publisher und Abonnenten zu implementieren.
- Kapitel 7 enthĂ€lt eine ErlĂ€uterung des aufgabenbasierten Programmiermodells fĂŒr die funktionale Programmierung zur Implementierung wettbewerbsfĂ€higer Operationen unter Verwendung der Monadic-Vorlage. Diese Methode wird dann verwendet, um eine wettbewerbsfĂ€hige Pipeline basierend auf einem funktionalen Programmierparadigma aufzubauen.
- Kapitel 8 befasst sich mit der Implementierung von unbegrenztem parallelem Rechnen unter Verwendung des asynchronen C # -Programmiermodells. In diesem Kapitel werden auch Fehlerbehandlungsmethoden und Methoden zum Erstellen asynchroner Operationen erlÀutert.
- Kapitel 9 beschreibt den asynchronen Workflow in F #. Es zeigt, wie eine verzögerte und explizite Bewertung in diesem Modell eine höhere Kompositionssemantik ermöglicht. AnschlieĂend lernen wir, wie benutzerdefinierte BerechnungsausdrĂŒcke implementiert werden, um den Abstraktionsgrad fĂŒr die deklarative Programmierung zu erhöhen.
- Kapitel 10 zeigt, wie basierend auf den in den vorherigen Kapiteln gewonnenen Erkenntnissen Kombinatoren und Vorlagen wie Functor, Monad und Applicative implementiert werden können, um mehrere asynchrone Operationen zu erstellen und auszufĂŒhren und Fehler ohne Nebenwirkungen zu behandeln.
- Kapitel 11 analysiert die reaktive Programmierung mithilfe eines Software-Messaging-Modells. Es zeigt das Konzept der natĂŒrlichen Isolation als eine Technologie, die die UnverĂ€nderlichkeit ergĂ€nzt und die Erstellung wettbewerbsfĂ€higer Programme ermöglicht. Dieses Kapitel konzentriert sich auf die MailboxProcessor-Klasse, die in F # zum Verteilen paralleler Arbeit mithilfe der Agentenprogrammierung und eines ressourcenfreien Ansatzes verwendet wird.
- Kapitel 12 beschreibt die Agentenprogrammierung mithilfe der TPL-Datenflussbibliothek aus .NET anhand von Beispielen in C #. Es wird gezeigt, wie zustandslose und statusbehaftete Agenten in C # implementiert werden und wie mehrere Berechnungen parallel durchgefĂŒhrt werden, die Daten miteinander austauschen, indem Nachrichten im Stil einer Pipeline gesendet werden.
Teil III zeigt, wie alle in den vorhergehenden Kapiteln untersuchten funktionalen Methoden der Wettbewerbsprogrammierung in die Praxis umgesetzt werden können.
- Kapitel 13 enthĂ€lt eine Reihe nĂŒtzlicher Rezepte zur Lösung komplexer Wettbewerbsprobleme aus der Praxis. Diese Rezepte verwenden alle in diesem Buch beschriebenen Funktionsmuster.
- Kapitel 14 beschreibt eine vollwertige Anwendung, die unter Verwendung der in diesem Buch erlernten funktionalen Wettbewerbsvorlagen und -methoden entwickelt und implementiert wurde. Sie erstellen eine hoch skalierbare, reaktionsschnelle Serveranwendung und ein reaktionsschnelles Clientprogramm. Das Buch enthĂ€lt zwei Versionen: eine fĂŒr iOS (iPad), die mit Xamarin Visual Studio erstellt wurde, und die zweite, die mit Windows Presentation Foundation (WPF) erstellt wurde. Um maximale Skalierbarkeit in der Serveranwendung sicherzustellen, wird eine Kombination verschiedener Programmiermodelle wie asynchron, agent und reaktiv verwendet.
Das Buch enthÀlt auch drei Anwendungen.
- Anhang A beschreibt kurz die grundlegenden Konzepte der funktionalen Programmierung und stellt die grundlegende Theorie der in diesem Buch verwendeten funktionalen Methoden vor.
- Anhang B enthĂ€lt die Grundkonzepte der F # -Sprache. Dies ist eine grundlegende ĂberprĂŒfung von F #, mit der Sie sich mit dieser Sprache vertraut machen und sich beim Lesen eines Buches wohler fĂŒhlen können.
- Anhang B zeigt verschiedene Methoden, die die Interaktion zwischen einem asynchronen Workflow in F # und einer .NET-Task in C # vereinfachen.
Auszug. 11.6. F # MailboxProcessor: 10.000 Agenten fĂŒr Game of Life
Im Vergleich zu Threads ist MailboxProcessor in Kombination mit asynchronen Workflows eine einfache Recheneinheit (primitiv). Agenten können mit minimalen Kosten erscheinen und zerstört werden. Sie können die Arbeit auf mehrere MailboxProcessor-Objekte auf dieselbe Weise verteilen, wie Sie Threads verwenden können, ohne den zusĂ€tzlichen Aufwand fĂŒr das Erstellen eines neuen Threads. Dank dessen ist es durchaus möglich, Anwendungen zu erstellen, die aus Hunderttausenden von Agenten bestehen, die parallel arbeiten, wobei die Computerressourcen minimal belastet werden.
In diesem Abschnitt werden wir mehrere Instanzen von MailboxProcessor verwenden, um das Spiel Game of Life (das Spiel "Life") (
wiki-eng und
wiki-rus ) zu implementieren. Laut Wikipedia ist das Spiel des Lebens in einfachen Worten ein zellularer Automat. Dies ist ein Spiel ohne Spieler - mit anderen Worten, wenn ein Spiel mit einer zufĂ€lligen Anfangskonfiguration beginnt, wird es ohne weitere Eingaben ausgefĂŒhrt. Das Spiel besteht aus einer Reihe von Zellen, die ein Gitter bilden. In jeder Zelle sind mehrere mathematische Regeln erfĂŒllt. Zellen können leben, sterben und sich vermehren. Jede Zelle interagiert mit acht Nachbarn (Nachbarzellen). Um Zellen gemÀà diesen Regeln zu verschieben, muss der neue Zustand des Gitters stĂ€ndig berechnet werden.
Game of Life hat folgende Regeln:
- Wenn eine Zelle nur einen Nachbarn oder keine Nachbarn hat, stirbt sie "an Einsamkeit".
- Wenn vier oder mehr Nachbarn einer Zelle sterben, stirbt sie âaufgrund von Ăberbevölkerungâ.
- Wenn die Zelle zwei oder drei Nachbarn hat, bleibt sie zu leben.
- Wenn eine Zelle drei Nachbarn hat, multipliziert sie sich.
AbhÀngig von den Anfangsbedingungen bilden die Zellen wÀhrend des Spiels charakteristische Strukturen. Durch wiederholte Anwendung der Regeln werden die folgenden Generationen von Zellen erzeugt, bis die Zellen einen stabilen Zustand erreichen (Abb. 11.12).
Listing 11.9 zeigt die Implementierung der Game of Life AgentCell-Zelle basierend auf den F # -Typen von MailboxProcessor. Jede Agentenzelle interagiert ĂŒber asynchrones Messaging mit benachbarten Zellen und erstellt so ein vollstĂ€ndig parallelisiertes Spiel des Lebens. Der KĂŒrze halber habe ich einige Teile des Codes weggelassen, da sie nicht mit dem Hauptthema des Beispiels zusammenhĂ€ngen. Die vollstĂ€ndige Implementierung finden Sie im Quellcode fĂŒr dieses Buch, der auf der Website des Herausgebers veröffentlicht ist.


AgentCell beschreibt eine Zelle im Game of Life-Raster. Das Grundkonzept besteht darin, dass jeder Agent durch asynchrones Messaging Informationen mit benachbarten Zellen ĂŒber seinen aktuellen Status austauscht. Diese Vorlage erstellt eine Kette miteinander verbundener paralleler Kommunikation, bei der alle Zellen ihren aktualisierten Status an den MailboxProcessor updateAgent senden. Nach Erhalt dieser Daten aktualisiert updateAgent die Grafiken in der BenutzeroberflĂ€che (Listing 11.10).
updateAgent aktualisiert, wie der Name schon sagt, den Status jedes Pixels gemÀà dem in der Aktualisierungsnachricht empfangenen Zellenwert. Der Agent behÀlt den Status der Pixel bei und erstellt daraus ein neues Bild, wenn alle Zellen ihren neuen Status weitergeben. UpdateAgent aktualisiert dann die WPF-GUI mithilfe dieses neuen Bildes, das dem aktuellen Game of Life-Raster entspricht:
do! Async.SwitchToContext ctx image.Source <- createImage pixels do! Async.SwitchToThreadPool()
Es ist wichtig zu beachten, dass der updateAgent den aktuellen Synchronisationskontext verwendet, um den WPF-Controller korrekt zu aktualisieren. Der aktuelle Thread wird mit der Funktion Async.SwitchToContext (beschrieben in Kapitel 9) auf den BenutzeroberflÀchenthread umgeschaltet.
Der letzte Code, der Game of Life ausfĂŒhrt, generiert ein Raster, das als Spielplatz fĂŒr die Zellen dient. AnschlieĂend benachrichtigt der Timer die Zellen ĂŒber die Notwendigkeit einer Aktualisierung (Listing 11.11). In diesem Beispiel ist das Raster ein Quadrat aus 100 Ă 100 Zellen, insgesamt 10.000 Zellen (MailboxProcessor-Objekte), die alle 50 ms parallel zu einem Timer berechnet werden, wie in Abb. 11.13. Zehntausend MailboxProcessor-Objekte interagieren und aktualisieren die BenutzeroberflĂ€che 20 Mal pro Sekunde (der Code, auf den Sie achten sollten, ist fett gedruckt).
Benachrichtigungen an alle Zellen (Agenten) werden parallel mit PLINQ gesendet. Zellen sind F # -Sequenzen, die als .NET IEnumerable behandelt werden, wodurch LINQ / PLINQ einfach zu integrieren ist.
Wenn der Code ausgefĂŒhrt wird, generiert das Programm in weniger als 1 ms 10.000 F # -Objekte vom Typ MailboxProcessor, wĂ€hrend die Agenten weniger als 25 MB Speicher belegen. Beeindruckend!
Zusammenfassung
- Das agentenbasierte Programmiermodell bietet natĂŒrlich UnverĂ€nderlichkeit und Isolation beim Schreiben wettbewerbsfĂ€higer Systeme, was die Diskussion komplexer Systeme noch einfacher macht, da Agenten in aktiven Objekten eingekapselt sind.
- Ein reaktives Manifest definiert die Eigenschaften fĂŒr die Implementierung eines reaktiven Systems, das flexibel, lose gekoppelt und skalierbar ist.
- NatĂŒrliche Isolation ist wichtig, um wettbewerbsfĂ€higen Code zu schreiben, ohne ihn zu blockieren. In einem Multithread-Programm löst die Isolation das Problem gemeinsamer ZustĂ€nde, indem jedem Thread ein kopiertes Datenelement zur VerfĂŒgung gestellt wird, um lokale Berechnungen durchzufĂŒhren. Bei Verwendung der Isolierung gibt es keine Rennbedingung.
- Da Agenten asynchron sind, sind sie einfach, da sie keine Threads blockieren, wÀhrend sie auf Nachrichten warten. Infolgedessen können Sie Hunderttausende von Agenten in einer Anwendung verwenden, ohne die SpeicherkapazitÀt wesentlich zu beeinflussen.
- Ein MailboxProcessor F # -Objekt bietet eine bidirektionale Kommunikation: Ein Agent kann einen asynchronen Kanal verwenden, um das Ergebnis der Berechnung an das aufrufende Objekt zurĂŒckzugeben (zu beantworten).
- Das Agentenprogrammiermodell in F # ĂŒber MailboxProcessor ist ein hervorragendes Tool zum Beheben von EngpĂ€ssen in Anwendungen, z. B. bei gleichzeitigem Datenbankzugriff. Mithilfe von Agenten können Sie die Anwendung erheblich beschleunigen und gleichzeitig die ReaktionsfĂ€higkeit des Servers gewĂ€hrleisten.
- In anderen .NET-Programmiersprachen können Sie den MailboxProcessor vom Typ F # verwenden und Methoden mithilfe des praktischen TPL-Programmiermodells bereitstellen, das auf Aufgaben basiert.
»Weitere Informationen zum Buch finden Sie auf
der Website des Herausgebers»
Inhalt»
Auszug20% Rabatt auf Gutschein fĂŒr HĂ€ndler -
ParallelitÀt in .NETNach Zahlung der Papierversion des Buches wird eine elektronische Version des Buches per E-Mail verschickt.