2017-01-29 31 views
1

In meiner Anwendung habe ich eine große verschachtelte Karte von unveränderlichen Zustand, die ich sehr oft mit Operationen wie get-in abfragen.Beschleunigen Transienten die Lesevorgänge?

Wenn ich viele Leseoperationen an einer solchen Struktur durchführe, kann ich daraus Nutzen ziehen, wenn ich sie in einen Transient umwandeln würde? Oder beschleunigen Transienten nur die Aktualisierungsvorgänge?

Antwort

1

Für integrierte transientenaktivierte Clojure-Datenstrukturen (und alle Datenstrukturen, die mit der gleichen allgemeinen Strategie implementiert wurden) gibt es keinen lesebezogenen Vorteil für die Verwendung von Transienten. In der Tat, Transienten müssen ein wenig mehr Arbeit für Nachschlagewerke - eine einzige .get auf einem AtomicReference und eine Verzweigung auf das Ergebnis. Normalerweise ist dies kaum messbar, daher ist es kein Problem, Transienten zu verwenden, bei denen das Schlüsselwertversprechen (schnellere Update-Ketten) relevant ist, aber auf jeden Fall bedeutet das, dass sie Lookups nicht schneller machen.

Dies liegt daran, Transienten fast die gleichen internen Strukturen wie ihre persistent Pendants verwenden (in die Tat nach einem persistent! Aufruf, die interne Baum der transienten wird direkt in der neu geschaffenen persistenten Datenstruktur verwendet wird), so dass ihre Lookup-Logik ist sehr fast gleich, aber in Bezug auf den allgemeinen API-Vertrag der Transienten müssen alle versuchten Lookups nach einem persistent!-Aufruf für einen bestimmten Transienten zu einem IllegalAccessError führen. Dies kostet Transienten eine kleine Menge zusätzlichen Aufwands jedes Mal, wenn man versucht, nachzuschlagen.


Es gibt einige kleinere Unterschiede: z.B. Transiente Vektoren verwenden immer ein 32-Elemente-Array als Tail (gepaart mit einem Feld, das den aktuellen "End-Index" verfolgt), während persistente Vektoren ein Array von so vielen Elementen verwenden, wie der Tail tatsächlich hält; das bedeutet, dass das Wachsen eines Tails mit einer In-Place-Mutation die meiste Zeit erreicht werden kann (in einer Kette von conj! s muss nur 1 von 32 ein neues Tail-Array zuweisen), und es verursacht keine Probleme für die persistente Version Wenn Sie persistent! anrufen, wird der Schwanz wieder getrimmt. Dies beeinflusst die aktuelle Diskussion jedoch nicht wirklich.

In der Tat werden die gleichen kleinen Kosten für Schreibvorgänge auch bezahlt, aber dort überwiegen die Vorteile oft in der Lage sein, die Datenstruktur an Ort und Stelle statt neue Knoten zu verteilen leicht überwiegen.

0

Dokumentation über instationäre Strukturen besagt, dass Sie O (1) Leistung für die Erstellung der Struktur selbst erhalten (daher Aufruf transient). Aktualisierungsvorgänge sind schneller als normale (wie assoc), aber ich würde erwarten, dass das Lesen das gleiche ist. Sie können eine ausführlichere Erklärung in der Clojure reference finden.

3

Transienten wurden entwickelt, um schreibt durch Batch-Updates zu beschleunigen. Ihr Zweck besteht nicht darin, Lesevorgänge zu optimieren, und wenn dies Ihr Ziel ist, würde ich sie nicht verwenden (die Verwendung einer effizienteren Datenstruktur für die Suche ist wahrscheinlich eine bessere Antwort).

Liest auf einer transienten Datenstruktur kann entweder langsamer oder schneller sein, da sie sowohl die Datenstruktur als auch die In-Prozess-Charge überprüfen müssen. Wenn sich der Wert zufällig in der gerade hinzugefügten Charge befindet, lautet der Wert möglicherweise schneller. Wenn sie sich in der größeren Datenstruktur befinden, könnten sie langsamer sein.

Verwandte Themen