Нужен совет. Пишу приложение, которое должно рассылать некоторую информацию (30байт) внутри одного компа нескольлким приложениям (~20). Есть очень жесткие требования к производительности. Процесс передачи не должен занимать больше 5-10 микросекунд.
Сейчас пробую смотреть на Shared Memory в качестве сторейджа для данных. Остановился на том, что не могу найти объект ядра, который бы позволил клиентам спать до наступления изменений в сторейдже и не просыпаться, до тех пор пока не придут новые для него новые данные. Тоесть нужно чтото типа такого:
// On client side
WaitUntilEqual( kernel_object, someVal );
// On server side
Update( kernel_object, new_value );
Если делать это в user-mode, то тогда сильно грузится проц. Пробовал играться с существующими объектами ядра:
— ManualResetEvent не подходит потому, что клиент может начать обрабатывать данные по второму кругу и еще нужно както думать, когда его выключать.
— С AutoResetEvent обратная фигня — клиент после просыпания должен высталвять этот евент в сигнальное состояние, если есть еще слушающие другие клиента. И потом latency последнего клиента будет сумарным от latency всех предыдущих.
— Семафор тоже не получается применить.
Сейчас буду играться с мультикастом на локале. ИМХО это будет как с пушки по воробьям. Может есть чтоот еще более легковесное?
Re: Рассылка данных от одного сервера к нескольлким клиентам
Здравствуйте, dimchick, Вы писали:
D>- ManualResetEvent не подходит потому, что клиент может начать обрабатывать данные по второму кругу и еще нужно както думать, когда его выключать.
Если серверу известно кол-во клиентов, то можно использовать ManualResetEvent вместе с InterlockedExchangeAdd. Сервер прибавляет к значению разделяемой переменной 20 (по числу клиентов) и будит клиентов Event'ом. Каждый клиент вычитывает данные и вычитает из переменной по единичке. Последний клиент понимает, что он последний, по нулевому значению переменной и сбрасывает Event.
Re[2]: Рассылка данных от одного сервера к нескольлким клиен
Здравствуйте, sz36, Вы писали:
S>Здравствуйте, dimchick, Вы писали:
D>>- ManualResetEvent не подходит потому, что клиент может начать обрабатывать данные по второму кругу и еще нужно както думать, когда его выключать.
S> Если серверу известно кол-во клиентов, то можно использовать ManualResetEvent вместе с InterlockedExchangeAdd. Сервер прибавляет к значению разделяемой переменной 20 (по числу клиентов) и будит клиентов Event'ом. Каждый клиент вычитывает данные и вычитает из переменной по единичке. Последний клиент понимает, что он последний, по нулевому значению переменной и сбрасывает Event.
Минусов тут два:
1. Клиенты будут просыпаться и в холостую работать, пока все не отработают
2. Если кто-то из клиентов отвалится (упадет процесс), или просто глюк в реализации, то это отразится на остальных клиентах.
Re: Рассылка данных от одного сервера к нескольлким клиентам
Здравствуйте, dimchick, Вы писали:
D>Нужен совет. Пишу приложение, которое должно рассылать некоторую информацию (30байт) внутри одного компа нескольлким приложениям (~20). Есть очень жесткие требования к производительности. Процесс передачи не должен занимать больше 5-10 микросекунд.
Не совсем понятно, что здесь имеется в виду: затраты процессорного времени на отправляющей стороне, интервал между помещением данных "в канал" и началом (завершением?) их чтения получателем, ещё что-то?
D>Сейчас пробую смотреть на Shared Memory в качестве сторейджа для данных. Остановился на том, что не могу найти объект ядра, который бы позволил клиентам спать до наступления изменений в сторейдже и не просыпаться, до тех пор пока не придут новые для него новые данные. Тоесть нужно чтото типа такого:
[...]
D>Сейчас буду играться с мультикастом на локале. ИМХО это будет как с пушки по воробьям. Может есть чтоот еще более легковесное?
Пайпы (pipes) пробовал?
Ещё посмотри в сторону boost::interprocess. Не ахти какая легковесная, но кроссплатформенная и есть много готовых примитивов.
Наконец, есть вот такой, почти классический приём (кстати, применяется в boost::interprocess):
// Client sidevoid waitForData()
{
while (!someoneSharedFlag) // Здесь может быть что-то из Interlocked
{
Sleep(0); // Пропускаем квант, можно каким-нибудь другим способом
}
}
Недостатки понятны, конечно: задержка передачи данных в общем не предсказуема и может оказаться равной длительности кванта (миллисекунды), зато надёжно и просто.
Я знаю только две бесконечные вещи — Вселенную и человеческую глупость, и я не совсем уверен насчёт Вселенной. (c) А. Эйнштейн
P.S.: Винодельческие провинции — это есть рулез!
Re[2]: Рассылка данных от одного сервера к нескольлким клиен
Здравствуйте, Геннадий Васильев, Вы писали:
ГВ>Здравствуйте, dimchick, Вы писали:
D>>Нужен совет. Пишу приложение, которое должно рассылать некоторую информацию (30байт) внутри одного компа нескольлким приложениям (~20). Есть очень жесткие требования к производительности. Процесс передачи не должен занимать больше 5-10 микросекунд.
ГВ>Не совсем понятно, что здесь имеется в виду: затраты процессорного времени на отправляющей стороне, интервал между помещением данных "в канал" и началом (завершением?) их чтения получателем, ещё что-то?
2-е. Интервал между началом передачи на сервере и завершением приема перед началом обработки на клиенте.
ГВ>Пайпы (pipes) пробовал?
Pipes — это соединение точка-точка. При увеличении кол-ва клиентов, работа по нотификации клиентов будет возрастать. Надо будет думать о разпаралеливании процесса нотификации от основной работы. А это дополнительные издержки синхронизации потоков.
ГВ>Ещё посмотри в сторону boost::interprocess. Не ахти какая легковесная, но кроссплатформенная и есть много готовых примитивов.
Смотрел. Хотел заюзать upgradable mutex и conditional variable. К сожалению они друг с другом не работают.
На счет портабельности — это клево, но не приоритет. Целевая платформа у меня Win Server 2008 x64.
ГВ>Наконец, есть вот такой, почти классический приём (кстати, применяется в boost::interprocess):
ГВ>
ГВ>// Client side
ГВ>void waitForData()
ГВ>{
ГВ> while (!someoneSharedFlag) // Здесь может быть что-то из Interlocked
ГВ> {
ГВ> Sleep(0); // Пропускаем квант, можно каким-нибудь другим способом
ГВ> }
ГВ>}
ГВ>
ГВ>Недостатки понятны, конечно: задержка передачи данных в общем не предсказуема и может оказаться равной длительности кванта (миллисекунды), зато надёжно и просто.
Sleep(0) уже не такой как раньше. Раньше он проц не грузил. Сейчас он грузит проц на 100%.
If you specify 0 milliseconds, the thread will relinquish the remainder of its time slice but remain ready.
Re: Рассылка данных от одного сервера к нескольлким клиентам
<skip> D>Сейчас пробую смотреть на Shared Memory в качестве сторейджа для данных. Остановился на том, что не могу найти объект ядра, который бы позволил клиентам спать до наступления изменений в сторейдже и не просыпаться, до тех пор пока не придут новые для него новые данные. Тоесть нужно чтото типа такого:
<skip>
Здравствуйте, dimchick, Вы писали:
ГВ>>Пайпы (pipes) пробовал?
D>Pipes — это соединение точка-точка. При увеличении кол-ва клиентов, работа по нотификации клиентов будет возрастать. Надо будет думать о разпаралеливании процесса нотификации от основной работы. А это дополнительные издержки синхронизации потоков.
Сдаётся, что тебе так и так придётся распараллеливать раздачу сообщений и основную работу. А пайпы хороши тем, что их можно использовать как объект синхронизации, т.е. приёмнику не понадобится терять time slice в ожидании.
Я знаю только две бесконечные вещи — Вселенную и человеческую глупость, и я не совсем уверен насчёт Вселенной. (c) А. Эйнштейн
P.S.: Винодельческие провинции — это есть рулез!