Синхронизировать доступ на чтение / запись к переменной экземпляра для высокой производительности в iOS?
Какие'лучший способ / способ наименьшего времени ожидания синхронизировать доступ на чтение / запись к переменной экземпляра в target-c для iOS?
Переменная читается и записывается очень часто (пустьскажем 1000 раз в секунду прочитал и написал). Не важно, чтобы изменения вступили в силу немедленно. Даже не важно, что чтения получают согласованные данные друг с другом, но записи рано или поздно должны отражаться в данных, полученных при чтении. Есть ли какая-то структура данных, которая позволяет это?
Я думал об этом:
Создайте две переменные вместо одной; позволять'зовут ихv[0]
а также .v[1]
Для каждогоv[i]
создать параллельную очередь отправки для созданиячитатели-писатель-замок механизм вокруг него. Позволять'позвони им.q[i]
Теперь только для записиv[0]
записывается, придерживаясь механизма блокировки с.q[0]
На операции чтения, сначалаv[1]
читается и только с определенной вероятностью, например 1%, операция чтения выглядитv[0]
и обновленияv[1]
если необходимо.Следующий псевдокод иллюстрирует это:
typedef int VType; // the type of the variable
VType* v; // array of first and second variable
dispatch_queue_t* q; // queues for synchronizing access to v[i]
- (void) setV:(VType)newV {
[self setV:newV at:0];
}
- (void) setV:(VType)newV at:(int)i {
dispatch_barrier_async(q[i], ^{
v[i] = newV;
});
}
- (VType) getV:(int)i {
__block VType result;
dispatch_sync(q[i], ^{
result = v[i];
});
return result;
}
- (VType) getV {
VType result = [self getV:1];
if ([self random] < 0.01) {
VType v0_result = [self getV:0];
if (v0_result != result) {
[self setV:v0_result at:1];
result = v0_result;
}
}
return result;
}
- (float) random {
// some random number generator - fast, but not necessarily good
}
Это имеет следующие преимущества:
v[0]
обычно не занят операцией чтения. Поэтому операция записи обычно не блокируется.
В большинстве случаевv[1]
не записывается, таким образом операции чтения на этом обычно нет блок.
Тем не менее, если происходит много операций чтения, в конечном итоге записанные значения передаются изv[0]
вv[1]
, Некоторые значения могут быть пропущены, но это нене имеет значения для моего заявления.
Как вы думаете, это работает? Есть ли лучшие решения?
ОБНОВИТЬ:
Некоторый бенчмаркинг производительности (чтение и запись одного бенчмарка за раз выполняются как можно быстрее одновременно за 1 секунду, одна очередь чтения, одна очередь записи):
На iPhone 4S с iOS 7:
runMissingSyncBenchmark: 484759 w/s
runMissingSyncBenchmark: 489558 r/s
runConcurrentQueueRWSyncBenchmark: 2303 w/s
runConcurrentQueueRWSyncBenchmark: 2303 r/s
runAtomicPropertyBenchmark: 460479 w/s
runAtomicPropertyBenchmark: 462145 r/s
В симуляторе с iOS 7:
runMissingSyncBenchmark: 16303208 w/s
runMissingSyncBenchmark: 12239070 r/s
runConcurrentQueueRWSyncBenchmark: 2616 w/s
runConcurrentQueueRWSyncBenchmark: 2615 r/s
runAtomicPropertyBenchmark: 4212703 w/s
runAtomicPropertyBenchmark: 4300656 r/s
Пока что атомная собственность выигрывает. Потрясающе. Это было проверено с.SInt64
Я ожидал, что подход с параллельной очередью по производительности похож на атомарное свойство, так как это стандартный подход для механизма r / w-синхронизации.
Конечно,runMissingSyncBenchmark
иногда производит чтения, которые показывают, что записьSInt64
на полпути сделано.