2012-04-11 6 views
7

Ich überlege, mit einem TVar einen Zustand in einer Webanwendung zu speichern (die beim Neustart neu erstellt werden kann). Die Wettbewerbsaspekte von TVar betreffen mich jedoch. Es scheint, dass eine häufige kurzlaufende Transaktion längere Transaktionen aushungern kann, indem sie sie kontinuierlich unterbricht. Da länger laufende Transaktionen immer wieder neu gestartet werden, würde dies die Belastung der CPU erhöhen und dazu neigen, die Länge dieser Transaktionen weiter zu erhöhen. Irgendwann könnte dies dazu führen, dass der Server nicht mehr reagiert.Haskell: TVar: Verhindern des Hungers

diese Anbetracht, ich habe folgende Fragen:

(1) Kann TVar (oder einen anderen Datentyp) verwenden Schlösser, nicht gleichzeitig Versuche/Wiederholungen.

(2) Kann TVar (oder ein anderer Datentyp) einen anderen Contention-Mechanismus haben, zB "Lassen Sie Transaktionen eine Sekunde laufen, bevor Sie eine andere Transaktion ausführen", oder zumindest einige Garantien, dass Transaktionen schließlich abgeschlossen werden das verhindert starvation für länger laufende Transaktionen).

+2

Hinweis 'retry' startet die Transaktion nicht sofort neu; Transaktionen werden nur wiederholt, wenn die von ihnen verwendeten TVar's geändert werden. – ehird

+0

@ehird: Versuchen Transaktionen nicht automatisch sofort, wenn eine andere Transaktion in die TVar schreibt, die sie zuvor gelesen haben (auch ohne einen Aufruf von 'retry')? – Clinton

+0

@Clinton: Ja, sie versuchen es erneut, aber erst, nachdem das Laufzeitsystem eine Möglichkeit für ein anderes Ergebnis der Transaktion entdeckt hat. I.e. es wartet bis einer der TVars gelesen hat bevor sich der Retry geändert hat. Das macht beschäftigt Warten auf ein Push-Benachrichtigungsschema. – jmg

Antwort

3

Dies ist nur ein Problem, wenn Sie viele günstige Transaktionen haben, die Daten aktualisieren und ein paar teure, die es lesen. Analytics in einem Live-aktualisierten Datensatz.

Wenn Sie sich darüber Sorgen machen, sollten Sie eine Flagge TVar verwenden. Setzen Sie es auf "false" und prüfen Sie, ob es zu Beginn jeder billigen Transaktion falsch ist und andernfalls retry aufruft. Setzen Sie es dann einfach auf "wahr", bevor Sie Ihre lang laufende Transaktion eingeben, und setzen Sie sie beim Beenden auf "false". Alternativ können Sie Ihren Zustand hinter einer TMVar schützen.Ihre langwierige Berechnung nimmt die tmvar atomar, tut, wie es sich anfühlt und gibt es dann zurück. Die anderen Transaktionen finden vollständig innerhalb einer einzigen tatsächlichen STM-Transaktion statt.

Denken Sie auch daran, eine lange laufende STM-Transaktion ist eine Art trickreiches Biest. Wegen der Faulheit können Sie einen teuren Wert in ein var billig setzen. Sie können auch sehr schnell einen "Schnappschuss" von Daten aus einer ganzen Reihe von Vars lesen. Um eine wirklich lange laufende Transaktion zu haben, müssen Sie aus einer ganzen Reihe von Vars lesen, dann berechnen Sie basierend auf dem, was Sie gelesen haben, , was vars Sie werden neue Werte schreiben (oder Werte lesen von), und das Die Berechnung selbst muss teuer sein. Wahrscheinlich bist du nicht einmal in diesem Szenario!

5

Ich glaube nicht, dass es eine Möglichkeit gibt, die Freiheit beim Verhungern zu garantieren, es sei denn, Sie ändern den Laufzeitcode des STM-Systems selbst. Meiner Meinung nach bringt das Einbringen von Sperren, um Konflikte zwischen TVars zu vermeiden, den Zweck von STM an erster Stelle zu besiegen, da der ganze Sinn der Verwendung von STM darin besteht, den klassischen fehleranfälligen lockbasierten Ansatz zur gleichzeitigen Programmierung loszuwerden.

Sicher, Hunger kann zu erheblichen Leistungseinbußen führen, aber nur unter der Annahme, dass so große Transaktionen tatsächlich erforderlich sind. Ein Designprinzip, das ich im Auge behalten möchte, ist die Verwendung von TVars bei einem niedrigen Granularitätsgrad. Anstatt beispielsweise eine ganze Data.Map in eine TVar zu setzen, die bei jeder Aktualisierung eines Eintrags zu Konflikten führen kann, können Sie eine STM-freundlichere Datenstruktur wie z. B. Skiplists [1] verwenden, .

[1] http://hackage.haskell.org/package/tskiplist

+0

Ich verstehe nicht wirklich, wie STM weniger fehleranfällig ist. Führen Sie keine kurzlaufenden Transaktionen durch, um effektiv eine Sperre einzurichten, die niemals für länger laufende Transaktionen freigegeben wird? Ist das nicht fehleranfälliger als unter einem lockbasierten System, zumindest wird irgendwann die länger laufende Transaktion die Sperre übernehmen und abschließen? STM scheint den Programmierer zu zwingen, sicherzustellen, dass ihre am längsten laufende Transaktion weniger Zeit benötigt als die längste Lücke zwischen den Transaktionen. Vielleicht vermisse ich hier aber etwas. – Clinton

+0

Wenn ich unter einem Sperrsystem richtig verstehe, wenn eine Transaktion gerade läuft, muss eine andere Transaktion warten. Wenn unter STM eine Transaktion gerade ausgeführt wird, beginnt sie stattdessen zu arbeiten, sie wird jedoch irgendwann trotzdem verschrotten. In beiden Fällen wird keine nützliche Arbeit geleistet, daher kann ich nicht sehen, wie STM weniger "sperrt" als gewöhnliche Sperren. Aber vielleicht verpasse ich noch etwas. – Clinton

+0

@ Clinton: Das primäre Problem mit Sperren ist nicht Verhungern, sondern zu wenigen Sperren oder Deadlocks. Probleme mit Sperren sind daher in der Regel Korrektheit, nicht Leistungsprobleme. Während Probleme mit STM möglicherweise Leistungsprobleme sind. Sie sollten auch die Möglichkeiten der Faulheit betrachten. Faulheit macht es möglich, das Ergebnis einer lang laufenden reinen Berechnung in einer kurzen laufenden Transaktion in eine TVar zu schreiben. – jmg

0

Dies als Kommentar zu einem von Clinton Kommentaren zu Peters Antwort geschrieben wurde. Aber es wurde zu lange.

Betrachten Sie, Sie haben zwei Bankkonten: A und B. Jedes ist durch sein eigenes Schloss geschützt. Jetzt haben Sie zwei Transaktionen, die ersten Geldüberweisungen von A nach B, und die zweite von B nach A. Jeder nimmt zuerst die Sperre des Quellkontos und dann des Zielkontos, überweist das Geld und gibt die Sperren frei. Wenn Ihr Pech nicht besteht, werden die beiden Transaktionen in eine tote Sperre geraten, und mit diesen beiden Konten wird nie etwas geschehen. Wenn Sie das in STM tun, werden sie nacheinander ausgeführt. Wenn Sie unendlich viele der ersten Art haben, könnten sie die zweite Transaktion verhungern. Aber du hast immer noch viel geschafft. Während der Verriegelung passiert nie etwas.

STM garantiert, dass es bei TVars keine Datenrennen gibt! Überhaupt keine. Mit der Sperrung können Sie nach sorgfältiger Prüfung Ihres Codes zu diesem Schluss kommen. Und jede Zeile, die Sie hinzufügen, könnte Ihre Schlussfolgerung vollständig ungültig machen.

Verwandte Themen