Блоки GCD в частной очереди перестают выполняться с большими базами данных SQLite3

У меня есть последовательная очередь, созданная следующим образом:

self.myQueue = dispatch_queue_create("com.myDomain.myQueue", DISPATCH_QUEUE_SERIAL);

У меня есть база данных sqlite3 для хранения моих данных. Вместо того, чтобы фиксировать эти данные каждый раз, каждый раз, когда я получаю часть данных, я сохраняю их в буфере — в данном случае, на основе CPP «вектора» более низкого уровня.

Я добавляю блоки в свою личную очередь для записи в буфер. Я использую dispatch_async () для этого. Через заданный интервал времени я фиксирую данные в БД из буфера.

Когда размер БД ниже 5 МБ, все работает как положено — все данные поступают, каждый записывается в буфер, после истечения временного интервала данные передаются в БД из буфера.

Когда размер БД увеличивается до 5 МБ (прибл.), Блоки в очереди, по-видимому, не выполняются до интервала времени для передачи данных в БД. По истечении этого времени одна запись записывается в буфер. В следующий раз, когда временной интервал истечет, данные будут переданы в БД, и снова только одна запись будет записана в буфер — на этот раз другая запись, которая находится в той последовательности, в которой я ожидаю, что записи поступят.
Кажется, что каждый блок выполняется только после того, как я записал в БД, что происходит только каждый раз, когда я нахожусь в определенный интервал времени.

Примечание: я проверил, что эти блоки выполняются, выполняются чисто — без ошибок.

Я не могу понять связь здесь между размером БД и неисполнением (если есть такое слово) блоков в частной очереди.

Имеет ли какое-либо отношение к ширине потока его частная очередь? Или память касается? Я бы сказал, размер БД, но кажется, что блоки с каждым интервалом времени выполняются правильно. Кроме того, я бы сказал, размер БД напрямую, но я не могу записать в сам буфер.

Любые мысли, чтобы дать мне направление ИЛИ это проблема ОС вне моего контроля?

0

Решение

Не совсем понятно, как вы его настроили: похоже, у вас есть вектор, защищенный для одновременного доступа через последовательную очередь. Тогда кажется, что вы также выполняете периодическую операцию с базой данных в той же очереди. Поскольку это последовательная очередь, если операции с базой данных начинают занимать все больше и больше времени, другие операции будут резервироваться за операцией базы данных. Я бы рекомендовал использовать очередь только для примитивных операций на 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 являются операциями над общим вектором. Когда приходит время передать в базу данных, вы копируете записи из общего вектора в личную копию, очищаете общий вектор и отправляете личную копию в dbQueue быть преданным.

1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]