Reactivecocoa: Atomic: SPINLOCK tidak aman di iOS

Dibuat pada 15 Des 2015  ·  20Komentar  ·  Sumber: ReactiveCocoa/ReactiveCocoa

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

Saya akan menahan diri untuk tidak membuat komentar apa pun (Saya hanya akan mengatakan ... jika itu ilegal di iOS, mengapa itu API publik ???)

Rupanya pthread mutex sekarang lebih cepat . Kita harus membuat patokan untuk membandingkan, dan mencoba mengonversi Atomic menjadi ini (juga RACCompoundDisposable dan RACSerialDisposable ?)

help wanted

Komentar yang paling membantu

Saya menemukan utas ini hari ini, dan melakukan penyelidikan tentang berbagai jenis sinkronisasi dan menjalankan tolok ukur pada simulator iOS dan perangkat nyata.
Hasilnya sangat menarik buat saya. Di iOS 10 kami memiliki penurunan kinerja dispatch_semaphore yang terlihat, yang mungkin mengubah perilakunya dengan menghormati prioritas utas.
Berikut adalah diagram ringkasan mekanisme sinkronisasi dasar yang tersedia di iOS. Semua pengujian dijalankan dengan konfigurasi rilis (Pengoptimalan Swift -O)

2016-06-29 17 58 39

Kode benchmark untuk SDK9
Kode benchmark untuk SDK10

Semua 20 komentar

Saya bahkan tidak yakin apa artinya "ilegal".

nope

Saya hanya ingin tahu, karena saya tidak ada sejak awal, tetapi mengapa OSSpinLock digunakan untuk jenis Atomic ?

Apakah NSLock digunakan dan kemudian terbukti terlalu lambat, lalu pthread_mutex_t diuji dan ternyata terlalu lambat juga? Sayangnya git tidak memiliki riwayat sebelum "pindahkan sumber…"

Spinlock bukanlah sesuatu yang saya pikirkan untuk digunakan dalam konteks non-kernel, non-device-driver, itulah sebabnya saya bertanya. Jika ada, saya akan mengatakan bahwa bug di sini adalah OSSpinLock digunakan sama sekali. : stuck_out_tongue:

Untuk menambahkan titik balik ke komentar saya di atas, ini bukan masalah besar seperti judulnya: https://twitter.com/Catfish_Man/status/676854531615883265

Bahkan di bawah kekurangan CPU, bagian kritis itu sangat kecil kemungkinannya baik-baik saja dalam situasi nyata.
- @Catfish_Man di Twitter

Adapun komentar di atas dari @kastiglione :

Saya bahkan tidak yakin apa artinya "ilegal".

Saya tidak memiliki jawabannya, tetapi saya akan menebak bahwa sesuatu di CPU ARM tidak memungkinkan spinlock primitif untuk menikmati banyak manfaat / jaminan / asumsi yang sama seperti pada CPU Intel. (Tapi sepertinya tidak semuanya, menurut https://twitter.com/Catfish_Man/status/676851988596809728)

Bagaimanapun, kemungkinan "tidak ada yang bisa dilihat di sini" dalam praktiknya, dan sebaliknya beberapa penyelidikan harus dilakukan untuk menggantikan dengan primitif yang lebih aman dan mengukur regresi kinerja apa pun, seperti yang disarankan @NachoSoto .

Saya pikir kita harus mengganti penggunaan OSSpinLock , tetapi saya pikir alasan saya / saya untuk menggunakannya valid mengingat dokumentasi yang tersedia untuk kita.

Ya, dan terima kasih atas komitmen sejarah yang relevan. Tidak yakin mengapa GitHub tidak melakukan git log --follow ketika riwayat diminta untuk file tertentu.

Bagaimanapun, saya akan menegaskan kembali bahwa "itu mungkin baik-baik saja." Menggunakan mutex "sekarang lebih cepat" mungkin merupakan tugas yang mudah, namun kurang begitu tanpa mengetahui bagaimana Anda membuat profil / mengujinya untuk memulai. Punya saran / petunjuk di sana?

Adapun cara ke depan jika / ketika kinerja menjadi perhatian, antrean bebas kunci perlu diselidiki. (Berikut adalah artikel yang cukup bagus untuk pembaca yang tidak terbiasa dengan konsep ini: http://www.linuxjournal.com/content/lock-free-multi-producer-multi-consumer-queue-ring-buffer?page=0,0). Saya membuat sesuatu yang mirip untuk perpustakaan audio internal beberapa waktu lalu, dan saya mungkin dapat menyesuaikannya untuk penggunaan umum seperti ini.

Menggunakan mutex "sekarang lebih cepat" mungkin merupakan tugas yang mudah, namun kurang begitu tanpa mengetahui bagaimana Anda membuat profil / mengujinya untuk memulai. Punya saran / petunjuk di sana?

Saya menjalankan GitHub Desktop di Instruments 'Time Profiler and Allocations, dan berfokus pada tumpukan RAC-heavy. Anda harus berbicara dengan @joshaber atau @mdiep untuk itu sekarang. :mengedipkan:

Baiklah senang mengetahuinya. Saya membayangkan hal-hal sisi Swift akan membutuhkan basis kode yang sama besar / dalam untuk diuji. Saya telah mengembangkan beberapa milik saya sendiri selama beberapa bulan terakhir 1 tetapi saya tidak tahu apakah saya mendorong RAC "cukup keras" untuk mendapatkan cukup sampel darinya. Banyak hal lain yang cenderung menggelembung di bagan Instrumen dengan aplikasi seperti milik saya. :tersenyum:

1 Pasang! http://capoapp.com , dengan http://capoapp.com/neptune menjadi komponen RAC4 terbaru yang dirancang sepenuhnya.

Saya menulis entri blog hari ini yang menjelaskan lebih detail tentang mengapa spinlock "ilegal" di iOS: http://engineering.postmates.com/Spinlocks-Considered-Harmful-On-iOS/

Saya menghentikan Atomic beberapa saat yang lalu dan memindahkannya ke pthread_mutex_lock. Menurut semua akun, ini adalah kunci terbaik yang pernah ada - tidak ada pengiriman dinamis seperti NSLock, kunci instan jika tidak dianggap seperti spinlock, tidak membuang energi tidak seperti kunci putar.

Jangan ragu untuk menyalin dan menempelkan sumber dari repo saya atau melakukan apa pun yang Anda suka dengannya.

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

@kballard itu penjelasan yang bagus, terima kasih!

Saya tidak memiliki pendapat yang kuat tentang ini karena saya bukan ahli dalam masalah ini. Saya akan tunduk kepada orang lain pada keputusan untuk mengubah (atau tidak mengubah) jenis kunci apa yang kami gunakan, meskipun saya akan dengan senang hati mengubahnya sendiri!

Tolok ukur seperti itu sama sekali tidak berguna tanpa sumber. Terlebih lagi, Anda hanya menampilkan satu waktu untuk setiap konstruksi, tanpa mendokumentasikan apa yang sebenarnya diwakili oleh waktu itu. Berbagai konstruksi akan berperilaku berbeda tergantung pada apakah mereka sedang diperdebatkan, prioritas utas yang bersaing di kunci, dll. @synchronized juga binatang yang aneh, kinerjanya akan sangat bergantung pada pola akses , seperti berapa banyak @synchronized blok yang dimasukkan / keluar pada saat yang sama, apakah Anda mengunci objek yang sama berulang kali atau mengunci objek baru, dll.

NB: dispatch_semaphore tidak menyumbangkan prioritas , yang merupakan potensi jebakan lainnya.

@jspahrsummers @kballard Saya memiliki implementasi menggunakan atom CAS. Jika ada minat saya dengan senang hati mengirimkan PR.

edit: Melihat penggunaan Atomic Saya rasa implementasi saya tidak akan berguna. Jika Anda dapat melakukan pembaruan idempoten CAS memungkinkan Anda melakukan semacam transaksi optimis dalam memori yang bisa menjadi hebat tetapi itu akan membutuhkan sedikit refactoring (meskipun itu bekerja sangat baik jika semuanya adalah CoW yang tidak dapat diubah, maka Anda benar-benar dapat memperlakukan mutasi sebagai transaksi dalam memori).

Saya menemukan utas ini hari ini, dan melakukan penyelidikan tentang berbagai jenis sinkronisasi dan menjalankan tolok ukur pada simulator iOS dan perangkat nyata.
Hasilnya sangat menarik buat saya. Di iOS 10 kami memiliki penurunan kinerja dispatch_semaphore yang terlihat, yang mungkin mengubah perilakunya dengan menghormati prioritas utas.
Berikut adalah diagram ringkasan mekanisme sinkronisasi dasar yang tersedia di iOS. Semua pengujian dijalankan dengan konfigurasi rilis (Pengoptimalan Swift -O)

2016-06-29 17 58 39

Kode benchmark untuk SDK9
Kode benchmark untuk SDK10

Nomor Anda terlihat sangat mencurigakan bagi saya. Berapa kali Anda menjalankan pengujian?

Sebagai perbandingan, saya menjalankan benchmark saya sendiri ( sumber ) pada OS X 10.11.5 menggunakan harness benchmark hacky yang saya tulis beberapa waktu lalu. Saya menjalankan seluruh tolok ukur 10 kali, menjatuhkan 2 angka terbawah dan teratas dari setiap tes (untuk menyingkirkan pencilan), dan angka lainnya menghasilkan kisaran berikut:

tidak ada sinkronisasi: 22-41ns
spinlock: 24ns
semaphore: 29ns
NSLock: 45-71ns
mutex: 40-64ns
disinkronkan: 75-122ns
antrian: 505-554ns

Dari sini Anda dapat melihat bahwa spinlock sejauh ini adalah yang termurah, diikuti oleh semaphore, lalu mutex, lalu NSLock hanya sedikit di belakang mutex (karena pada dasarnya mutex + objc_msgSend), kemudian disinkronkan hampir dua kali lebih mahal, dan akhirnya antrian menjadi sangat luar biasa mahal, jauh lebih dari yang saya harapkan.

@kballard seperti yang Anda lihat, tolok ukur saya cukup sederhana, tetapi menggunakan mekanisme xctest default untuk mengukur waktu eksekusi. Angka adalah waktu berjalan rata-rata untuk setiap pengujian, bukan untuk setiap sinkronisasi. Secara umum, hasil Anda dan saya berhubungan dengan antrean pengecualian, yang tidak terlalu buruk, seperti yang biasa kita pikirkan

alasan

Apakah halaman ini membantu?
0 / 5 - 0 peringkat