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:
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?
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.
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.
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.
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: -)
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?
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
Ein paar Kommentare zu dem Missverständnis, das Sie von Erlang haben:
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!
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.
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.
Tags und Links distributed-computing concurrency erlang transactions