суббота, 21 апреля 2012 г.

fork vs pthread

Попытка построить ядро моего диплома, включающего сбор ip, tcp и http заголовков с отправкой их в mysql для последующего анализа на базе одного процесса провалилась - инсерт сильно дольше приёма очередного пакета при большом трафике, в БД каша получается.
Попытался делать так - форкать отдельный процесс под отправку данных в БД и передавать ему обработанный пакет через пайп - тот же эффект.
Стал одним процессом собирать запросы в shared memory,  дочерним зеркалировать участок памяти и из зеркала слать. Синхронизацию делал через posix semaphores. Что получил - при большом трафике тот процесс, что загребает трафик, постоянно заходит в свою критическую зону, а отсылающий процесс просто висит в ожидании, отжирая целое ядро.

Уже было отчаился, но решил переписать с тредами - и, о диво! Оно заработало!!!
Механика такая: создаём 2 треда - для сбора трафика и для отправки.
Первый в pcap_loop callout раздирает пакет и формирует VALUE список, добавляя его в своей критической секции в шаренный через анонимный mmap участок.
Второй тред в своей критикал цепляет содержимое вышеуказанного участка в свой буфер и после выхода из критикала спокойно инсертит одним запросом. Сегодня вечером выкатил на продакшн, было около 3 тыс. инсертов в секунду.
Вот сам код, непричёсанный ещё, правда:
 https://github.com/speedcorezombie/pget/blob/master/pget.c

Комментариев нет: