LINUX.ORG.RU

Ответ на: комментарий от klalafuda

>selectable event queue

я если правильно понимаю фразу "межтредовое" то бишь над расшареной памятью, то трубы тут не применимы/приведут к тормозам; а в качестве очереди можно сделать список, на который поставить семафор доступа.

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

> я если правильно понимаю фразу "межтредовое" то бишь над расшареной памятью, то трубы тут не применимы/приведут к тормозам; а в качестве очереди можно сделать список, на который поставить семафор доступа.

это не применимо в случае, когда необходимо ждать на пачке разнородных источников событий. например, на сокете и каком-то application specific событии.

// wbr

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

>>selectable event queue

>я если правильно понимаю фразу "межтредовое" то бишь над расшареной памятью, то трубы тут не применимы/приведут к тормозам

применимы; не приведут.

> а в качестве очереди можно сделать список, на который поставить семафор доступа.

и как ты будешь одновременно ждать очередь и (например) сокет?

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

> Поллить сокет и проверять очередь. Кстати чем это плохо?

Проверять очередь на истечении тайм-аута poll? Это либо потеря во времени реакции, либо переход к busy waiting.

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

Спасибо, я понял.

Передача чего-то маленького между тредами по трубам даёт возможность юзать один вызов select, ожидая чего-то из труб и из каких-нибудь там сетевых дескрипторов.

Legioner
Ну плохо постоянным движением. Сидеть в select и не дёргаться - это меньше шевелений с тем же результатом. Дёргаться между очередью и poll - это постоянное шевеление. И возникает вопрос баланса: жрать больше проца и быстрее реагировать или наоборот? А селект изящнее - засел в него и без всяких шевелений тебе гарантируется самая быстрая реакция.

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

> Это либо потеря во времени реакции

почему? если в select передавать в качестве timeout 0, то он с одной стороны не ждёт лишнее время, с другой стороны это не busy waiting, т.к. процессор не грузится.

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

> А селект изящнее

это да, но он жутко не гибкий, только дескрипторы слушать умеет. Наверное я просто не понимаю дао юникса.

Legioner ★★★★★
()

Главное применение уже озвучено -- когда надо _в_том_числе_ ждать на селекте внешнее событие.

Еще я сталкивался с таким: при определенных условиях нитка может форкнуться.

Еще навскидку:

Использование универсальной функции, пригодной на все случаи жизни.

Тестирование / бенчмарки разрабатываемой функции.

Тестирование / бенчмарки ядра.

Извращения:

Автоматическое квантование по PIPE_BUF байт (когда несколько ниток пишут в один пайп);

накрутка sys time.

Ну, дальше лень фантазировать...

Die-Hard ★★★★★
()
Ответ на: комментарий от Legioner

>> Это либо потеря во времени реакции

> почему?

ы...

> если в select передавать в качестве timeout 0, то он с одной стороны не ждёт лишнее время, с другой стороны это не busy waiting, т.к. процессор не грузится.

Ты передал 0 в select, опросил сокет, и... дальше что? Ты начинаешь ждать очереди? тогда ты теряешь время реакции на данные из сокета. Ты опрашиваешь очередь, и потом переходишь к select с 0? Это busy waiting.

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

> если в select передавать в качестве timeout 0, то он с одной стороны не ждёт лишнее время, с другой стороны это не busy waiting, ...

:-)

Это -- именно busy waiting.

Die-Hard ★★★★★
()
Ответ на: комментарий от Legioner

>> А селект изящнее

> это да, но он жутко не гибкий, только дескрипторы слушать умеет. Наверное я просто не понимаю дао юникса.

Именно -- селект как раз ЖУТКО гибкий! И именно в духе юнихового дао, ибо "все есть файл"!

Die-Hard ★★★★★
()
Ответ на: комментарий от Legioner

> Почему он busy waiting?

Потому что у тебя в цикле нет ни одного ожидания события - только опрос.

Ну а вообще - мы с Дайхардом так сказали, ты нам что - не веришь? :D

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

>> Ты опрашиваешь очередь, и потом переходишь к select с 0? Это busy waiting.

>Этот вариант. Почему он busy waiting?

Это не просто busy waiting, а извращенный busy waiting, с заходом в ядро! Такое приложение на непреемтабельном ядре даже убить может не сразу получиться...

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

> Именно -- селект как раз ЖУТКО гибкий! И именно в духе юнихового дао, ибо "все есть файл"!

Да нифига... дисковых файлов он не ждет. Ну и не всё есть файл :(

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

> ибо "все есть файл"!

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

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

> Потому что у тебя в цикле нет ни одного ожидания события - только опрос.

сейчас проверю. Критерием busy waiting является ведь загруженный (хотя бы до 2 процентов) процессор, так?

> Ну а вообще - мы с Дайхардом так сказали, ты нам что - не веришь? :D

я агностик :)

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

> Критерием busy waiting является ведь загруженный (хотя бы до 2 процентов) процессор, так?

Упрощенно говоря, да.

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

> Передача чего-то маленького между тредами по трубам даёт возможность юзать один вызов select, ожидая чего-то из труб и из каких-нибудь там сетевых дескрипторов.

да, всё лишь для select & K. сама по себе передача данных между процессами посредством IPC большого смысла конечно же не несёт.

// wbr

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

#include <sys/select.h>
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>

int main(void)
{
    fd_set read_set;
    struct timeval timeout;
    int read_rv;
    char c;
    int sum = 0;

    FD_ZERO(&read_set);
    FD_SET(0, &read_set);
    timeout.tv_sec = 0;
    timeout.tv_usec = 0;

    if (fcntl(0, F_SETFD, O_NONBLOCK) == -1) {
        perror("fcntl");
        abort();
    }

    for (;;) {
        if (select(1, &read_set, NULL, NULL, &timeout) == -1) {
            perror("select");
            abort();
        }

        read_rv = read(0, &c, 1);
        if (read_rv == -1 && errno != EAGAIN) {
            perror("read");
            abort();
        }
        if (read_rv == 0) {
            break;
        }

        sum += c;
        printf("Sum: %d\n", sum);
    }

    return 0;
}

Работает, процессор не ест (т.е. совсем не ест), что я делаю не так?

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

> Работает, процессор не ест (т.е. совсем не ест), что я делаю не так?

размножте это на 100 потоков по по 10к дескрипторов в каждом.

// wbr

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

> Работает, процессор не ест (т.е. совсем не ест)

А что это вообще такое?

> что я делаю не так?

Прогони под strace - поймешь.

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

> размножте это на 100 потоков по по 10к дескрипторов в каждом.

всё равно будет работать :) но это не то, о чем говорилось выше.

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

>> Работает, процессор не ест (т.е. совсем не ест)

> А что это вообще такое?

Где? :) Демонстрация "активного" ожидания, которое не ресурсоёмко.

>> что я делаю не так?

>Прогони под strace - поймешь.

Я представляю, что будет. И что это показывает?

100 тредов сейчас попробую, даже интересно.

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

> 100 тредов сейчас попробую, даже интересно.

Не надо, я тебе верю.

Ты что-то глобально не понимаешь... Я ж даже строчку "неверную" привел! Или ты не понимаешь термина busy waiting? Или не знаешь, что такое блокирующее чтение?

Die-Hard ★★★★★
()
Ответ на: комментарий от Legioner

>Работает, процессор не ест (т.е. совсем не ест), что я делаю не так?

read блокирует процесс

rc = select(1, &read_set, NULL, NULL, &timeout);

if (rc == -1) {
 perror("select");
 abort();
}
else if (rc > 0) {
 read_rv = read(0, &c, 1);
 if (read_rv == -1 && errno != EAGAIN) {
  perror("read");
  abort();
 }
 if (read_rv == 0) {
  break;
 }

 sum += c;
 printf("Sum: %d\n", sum);
}

generatorglukoff ★★
()
Ответ на: комментарий от Die-Hard

> Или не знаешь, что такое блокирующее чтение?

Он не понимает, что такое "неблокирующее чтение".

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

Протормозил, сорри. Я думал, что fcntl сделает 0 неблокируемым, а он почему то не сделал. Сейчас поразбираюсь.

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

int flags;

    flags = fcntl(0, F_GETFL);
    flags |= O_NONBLOCK;
    fcntl(0, F_SETFL, flags);


Еще как жрет!!!
:-)

Die-Hard ★★★★★
()
Ответ на: комментарий от Legioner

> Мои посты здесь можно грохнуть как 4.2

Не надо, очень поучительная дискуссия вышла! Оставь их.

Если хочешь, могу свой "наезд" грохнуть.

Die-Hard ★★★★★
()
Ответ на: комментарий от Legioner

> Работает, процессор не ест (т.е. совсем не ест)

Не ест, так как блокируется в read. Видимо fcntl эффекта не возымело тупо. А раз блокируется, то нифига это не активное ожидание. Это вообще гавнищецкое и саксовое ожидание с попадаловом в глубокий read получился (-;

irc_007_1
() автор топика
Ответ на: комментарий от Die-Hard

> Если хочешь, могу свой "наезд" грохнуть.

Блин, уже не получится без жертв...

Ладно, я просто извинюсь за свою фразу "Ты что-то глобально не понимаешь...", ок?

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

Не надо, поделом мне.

На самом деле я всё это написал потому, что когда то писал на Xlib-е программу, мне там нужен было имитировать события таймера и я делал poll на сокете соединения с Xserver-ом. Видимо там всё таки был не 0, потому что всё работало и не ело процессор. Но я почему то подумал, что 0.

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

Кстати, на Линуксе возможно извращение с sched_yield();
тогда процесс будет кушать только свободный процессор.
Такое в большинстве современных ядер по умолчанию
будет кушать под 100 процентов, если оно одно, но 
если есть конкуренты, оно будет кушать 0 процентов 
(но так делать не надо, если не знаешь, зачем):

конкуренты, оно б
#include <sys/select.h>
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sched.h>

int main(void)
{
    fd_set read_set;
    struct timeval timeout;
    int read_rv;
    char c;
    int sum = 0;
    int flags;

    FD_ZERO(&read_set);
    FD_SET(0, &read_set);
    timeout.tv_sec = 0;
    timeout.tv_usec = 0;

    if (fcntl(0, F_SETFD, O_NONBLOCK) == -1) {
        perror("fcntl");
        abort();
    }

    flags = fcntl(0, F_GETFL);
    flags |= O_NONBLOCK;
    fcntl(0, F_SETFL, flags);

    for (;;) {
        if (select(1, &read_set, NULL, NULL, &timeout) == -1) {
            perror("select");
            abort();
        }
        sched_yield();
        read_rv = read(0, &c, 1);
        if (read_rv == -1 && errno != EAGAIN) {
            perror("read");
            abort();
        }
        if (read_rv == 0) {
            break;
        }

        sum += c;

    }
        printf("Sum: %d\n", sum);
    return 0;
}

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

Вдогонку -- там непринципиальные опечатки (например, if (fcntl(0, F_SETFD, O_NONBLOCK) == -1) {} лишний), но смысл, надеюсь, понятен.

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

Итог.

Эти условия таковы: куча всего уже засунуто в один селект и тут возникает потребность в какой-то специфической нашей очереди сообщений. Соблазн "засунуть её в тот же селект" может быть реализован трубопрокатностью. Соблазн продиктован неприятием поллинга и излишних шевелений.

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

Хм, а ты видел мой ответ?

http://www.linux.org.ru/view-message.jsp?msgid=2631114#2631465

В ситуации с селектом пайпы -- классический паттерн, иначе проблема просто труднорешаемая, никакой поллинг тут не поможет, разве что перебивать селект сигналом из другой нитки (верх изящества!)

Мне реально встречалась ситуация, когда пришлось общаться пайпами просто потому, что нитка при определенных условиях могла форкаться.

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

> Главное применение уже озвучено -- когда надо _в_том_числе_ ждать на
> селекте внешнее событие.

Понято.

> Еще я сталкивался с таким: при определенных условиях нитка может
> форкнуться.

Может лучше сказать "иногда программируют форкание из треда", а то как-то самопроизвольно форкающийся тред чё-то пугает )

>Еще навскидку:
>Использование универсальной функции, пригодной на все случаи жизни.
Например!

>Тестирование / бенчмарки разрабатываемой функции.
Например!

>Тестирование / бенчмарки ядра.
Например!


А зачем нужна накрутка систайма?

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

> Может лучше сказать "иногда программируют форкание из треда", а то как-то самопроизвольно форкающийся тред чё-то пугает )

:-) Терминологический вопрос! Мой сленг коробит кривая вилка, а слова "самопроизвольно" там не было. В нитке происходит вызов форка => нитка форкнулась т.е., раздвоилась (со всем адресным пространством), ИМХО понятно...

>>Использование универсальной функции, пригодной на все случаи жизни.

>Например!

Ну, хочется тебе некий IPC протокол свой наваять, чтобы и на кластер вставал, и на SMP, а на SMP вместо процессов часто логичнее треды юзать...

>>Тестирование / бенчмарки разрабатываемой функции.

>Например!

Ну, отлаживаешь консольную функцию на предмет перехвата stdin, stdout и stderr, и в процессе отладки хочешь ее глобальными параметрами играть..

>>Тестирование / бенчмарки ядра.

>Например!

Насколько твой супер-патч на тему футекса влияет на латентность блокировки файлового дескриптора, например...

> А зачем нужна накрутка систайма?

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

:-)

Die-Hard ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.