Leistungseinbußen bei der Nachrichtenübergabe im Gegensatz zu freigegebenen Daten

8

Heutzutage gibt es viel Aufregung darüber, keine Sperren zu verwenden und Message-Passing-Ansätze wie Erlang zu verwenden. Oder über die Verwendung unveränderlicher Datenstrukturen wie in Functional Programming vs. C ++ / Java.

Aber was mich beschäftigt, ist folgendes:

  1. AFAIK, Erlang garantiert keine Nachrichtenübermittlung. Nachrichten können verloren gehen. Wird der Algorithmus und der Code nicht aufgebläht und wieder kompliziert, wenn Sie sich Gedanken über den Verlust von Nachrichten machen müssen? Welcher verteilte Algorithmus Sie auch verwenden, hängt nicht von der garantierten Zustellung von Nachrichten ab.
  2. Was ist, wenn die Nachricht ein kompliziertes Objekt ist? Gibt es nicht eine große Leistungseinbuße beim Kopieren und Versenden der Nachrichten im Gegensatz zu dem Beibehalten eines gemeinsamen Speicherorts (wie bei einer DB, auf die beide Prozesse zugreifen können)?
  3. Kannst du wirklich gemeinsame Zustände beseitigen? Ich denke nicht. Für z.B. In einem DB müssen Sie auf denselben Datensatz zugreifen und diesen ändern. Sie können keine Nachrichten verwenden, die dort übergeben werden. Sie müssen Locking-Mechanismen verwenden oder Optimistic-Mechanismen zur Steuerung des gemeinsamen Zugriffs akzeptieren und dann Rollbacks für Fehler durchführen. Wie funktioniert Mnesia?
  4. Es ist auch nicht so, dass Sie sich immer Gedanken um Nebenläufigkeit machen müssen. Jedes Projekt wird auch einen großen Code haben, der nichts mit Nebenläufigkeit oder Transaktionen zu tun hat (aber sie haben Leistung und Geschwindigkeit als ein Anliegen). Viele dieser Algorithmen hängen von gemeinsamen Zuständen ab (deshalb sind Pass-by-Reference oder Zeiger so nützlich).

Angesichts dieser Tatsache ist das Schreiben von Programmen in Erlang usw. ein Schmerz, weil Sie daran gehindert werden, irgendwelche dieser Dinge zu tun. Vielleicht macht es Programme robust, aber für Dinge wie die Lösung eines Problems der linearen Programmierung oder die Berechnung der konvexen Hülle usw. ist die Leistung wichtiger und erzwingt die Unveränderbarkeit usw. des Algorithmus, wenn es nichts mit Nebenläufigkeit / Transaktionen zu tun hat . Ist es nicht?

    
user855 27.11.2009, 19:24
quelle

7 Antworten

6
  1. Das ist das wirkliche Leben : Sie müssen diese Möglichkeit ungeachtet der Sprache / Plattform berücksichtigen. In einer verteilten Welt (der realen Welt) versagen die Dinge: lebe damit.

  2. Natürlich gibt es Kosten : Nichts ist in unserem Universum frei. Aber sollten Sie nicht ein anderes Medium (z. B. Datei, db) verwenden, anstatt "große Objekte" in Kommunikationsleitungen zu pendeln? Sie können immer "Nachricht" verwenden, um auf "große Objekte" zu verweisen, die irgendwo gespeichert sind.

  3. Natürlich nicht: Die Idee hinter der funktionalen Programmierung / Erlang OTP ist, isolieren so viel wie möglich die Bereiche, in denen "shared state" manipuliert wurde. Darüber hinaus hilft die eindeutige Markierung von Orten , in denen der gemeinsame Status mutiert ist, die Testbarkeit & amp; Rückverfolgbarkeit.

  4. Ich glaube, Sie vermissen den Punkt: Es gibt keine Silberkugel. Wenn Ihre Anwendung nicht erfolgreich mit Erlang erstellt werden kann, tun Sie es nicht. Sie können immer einen anderen Teil des Gesamtsystems auf andere Weise verwenden, d. H. Eine andere Sprache / Plattform verwenden. Erlang unterscheidet sich in dieser Hinsicht nicht von einer anderen Sprache: Verwenden Sie das richtige Werkzeug für den richtigen Job .

Erinnern Sie sich: Erlang wurde entwickelt, um gleichzeitige , asynchrone und verteilte Probleme zu lösen. Es ist nicht optimiert, um effizient auf einem freigegebenen Speicherblock zu arbeiten, zum Beispiel ... es sei denn, Sie zählen mit nif functions arbeiten mit geteilten Blöcken Teil des Spiels: -)

    
jldupont 27.11.2009, 19:33
quelle
3

Systeme der realen Welt sind sowieso immer Hybride : Ich glaube nicht, dass die modernen Paradigmen in der Praxis versuchen, veränderliche Daten und den gemeinsamen Zustand loszuwerden.

Das Ziel besteht jedoch nicht darin, einen gleichzeitigen Zugriff auf diesen gemeinsamen Status zu benötigen. Programme können in die gleichzeitige und die sequenzielle unterteilt werden und Message-Passing und die neuen Paradigmen für die gleichzeitigen Teile verwenden.

Nicht jeder Code erhält dieselbe Investition : Es gibt Bedenken, dass Threads grundsätzlich als "schädlich" eingestuft werden. So etwas wie Apache kann traditionelle gleichzeitige Threads erfordern, und ein Schlüsselelement solcher Technologie kann über einen Zeitraum von Jahren hinweg sorgfältig verfeinert werden, so dass es mit einem vollständig gleichzeitigen gemeinsamen Zustand explodieren kann. Betriebssystem-Kernel sind ein weiteres Beispiel, wo "das Problem lösen, egal wie teuer es ist" sinnvoll sein kann.

Es gibt keinen Vorteil für Fast-but-broken : Aber für neuen Code oder Code, der nicht so viel Aufmerksamkeit bekommt, kann es der Fall sein, dass es einfach nicht Thread- ist sicher, und es wird nicht mit der echten Nebenläufigkeit umgehen, und so ist die relative "Effizienz" irrelevant. Ein Weg funktioniert und ein Weg nicht.

Vergessen Sie nicht die Testbarkeit: Auch welchen Wert können Sie beim Testen haben? Thread-Shared-Memory-Concurrency ist einfach nicht testbar. Message-passing Concurrency ist. Jetzt hast du die Situation, in der du ein Paradigma testen kannst, aber nicht das andere. Also, was ist der Wert zu wissen, dass der Code getestet wurde? Die Gefahr, nicht einmal zu wissen, ob der andere Code in jeder Situation funktioniert?

    
DigitalRoss 27.11.2009 19:32
quelle
3

Es gibt einige implizite Annahmen in Ihren Fragen - Sie gehen davon aus, dass alle Daten passen auf einer Maschine und dass die Anwendung intrinsisch an einer Stelle lokalisiert ist.

Was passiert, wenn die Anwendung so groß ist, dass sie nicht auf eine Maschine passt? Was passiert, wenn die Anwendung eine Maschine verlässt?

Sie möchten keine Möglichkeit haben, eine Anwendung zu programmieren, wenn sie auf einen Rechner passt und eine völlig andere Art, es zu programmieren, sobald es aus einer Maschine herauswächst.

Was passiert, wenn Sie eine fehlertolerante Anwendung erstellen möchten? Um etwas fehlertolerant zu machen, benötigen Sie mindestens zwei physisch getrennte Maschinen und keine gemeinsame Nutzung . Wenn Sie über das Teilen und Datenbanken sprechen, erwähnen Sie Dinge wie mySQL Cluster erreichen Fehlertoleranz gerade durch die Aufrechterhaltung synchronisierter Kopien der Daten in physisch getrennten Maschinen - es gibt eine Menge Nachrichtenübergabe und Kopieren, das man nicht auf der Oberfläche sieht - Erlang stellt dies bloß bloß.

Die Art und Weise, wie Sie programmieren, sollte nicht plötzlich geändert werden, um Fehlertoleranz und Skalierbarkeit zu berücksichtigen.

Erlang wurde in erster Linie für fehlertolerante Anwendungen entwickelt.

Freigegebene Daten auf einem Multicore haben ihre eigenen Probleme - wenn Sie auf gemeinsam genutzte Daten zugreifen Sie müssen eine Sperre erwerben - wenn Sie eine globale Sperre verwenden (die einfachste Methode), können Sie enden Anhalten aller Kerne, während Sie auf die freigegebenen Daten zugreifen. Gemeinsamer Datenzugriff auf einem Multicore kann problematisch sein aufgrund von Caching-Problemen, wenn die Kerne lokale Datencaches haben und der Zugriff auf "weit entfernte" Daten (in einigen anderen Prozessoren Cache) kann sehr teuer sein.

Viele Probleme sind intrinsisch verteilt und die Daten sind niemals an einem Ort verfügbar gleichzeitig so - diese Art von Problemen passen gut zur Erlang-Art des Denkens.

In einer verteilten Einstellung ist die "garantierte Nachrichtenübermittlung" unmöglich - der Zielcomputer ist möglicherweise abgestürzt. Erlang kann daher die Zustellung der Nachricht nicht garantieren - Es ist ein anderer Ansatz - das System teilt Ihnen mit, wenn es versäumt hat, eine Nachricht zu senden (aber nur, wenn Sie den Link-Mechanismus verwendet haben) - dann können Sie Ihren eigenen benutzerdefinierten Fehler schreiben Wiederherstellung.)

Für reines Zahlenknirschen ist Erlang nicht geeignet - sondern in einem Hybridsystem Erlang ist gut darin zu verwalten, wie Berechnungen auf verfügbare Prozessoren verteilt werden, so dass wir eine Menge Systeme sehen, in denen Erlang die Verteilung und fehlertolerante Aspekte des Problems verwaltet, aber das Problem selbst wird in einer anderen Sprache gelöst.

und andere Sprachen werden verwendet

    
ja. 30.11.2009 14:55
quelle
2

Ein paar Kommentare zu dem Missverständnis, das Sie von Erlang haben:

  • Erlang garantiert, dass Nachrichten nicht verloren gehen und dass sie in der gesendeten Reihenfolge ankommen. Eine grundlegende Fehlersituation ist, dass Maschine A nicht mit Maschine B sprechen kann. Wenn dies geschieht, werden Prozessmonitore und -verbindungen ausgelöst und System-Node-Down-Nachrichten werden an die Prozesse gesendet, die für sie registriert wurden. Nichts wird stillschweigend fallen gelassen. Prozesse werden "abstürzen" und Supervisor (falls vorhanden) versuchen, sie neu zu starten.
  • Objekte können nicht mutiert werden, sodass sie immer kopiert werden. Eine Möglichkeit, die Unveränderbarkeit zu sichern, besteht darin, Werte in andere Erlang-Prozesshaufen zu kopieren. Eine andere Möglichkeit besteht darin, Objekte in einem gemeinsamen Heap zuzuweisen, auf sie zu verweisen und einfach keine Operationen zu haben, die sie mutieren. Erlang macht die erste Leistung! Echtzeit leidet, wenn Sie alle Prozesse stoppen müssen, um einen gemeinsamen Heap zu sammeln. Fragen Sie Java.
  • In Erlang gibt es einen geteilten Staat. Erlang ist nicht stolz darauf, aber es ist pragmatisch. Ein Beispiel ist die lokale Prozessregistrierung, bei der es sich um eine globale Zuordnung handelt, die einen Namen einem Prozess zuordnet, sodass Systemprozesse neu gestartet werden können und ihren alten Namen beanspruchen können. Erlang versucht nur Shared State zu vermeiden, wenn es möglich ist . ETS-Tabellen, die öffentlich sind, sind ein anderes Beispiel.
  • Ja, manchmal ist Erlang zu langsam. Das passiert in allen Sprachen. Manchmal ist Java zu langsam. Manchmal ist C ++ zu langsam. Nur weil eine enge Schleife in einem Spiel zur Assembly herunterfallen musste, um einige ernsthafte SIMD-basierte Vektor-Mathematik zu starten, kann man nicht ableiten, dass alles in Assembly geschrieben werden sollte, weil es die einzige Sprache ist, die schnell ist, wenn es darauf ankommt. Es kommt darauf an, Systeme mit einer guten Leistung zu schreiben, und Erlang kommt gut zurecht. Siehe Benchmarks für Gier oder Hasenmq.

Ihre Fakten sind keine Fakten über Erlang. Selbst wenn Sie denken, Erlang Programmierung ist ein Schmerz, werden Sie andere Leute finden, einige tolle Software dank ihr zu erstellen. Sie sollten versuchen, einen IRC-Server in Erlang oder etwas sehr gleichzeitiges zu schreiben. Selbst wenn Sie Erlang nie wieder benutzen würden, hätten Sie gelernt, über Nebenläufigkeit anders nachzudenken. Aber natürlich wirst du das, denn Erlang ist einfach genial.

Diejenigen, die Erlang nicht verstehen, sind dazu verdammt, es schlecht umzusetzen.

Okay, das Original handelte von Lisp, aber ... es ist wahr!

    
Christian 27.11.2009 22:30
quelle
1
  

Für z.B. In einem DB müssen Sie auf denselben Datensatz zugreifen und diesen ändern

Aber das erledigt die DB. Als Benutzer der Datenbank führen Sie einfach Ihre Abfrage aus, und die Datenbank stellt sicher, dass sie isoliert ausgeführt wird.

Was die Leistung angeht, ist eines der wichtigsten Dinge bei der Eliminierung des Shared State, dass es neue Optimierungen ermöglicht. Der gemeinsame Status ist nicht besonders effizient. Sie erhalten Kerne, die über die gleichen Cache-Zeilen kämpfen, und Daten müssen in den Speicher geschrieben werden, wo sie sonst in einem Register oder im CPU-Cache verbleiben könnten.

Viele Compileroptimierungen beruhen auf der Abwesenheit von Nebeneffekten und dem gemeinsamen Status.

Man könnte sagen, dass eine strengere Sprache, die diese Dinge garantiert, mehr Optimierungen erfordert, um leistungsfähiger zu sein als etwas wie C, aber es macht auch diese Optimierungen viel einfacher für den Compiler zu implementieren.

Viele Probleme, die Parallelitätsproblemen ähneln, treten bei eingängigem Code auf. Moderne CPUs sind pipelineartig, führen Anweisungen in der falschen Reihenfolge aus und können 3-4 von ihnen pro Zyklus ausführen. Selbst in einem Singlethread-Programm ist es daher wichtig, dass der Compiler und die CPU in der Lage sind zu bestimmen, welche Befehle parallel verschachtelt und ausgeführt werden können.

    
jalf 27.11.2009 19:35
quelle
0
  1. Erlang bietet Supervisor- und gen_server-Callbacks für synchrone Aufrufe, so dass Sie darüber Bescheid wissen, wenn eine Nachricht nicht zugestellt wird: Entweder gibt der Aufruf gen_server ein Timeout zurück oder Ihr gesamter Knoten wird heruntergefahren, wenn der Supervisor ausgelöst wird .
  2. Normalerweise, wenn sich die Prozesse auf demselben Knoten befinden, optimieren Message-Passing-Sprachen das Kopieren von Daten, so dass es fast wie Shared Memory ist, außer wenn das Objekt später von beiden verwendet wird, was auch nicht mit Shared Memory möglich ist wie auch immer
  3. Es gibt einen Zustand, der von Prozessen gehalten wird, indem er sie in den rekursiven Tail-Calls an sich selbst weitergibt. Natürlich kann auch ein Zustand durch Nachrichten weitergegeben werden. Ich benutze keine mnesia viel, aber es ist eine transaktionale Datenbank, also, sobald Sie die Operation nach mnesia übergeben haben (und es zurückgekehrt ist), sind Sie ziemlich sicher, dass es durchgeht ..
  4. Deshalb ist es einfach, solche Anwendungen mit Hilfe von Ports oder Treibern in erlang einzubinden. Am einfachsten sind die Ports, es ist wie eine Unix-Pipe, obwohl ich denke, die Leistung ist nicht so toll ... und wie gesagt, Message-Passing endet in der Regel nur als Zeiger übergeben, wie der VM / Compiler die Speicherkopie optimieren .
glenda 30.11.2009 02:28
quelle
-1

Für die Korrektheit ist shared der Weg zu gehen und die Daten so normal wie möglich zu halten. Senden Sie zur Unmittelbarkeit Nachrichten, um auf Änderungen hinzuweisen, aber sichern Sie sie immer mit Polling. Nachrichten werden gelöscht, dupliziert, neu geordnet, verzögert - verlassen Sie sich nicht darauf.

Wenn die Geschwindigkeit das ist, worüber Sie sich Sorgen machen, tun Sie dies zunächst einmal und Stimmen Sie die Daylights raus . Dann, wenn Sie mehrere Kerne haben und wissen, wie Sie die Arbeit aufteilen, verwenden Sie Parallelität.

    
Mike Dunlavey 27.11.2009 19:46
quelle