У меня есть последовательная очередь, созданная следующим образом:
self.myQueue = dispatch_queue_create("com.myDomain.myQueue", DISPATCH_QUEUE_SERIAL);
У меня есть база данных sqlite3 для хранения моих данных. Вместо того, чтобы каждый раз записывать эти данные, каждый раз, когда я получаю кусок данных, я храню его в буфере - в данном случае - на "основе" на основе CPP на нижнем уровне.
Я добавляю блоки в свою приватную очередь для записи в буфер. Для этого я использую dispatch_async(). После предопределенного интервала времени я передаю данные в БД из буфера.
Когда БД находятся ниже 5 МБ, все работает так, как ожидалось, - все данные поступают, каждый записывается в буфер, по истечении интервала времени данные передаются в БД из буфера.
Когда размер БД увеличивается до более 5 МБ (приблизительно), блоки в очереди, похоже, не выполняются до временного интервала для передачи данных в БД. Когда это время будет сделано, одна запись будет записана в буфер. В следующий раз истекает интервал времени, данные передаются в БД, и снова в буфер записывается только одна запись - на этот раз другая запись, которая находится в последовательности, я ожидаю, что записи войдут. Кажется, что каждый блок выполняется только после того, как я написал в БД, который происходит только каждый раз, когда я нахожусь на определенном временном интервале.
Примечание. Я проверил, что эти блоки выполняются, выполняются чисто - без ошибок.
Я не могу понять ссылку здесь между размером БД и невыполнением (если есть такое слово) блоков в частной очереди.
Связана ли ширина его частной очереди с ней? Или проблема памяти? Я бы сказал, размер БД, но кажется, что каждый раз-интервальные блоки выполняются правильно. Кроме того, я бы сказал, DB размер напрямую, но я не могу писать в буфер.
Любые мысли, чтобы дать мне направление ИЛИ, это проблема ОС вне моего контроля?
Не совсем понятно, как вы его настроили: похоже, у вас есть вектор, который защищен для одновременного доступа с использованием последовательной очереди. Похоже, вы также выполняете периодическую операцию с базой данных в одной очереди. Поскольку это последовательная очередь, если операции с базой данных начинают занимать больше времени и дольше, другие операции будут выполнять резервное копирование за операцией базы данных. Я бы рекомендовал использовать очередь только для примитивных операций над vector
и использовать вторую очередь для управления операциями с базой данных. Это может выглядеть примерно так:
using namespace std;
dispatch_queue_t vectorQueue = NULL;
dispatch_queue_t dbQueue = NULL;
dispatch_source_t timer = NULL;
vector<whatever>* dbRecords = NULL;
void init()
{
dbRecords = new vector<whatever>();
vectorQueue = dispatch_queue_create(NULL, DISPATCH_QUEUE_SERIAL);
dbQueue = dispatch_queue_create(NULL, DISPATCH_QUEUE_SERIAL);
timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dbQueue);
dispatch_source_set_timer(timer, DISPATCH_TIME_NOW, NSEC_PER_SEC * 60, NSEC_PER_SEC);
dispatch_source_set_event_handler(timer, ^{
__block vector<whatever>* toCommit = NULL;
dispatch_sync(vectorQueue, ^{
if (dbRecords->size())
{
toCommit = new vector<whatever>(*dbRecords);
dbRecords->clear();
}
});
if (toCommit)
{
// Commit the records using your db code...
delete toCommit;
}
});
dispatch_resume(timer);
}
void enqueueRecord(whatever record)
{
dispatch_async(vectorQueue, ^{
dbRecords->push_back(record);
});
}
Таким образом, входящие блоки записи не резервируются, ожидая операции с базой данных. Единственными блоками, выполняемыми в vectorQueue
являются операции с общим вектором. Когда его время для фиксации на db, вы копируете записи из общего вектора в частную копию, очищаете общий вектор и отправляете личную копию на dbQueue
должна быть зафиксирована.
dbQueue
читает вектор, он делает это с помощью dispatch_sync для vectorQueue
.