Reactivecocoa: Atomic: SPINLOCK ist unter iOS nicht sicher

Erstellt am 15. Dez. 2015  ·  20Kommentare  ·  Quelle: ReactiveCocoa/ReactiveCocoa

https://twitter.com/steipete/status/676851647042203648

Ich werde keine Kommentare abgeben (ich sage nur ... wenn es unter iOS illegal ist, warum ist es eine öffentliche API ???)

Anscheinend sind pthread Mutexe jetzt schneller . Wir sollten einen Vergleichsmaßstab erstellen und versuchen, Atomic in diesen umzuwandeln (auch RACCompoundDisposable und RACSerialDisposable ?).

help wanted

Hilfreichster Kommentar

Ich habe diesen Thread heute herausgefunden, verschiedene Arten der Synchronisation untersucht und einen Benchmark für den iOS-Simulator und reale Geräte durchgeführt.
Die Ergebnisse sind für mich sehr interessant. In iOS 10 haben wir einen sichtbaren Leistungsabfall von dispatch_semaphore, der wahrscheinlich sein Verhalten unter Berücksichtigung der Thread-Priorität ändert.
Hier ist das zusammenfassende Diagramm der grundlegenden Synchronisationsmechanismen, die in iOS verfügbar sind. Alle Tests werden mit Release-Konfiguration ausgeführt (Swift-Optimierung -O).

2016-06-29 17 58 39

Benchmark-Code für SDK9
Benchmark-Code für SDK10

Alle 20 Kommentare

Ich bin mir nicht mal sicher, was "illegal" bedeutet.

nope

Ich bin nur neugierig, da ich von Anfang an nicht da war, aber warum wurde OSSpinLock für den Typ Atomic verwendet?

Wurde NSLock verwendet und dann als zu langsam angezeigt, dann wurde pthread_mutex_t getestet und auch als zu langsam befunden? Leider hat Git keine Geschichte vor "Quellen verschieben ..."

Spinlocks sind nichts, was ich in einem Nicht-Kernel-, Nicht-Gerätetreiber-Kontext verwenden würde, weshalb ich frage. Wenn überhaupt, würde ich sagen, dass der Fehler hier darin besteht, dass OSSpinLock überhaupt verwendet wird. : stick_out_tongue:

Um meinem obigen Kommentar einen Kontrapunkt hinzuzufügen, ist dies keine so große Sache, wie der Titel vermuten lässt: https://twitter.com/Catfish_Man/status/676854531615883265

Selbst unter CPU-Mangel ist dieser kritische Bereich so klein, dass er in realen Situationen wahrscheinlich in Ordnung ist.
- @Catfish_Man auf Twitter

Wie für den Kommentar oben von @kastiglione :

Ich bin mir nicht mal sicher, was "illegal" bedeutet.

Ich habe keine Antwort, aber ich würde vermuten, dass etwas in der ARM-CPU dem Spinlock-Grundelement nicht erlaubt, viele der gleichen Vorteile / Garantien / Annahmen zu genießen wie bei Intel-CPUs. (Aber wahrscheinlich nicht alle, laut https://twitter.com/Catfish_Man/status/676851988596809728)

Wie auch immer, in der Praxis gibt es wahrscheinlich "hier nichts zu sehen", und stattdessen sollten einige Untersuchungen durchgeführt werden, um das sicherere Grundelement zu ersetzen und Leistungsrückgänge zu messen, wie

Ich denke, wir sollten unsere Verwendung von OSSpinLock ersetzen, aber ich denke, unsere / meine Argumentation für die Verwendung war angesichts der uns zur Verfügung stehenden Dokumentation gültig.

Ja, und danke für die relevanten Commits in der Geschichte. Ich bin mir nicht sicher, warum GitHub kein git log --follow wenn der Verlauf für eine bestimmte Datei angefordert wird.

Auf jeden Fall werde ich wiederholen, dass "es wahrscheinlich in Ordnung ist". Die Verwendung eines "jetzt schnelleren" Mutex ist wahrscheinlich eine unkomplizierte Aufgabe, jedoch weniger, ohne zu wissen, wie Sie sie zunächst profiliert / getestet haben. Haben Sie dort Vorschläge / Hinweise?

Für einen Weg nach vorne, wenn / wenn die Leistung zu einem Problem wird, sollten Warteschlangen ohne Sperren untersucht werden. (Hier ist ein ziemlich guter Artikel für Leser, die mit dem Konzept nicht vertraut sind: http://www.linuxjournal.com/content/lock-free-multi-producer-multi-consumer-queue-ring-buffer?page=0,0). Ich habe vor einiger Zeit etwas Ähnliches für eine interne Audiobibliothek erstellt und kann es möglicherweise für den allgemeinen Gebrauch wie diesen anpassen.

Die Verwendung eines "jetzt schnelleren" Mutex ist wahrscheinlich eine unkomplizierte Aufgabe, jedoch weniger, ohne zu wissen, wie Sie sie zunächst profiliert / getestet haben. Haben Sie dort Vorschläge / Hinweise?

Ich habe GitHub Desktop in Instruments 'Time Profiler und Allocations ausgeführt und mich auf RAC-schwere Stacks konzentriert. Dafür musst du jetzt mit @mdiep sprechen. :zwinkern:

Ok, gut zu wissen. Ich kann mir vorstellen, dass das Swift-Side-Zeug eine ähnlich große / tiefe Codebasis zum Testen benötigt. Ich habe in den letzten Monaten einige meiner eigenen gewachsen 1, aber ich weiß nicht, ob ich den RAC "hart genug" drücke, um genug Proben herauszuholen. Viele andere Dinge sprudeln mit Apps wie meinen in den Instrumentendiagrammen. :Lächeln:

1 Stecker! http://capoapp.com , wobei http://capoapp.com/neptune die neueste, vollständig mit RAC4 entwickelte Komponente ist.

Ich habe heute einen Blog-Beitrag geschrieben, in dem ausführlicher erläutert wird, warum Spinlocks unter iOS "illegal" sind: http://engineering.postmates.com/Spinlocks-Considered-Harmful-On-iOS/

Ich habe Atomic vor einiger Zeit abgebrochen und auf pthread_mutex_lock migriert. In jedem Fall ist es die beste Sperre, die es gibt - kein dynamischer Versand wie NSLock, sofortige Sperre, wenn nicht wie Spinlock, keine Energieverschwendung im Gegensatz zu Spin Lock.

Fühlen Sie sich frei, die Quelle aus meinem Repo zu kopieren und einzufügen oder damit zu tun, was Sie wollen.

https://github.com/Adlai-Holler/Atomic
https://github.com/Adlai-Holler/Atomic/blob/master/Atomic/Atomic.swift

@kballard das ist eine tolle Erklärung, danke!

Ich habe keine starke Meinung dazu, da ich kein Experte in dieser Angelegenheit bin. Ich werde anderen die Entscheidung aufschieben, zu ändern (oder nicht zu ändern), welche Art von Schloss wir verwenden, obwohl ich die Änderung gerne selbst vornehmen würde!

Ein solcher Benchmark ist ohne Quelle völlig nutzlos. Darüber hinaus zeigen Sie für jedes Konstrukt nur eine einzige Zeit an, ohne zu dokumentieren, was diese Zeit tatsächlich darstellt. Die verschiedenen Konstrukte verhalten sich unterschiedlich, je nachdem, ob sie in Konflikt stehen, welche Prioritäten die Threads haben, die um die Sperre kämpfen usw. @synchronized ist ebenfalls ein merkwürdiges Tier, dessen Leistung stark von den Zugriffsmustern abhängt B. wie viele @synchronized Blöcke gleichzeitig eingegeben / verlassen werden, ob Sie dasselbe Objekt wiederholt sperren oder neue Objekte sperren usw.

NB: dispatch_semaphore spendet keine Priorität , was eine weitere potenzielle Gefahr darstellt.

@jspahrsummers @kballard Ich habe eine Implementierung mit atomarem CAS. Bei Interesse reiche ich gerne eine PR ein.

edit: Wenn ich mir die Verwendung von Atomic anschaue, denke ich nicht, dass meine Implementierung nützlich sein wird. Wenn Sie idempotente Updates durchführen können, können Sie mit CAS eine Art optimistischer Transaktionen im Speicher durchführen, die großartig sein können, aber einiges an Refactoring erfordern würden (obwohl es sehr gut funktioniert, wenn alles eine unveränderliche CoW ist, können Sie Mutation wirklich als behandeln eine In-Memory-Transaktion).

Ich habe diesen Thread heute herausgefunden, verschiedene Arten der Synchronisation untersucht und einen Benchmark für den iOS-Simulator und reale Geräte durchgeführt.
Die Ergebnisse sind für mich sehr interessant. In iOS 10 haben wir einen sichtbaren Leistungsabfall von dispatch_semaphore, der wahrscheinlich sein Verhalten unter Berücksichtigung der Thread-Priorität ändert.
Hier ist das zusammenfassende Diagramm der grundlegenden Synchronisationsmechanismen, die in iOS verfügbar sind. Alle Tests werden mit Release-Konfiguration ausgeführt (Swift-Optimierung -O).

2016-06-29 17 58 39

Benchmark-Code für SDK9
Benchmark-Code für SDK10

Ihre Zahlen sehen für mich sehr verdächtig aus. Wie oft haben Sie die Tests durchgeführt?

Zum Vergleich habe ich meinen eigenen Benchmark ( Quelle ) unter OS X 10.11.5 mit einem Hacky-Benchmark-Gurt ausgeführt, den ich vor einiger Zeit geschrieben habe. Ich habe den gesamten Benchmark 10 Mal ausgeführt, die unteren und oberen 2 Zahlen aus jedem Test entfernt (um Ausreißer loszuwerden), und der Rest der Zahlen ergab die folgenden Bereiche:

keine Synchronisation: 22-41ns
Spinlock: 24ns
Semaphor: 29ns
NSLock: 45-71ns
Mutex: 40-64 ns
synchronisiert: 75-122ns
Warteschlange: 505-554ns

Daraus können Sie ersehen, dass Spinlock bei weitem am billigsten ist, gefolgt von Semaphor, dann Mutex, dann NSLock nur geringfügig hinter Mutex (da es sich im Grunde genommen um Mutex + objc_msgSend handelt). Dann ist die Synchronisierung fast doppelt so teuer, und schließlich sind die Warteschlangen extrem teuer, viel teurer als ich erwartet hatte.

@kballard Wie Sie sehen können, ist mein Benchmark recht einfach, verwendet jedoch den Standardmechanismus xctest zum Messen der Ausführungszeit. Die Zahlen sind die durchschnittliche Laufzeit für jeden Test, nicht für jede Synchronisierung. Im Allgemeinen korrelieren Ihre und meine Ergebnisse mit Ausnahme von Warteschlangen, die nicht so schlecht sind, wie wir früher dachten

Gründe dafür

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen