LINUX.ORG.RU

queue+spinlock или ядерная очередь?

 ,


0

1

Из одного потока в другой нужно организовать очередь. Один писатель и один читатель. Рассматриваю варианты <queue>+spinlock или ядерную очередь.
Спинлок вроде быстр, но будет топить проц ждущим потоком
Ядерная очередь это передача данных через само ядро, но событие на очереди можно отлавливать с пом того же epoll, что очень удобно

Что думаете?



Последнее исправление: nyka (всего исправлений: 1)

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

Спинлок вроде быстр, но будет топить проц ждущим потоком

Не будет, если сразу после неудачной попытки захвата отдавать остаток кванта

Deleted
()

P. S. ядерная очередь, наверное, предполагает наличие системного вызова, который тоже не быстрый

Deleted
()

Ядерная очередь это передача данных через само ядро, но событие на очереди можно отлавливать с пом того же epoll, что очень удобно

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

Ядерная очередь это передача данных через само ядро, но событие на очереди можно отлавливать с пом того же epoll, что очень удобно

Топорная передача данных подобным образом создаёт накладные расходы множественным копированием передаваемых данных. Если по какой-то из причин захотелось использовать epoll (например, кроме событий от потоков нужно ловить IO события) и есть возможность использовать одно адрессное пр-во, то через epoll стоит передавать только эвент a la прочитай очередь.

anonymous
()
Ответ на: комментарий от anonymous

эвент через epoll на чтение очереди в юзерспейс тоже вариант. Для генерации эвента придется использовать тоже системный вызов. Какие есть варианты сгенерить событие дешевле всего?

nyka
() автор топика

Что думаете?

Мы думаем, что преждевременая оптимизация - дешевые понты корень всех зол. Естественно, нужно использовать готовые системные примитивы.

Ядерная очередь это передача данных через само ядро

«Ядерная очередь» - это что? POSIX mq, SysV IPC?

tailgunner ★★★★★
()
Последнее исправление: tailgunner (всего исправлений: 2)
Ответ на: комментарий от tailgunner

Спасибо что поправили. Имела в виду SysV

nyka
() автор топика
Ответ на: комментарий от tailgunner

Тогда складывается нормальная картина. Генерерируем событие в одном потоке eventfd(2) и отлавливаем в другом еполом. Для чтения/записи запираем спинлоком и используем обыкновенную юзерспейсную очередь.

nyka
() автор топика
Ответ на: комментарий от nyka

и отлавливаем в другом еполом.

Для чтения/записи запираем спинлоком

Очень жаль, если такая картина сложилось из моих слов. Использование спинлоков в юзерспейсе - это само по себе крайне cомнительное преприятие; это иногда нужно, но это не твой случай. То же самое и с epoll - если тебе не нужно ждать данные из нескольких очередей, тебе даже eventfd и poll не нужны - хватит обычного pthread_cond_wait(3).

tailgunner ★★★★★
()
Последнее исправление: tailgunner (всего исправлений: 1)
Ответ на: комментарий от tailgunner

У меня 2 потока и их нельзя заставлять ожидать данных из очереди. Данные должны обрабатываться только тогда когда пришли. Epoll уже обрабатывает события, т.е. костылем не будет.
Про сомнительность спинлока в юзерспейсе объясните пожалуйста

nyka
() автор топика
Ответ на: комментарий от nyka

У меня 2 потока и их нельзя заставлять ожидать данных из очереди.

epoll - это ожидание. И даже спинлок - это тоже ожидание.

Про сомнительность спинлока в юзерспейсе объясните пожалуйста

Спинлок - это занятое ожидание, используемое обычно при гарантиях невытесняемости нити. В юзерспейсе такой гарантии нет. И, судя по тому, что тебя бросает от спинлоков к epoll, ты сама не понимаешь, что тебе нужно (спинлоки и epoll - это средства, предназначенные для решения абсолютно разных задач).

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

да как это других? пришло событие-вынимаю из очереди данные. чем заперереть переменную так чтобы не усыплять потоки?

nyka
() автор топика

Что думаете?

Что ты чумичка бестолковая. Это настолько распространенный паттерн «producer-consumer queue», что даже неудобно писать.

Лучшее решение определяется тем как ведет себя очередь, она практически всегда пуста или практически всегда имеет элемент?

Bobby_
()
Ответ на: комментарий от Bobby_

как-то странно оскорблять за незнание
Данные в очередь помещаются редко, практически всегда пуста

nyka
() автор топика
Ответ на: комментарий от nyka

Тебе уже сказали как нужно работать правильно, а ты все тупишь. Тебе не приходило в голову, что люди уже решили эту проблему и решили ее оптимально?

практически всегда пуста

значим выбираем blocking queues

https://stackoverflow.com/questions/4577961/pthread-synchronized-blocking-queue

Bobby_
()

Просто замени spinlock на комбинацию spinlock и системного mutex (например, от pthread). Комбинированный mutex на вызове lock сначала N раз пытается залочить spinlock, а в случае неудачи уходит в ожидание системного mutex. Так работает std::mutex (по крайней мере в реализации от Microsoft).

quiet_readonly ★★★★
()
Последнее исправление: quiet_readonly (всего исправлений: 1)
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.