Reactivecocoa: Atomic: SPINLOCK небезопасен в iOS

Созданный на 15 дек. 2015  ·  20Комментарии  ·  Источник: ReactiveCocoa/ReactiveCocoa

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

Я воздержусь от комментариев (просто скажу ... если это незаконно на iOS, почему это публичный API ???)

Судя по всему, мьютексы pthread теперь быстрее . Мы должны создать тест для сравнения и попытаться преобразовать в него Atomic (также RACCompoundDisposable и RACSerialDisposable ?)

help wanted

Самый полезный комментарий

Сегодня я узнал об этой теме, провел исследование различных типов синхронизации и выполнил тест на симуляторе iOS и реальных устройствах.
Результаты для меня очень интересны. В iOS 10 мы видим видимое снижение производительности dispatch_semaphore, которое, вероятно, изменило его поведение с учетом приоритета потока.
Вот сводная диаграмма основных механизмов синхронизации, доступных в iOS. Все тесты выполняются с конфигурацией выпуска (оптимизация Swift -O)

2016-06-29 17 58 39

Код теста для SDK9
Код теста для SDK10

Все 20 Комментарий

Я даже не уверен, что означает «незаконный».

nope

Мне просто любопытно, так как меня не было с самого начала, но почему для начала использовался OSSpinLock для типа Atomic ?

Было ли использовано NSLock а затем показано, что он слишком медленный, тогда pthread_mutex_t был протестирован и также оказался слишком медленным? К сожалению, у git нет истории до «переместить источники…»

Я бы не подумал использовать спин-блокировки в контексте, отличном от ядра и драйвера устройства, вот почему я спрашиваю. Во всяком случае, я бы сказал, что ошибка здесь в том, что OSSpinLock вообще используется. : stuck_out_tongue:

Чтобы добавить контраргумент к моему комментарию выше, это не так уж важно, как может показаться в названии: https://twitter.com/Catfish_Man/status/676854531615883265

Даже при нехватке ЦП эта критическая секция настолько крошечная, что в реальных ситуациях вполне нормально.
- @Catfish_Man в Твиттере

Что касается комментария выше от @kastiglione :

Я даже не уверен, что означает «незаконный».

У меня нет ответа, но я предполагаю, что что-то в ЦП ARM не позволяет примитиву спин-блокировки пользоваться многими из тех же преимуществ / гарантий / предположений, что и в ЦП Intel. (Но, вероятно, не все из них, согласно https://twitter.com/Catfish_Man/status/676851988596809728)

В любом случае, на практике, скорее всего, «здесь не на что смотреть», и вместо этого следует провести некоторое исследование, чтобы заменить его более безопасным примитивом и измерить любое снижение производительности, как предлагает

Я действительно думаю, что мы должны заменить наши способы использования OSSpinLock , но я думаю, что наши / мои доводы в пользу их использования были обоснованными, учитывая доступную нам документацию.

Да, и спасибо за соответствующие исторические коммиты. Не уверен, почему GitHub не делает git log --follow когда история запрашивается для данного файла.

Во всяком случае, повторю, что «наверное, нормально». Использование «теперь более быстрого» мьютекса, вероятно, является простой задачей, однако это не так, если вы не знаете, как вы их профилировали / тестировали для начала. Есть там какие-нибудь предложения / подсказки?

Что касается дальнейших действий, если / когда производительность станет проблемой, стоит изучить очереди без блокировки. (Вот довольно хорошая статья для читателей, незнакомых с этой концепцией: http://www.linuxjournal.com/content/lock-free-multi-producer-multi-consumer-queue-ring-buffer?page=0,0). Некоторое время назад я создал нечто подобное для внутренней аудиотектории, и, возможно, я смогу адаптировать ее для такого общего использования.

Использование «теперь более быстрого» мьютекса, вероятно, является простой задачей, однако это не так, если вы не знаете, как вы их профилировали / тестировали для начала. Есть там какие-нибудь предложения / подсказки?

Я запускал GitHub Desktop в инструментах Time Profiler and Allocations и сосредоточился на стеках с большим количеством RAC. Для этого вам нужно поговорить с @joshaber или @mdiep . :подмигивание:

Хорошо, хорошо знать. Я полагаю, что для работы со Swift потребуется такая же большая / глубокая база кода для тестирования. Я вырастил несколько своих собственных за последние несколько месяцев 1, но я не знаю, достаточно ли я нажимаю на RAC, чтобы получить от него достаточно сэмплов. Множество других вещей, как правило, всплывают на диаграммах инструментов с такими приложениями, как мое. :улыбка:

1 штекер! http://capoapp.com , причем http://capoapp.com/neptune является самым последним, полностью разработанным с использованием RAC4 компонентом.

Сегодня я написал сообщение в блоге, в котором более подробно рассказывается о том, почему спин-блокировки «незаконны» на iOS: http://engineering.postmates.com/Spinlocks-Considered-Harmful-On-iOS/

Некоторое время назад я отключил Atomic и перенес его на pthread_mutex_lock. По общему мнению, это лучшая блокировка из всех существующих - нет динамической диспетчеризации, такой как NSLock, мгновенная блокировка, если не используется, как спин-блокировка, не тратит энергию в отличие от спин-блокировки.

Не стесняйтесь копировать и вставлять исходный код из моего репо или делать с ним все, что вам нравится.

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

@kballard , это отличное объяснение, спасибо!

У меня нет твердого мнения по этому поводу, так как я не эксперт в этом вопросе. Я предоставлю решение изменить (или не менять) тип блокировки, который мы используем, другим, хотя я был бы рад внести изменения сам!

Такой тест без исходного кода совершенно бесполезен. Более того, вы показываете только одно время для каждой конструкции, не документируя, что это время на самом деле представляет. Различные конструкции будут вести себя по-разному в зависимости от того, находятся ли они в состоянии конкуренции, приоритетов потоков, которые борются за блокировку, и т. Д. @synchronized также любопытный зверь, его производительность будет сильно зависеть от шаблонов доступа , например, сколько блоков @synchronized вводится / выходит одновременно, блокируете ли вы один и тот же объект повторно или блокируете новые объекты и т. д.

NB: dispatch_semaphore не передает приоритет , что является еще одной потенциальной ловушкой.

@jspahrsummers @kballard У меня есть реализация, использующая атомарный CAS. Если есть интерес, я с радостью предоставлю PR.

edit: глядя на использование Atomic я не думаю, что моя реализация будет полезной. Если вы можете выполнять идемпотентные обновления, CAS позволяет вам выполнять своего рода оптимистичные транзакции в памяти, что может быть отличным, но для этого потребуется довольно много рефакторинга (хотя он работает очень хорошо, если все является неизменным CoW, тогда вы действительно можете рассматривать мутацию как транзакция в памяти).

Сегодня я узнал об этой теме, провел исследование различных типов синхронизации и выполнил тест на симуляторе iOS и реальных устройствах.
Результаты для меня очень интересны. В iOS 10 мы видим видимое снижение производительности dispatch_semaphore, которое, вероятно, изменило его поведение с учетом приоритета потока.
Вот сводная диаграмма основных механизмов синхронизации, доступных в iOS. Все тесты выполняются с конфигурацией выпуска (оптимизация Swift -O)

2016-06-29 17 58 39

Код теста для SDK9
Код теста для SDK10

Ваши цифры мне кажутся очень подозрительными. Сколько раз вы запускали тесты?

Для сравнения я запустил свой собственный тест ( исходный код ) на OS X 10.11.5, используя хакерскую программу тестирования, которую написал недавно. Я провел весь тест 10 раз, отбросил два нижних и верхних числа из каждого теста (чтобы избавиться от выбросов), а остальные числа дали следующие диапазоны:

без синхронизации: 22-41 нс
спин-блокировка: 24 нс
семафор: 29 нс
NSLock: 45-71 нс
мьютекс: 40-64 нс
синхронизировано: 75-122нс
очередь: 505-554нс

Из этого вы можете видеть, что спин-блокировка, безусловно, самая дешевая, за ней следует семафор, затем мьютекс, затем NSLock чуть отстает от мьютекса (так как это в основном mutex + objc_msgSend), затем синхронизация почти вдвое дороже, и, наконец, очереди становятся чрезвычайно дорого, намного дороже, чем я ожидал.

@kballard, как видите, мой тест довольно прост, но он использует механизм xctest по умолчанию для измерения времени выполнения. Числа - это среднее время выполнения каждого теста, а не каждой синхронизации. В общем, ваши и мои результаты коррелируют с исключениями очередей, что не так уж и плохо, как мы привыкли думать.

причины

Была ли эта страница полезной?
0 / 5 - 0 рейтинги

Смежные вопросы

toddbluhm picture toddbluhm  ·  5Комментарии

BrettThePark picture BrettThePark  ·  4Комментарии

RuiAAPeres picture RuiAAPeres  ·  3Комментарии

mdiep picture mdiep  ·  5Комментарии

eimantas picture eimantas  ·  6Комментарии