A> while(true)
A> {
A> const int packet_awailable = get_pending_count(sock);
A> for (int i = 0; i < packet_awailable; ++i)
A> {
A> int nRead = recvfrom(sock, packet, PACKET_LEN, 0, NULL, NULL);
A> _ASSERT(nRead == PACKET_LEN);
A> stat.OnPacket(packet);
A> }
A> Sleep(20);
A> }
Идея со Sleep(20) — так себе.
Поток не пробуждается сразу же по приходу хотя бы одного пакета.
Представьте, что пакет приходит в первую мс слипа, а мы все равно спим еще 19 мс.
Лучше для ожидания поступления данных использовать select.
Вторая проблема, если за время слипа придет слишком много пакетов, то возможна их потеря.
Т.к. у сокета внутренний буфер конечного размера.
Здравствуйте, qaz77, Вы писали:
Q>Идея со Sleep(20) — так себе. Q>Поток не пробуждается сразу же по приходу хотя бы одного пакета. Q>Представьте, что пакет приходит в первую мс слипа, а мы все равно спим еще 19 мс. Q>Лучше для ожидания поступления данных использовать select.
такая актуальность и не требуется, обработка всех собранных за "такт" пакетов происходит пачкой, поток не прыгает в сон и не пробуждается без надобности
в случае обработки по приходу поток бы постоянно дергался (пакеты идут 20 К в секунду) полюсов не видно.
Q>Вторая проблема, если за время слипа придет слишком много пакетов, то возможна их потеря. Q>Т.к. у сокета внутренний буфер конечного размера.
конечно, но с существенным запасом,
при потоке 20К в секунду за 20 мс придет 400 пакетов, а буфер у меня на ~4000
Здравствуйте, tryAnother, Вы писали: A>такая актуальность и не требуется, обработка всех собранных за "такт" пакетов происходит пачкой, поток не прыгает в сон и не пробуждается без надобности A>в случае обработки по приходу поток бы постоянно дергался (пакеты идут 20 К в секунду) полюсов не видно.
Если много датаграм приходит в единицу времени, то ожидание по select не приведет к лишним пробуждениям потока.
Когда пробудились кушаем все, пока очередь пакетов не пустая.
На практике надо замерять производительность со Sleep и select.
Все-таки смущает хардкод константы 20 мс.
Допустим софт будет крутится на слабенькой машине и время манипуляции с принятым пакетом будет сильно больше...
Если это не массовый софт, а написанный для конкретной железки, то наверное и так норм.
Я вот пишу коробочный и даже сейчас в 2022 еще пентиум 3 у клиентов бывает.
Здравствуйте, tryAnother, Вы писали:
A> ++seq_; A> if(seq_ != seq) A> printf("Sequence broken, recv %d expect %d, dif %d\n", seq, seq_, seq-seq_);
блэт, слона то я и не заметил, это UDP, алло, откуда здесь гарантия последовательности пакетов? и откуда гарантия последовательного вызова хендлеров в азио?
УК>надо сделать один раз, например в конструкторе, хендлер один и тот же, зачем он аллоцируется каждый раз?
допускаю что тут лишние аллокации, которых можно избежать, но 20К аллокаций в секунду не большая нагрузка
и синхронная версия по потерям ведет себя аналогично асинхронной, то есть дело не в этом.
а можно ли посмотреть на код где "асио не напрягаясь может хендлить на одном ядре на порядок больше пакетов" и интересно какой там pps и общая скорость.
УК>блэт, слона то я и не заметил, это UDP, алло, откуда здесь гарантия последовательности пакетов? и откуда гарантия последовательного вызова хендлеров в азио?
гарантий никто и не обещал, это понятно, но сеть там точка точка, никого кроме железки и принимающей машины нет, и она работает хорошо, пакетам там теряться некуда.
вопрос в сравнении подходов к чтению:
— синхронный и асинхроный asio теряют пачки по единицам — десяткам пакетов от единиц до десятков в час в зависимости от загрузки машины,
— подход с чтением через sleep теряет единицы пакетов в сутки
Здравствуйте, tryAnother, Вы писали:
A>гарантий никто и не обещал, это понятно, но сеть там точка точка, никого кроме железки и принимающей машины нет, и она работает хорошо, пакетам там теряться некуда.
рация работает на бронепоезде? речь не о потерях, а о порядке пакетов
A>вопрос в сравнении подходов к чтению: A>- синхронный и асинхроный asio теряют пачки по единицам — десяткам пакетов от единиц до десятков в час в зависимости от загрузки машины, A>- подход с чтением через sleep теряет единицы пакетов в сутки
ещё раз, текущий тест "потери пакетов" невалиден, инкремент счётчика тут не канает, если надо посчитать количество принятых пакетов — заведи vector<bool> например на миллион элементов, и засовывай ему по индексу, который равен id пришедшего пакета true, после отправки миллиона пакетов выждать паузу и посчитать, сколько в векторе true значений, если меньше миллиона, то есть потери.
Здравствуйте, Умака Кумакаки, Вы писали:
УК>Здравствуйте, tryAnother, Вы писали:
A>>гарантий никто и не обещал, это понятно, но сеть там точка точка, никого кроме железки и принимающей машины нет, и она работает хорошо, пакетам там теряться некуда. УК>рация работает на бронепоезде? речь не о потерях, а о порядке пакетов
рация конечно на танке, но тест результаты теста показывают не перетасовку пакетов, а именно потерю
если бы проблемы была в потере порядка, то сообщения изобиловали как положительными так и отрицательными dif
A>>вопрос в сравнении подходов к чтению: A>>- синхронный и асинхроный asio теряют пачки по единицам — десяткам пакетов от единиц до десятков в час в зависимости от загрузки машины, A>>- подход с чтением через sleep теряет единицы пакетов в сутки
УК>ещё раз, текущий тест "потери пакетов" невалиден, инкремент счётчика тут не канает, если надо посчитать количество принятых пакетов — заведи vector<bool> например на миллион элементов, и засовывай ему по индексу, который равен id пришедшего пакета true, после отправки миллиона пакетов выждать паузу и посчитать, сколько в векторе true значений, если меньше миллиона, то есть потери.
счетчик не только инкриминируется (перед проверкой), но и устанавливается на последний принятый номер (после проверки)
что обеспечивает оба типа проверки, и потерю и перестановку.
и перестановки действительно ловились но проблема тогда была в самой железке, сейчас их нет.
и при чтении с задержкой и потерь почти нет.
еще какие предположения по невалидности теста? и почему он проходит в режиме с задержкой
Здравствуйте, tryAnother, Вы писали:
A>еще какие предположения по невалидности теста? и почему он проходит в режиме с задержкой
я бы всё таки убрал аллокацию, возможно после тысяч аллокаций аллокатор решает компактифицировать кучу, или ещё какую оптимизацию провести, и на этот момент попадает передача пакета. Убери вообще класс calcstat, сделай просто свободную функцию OnPacket(const boost::system::error_code& error, std::size_t bytes_transferre), внутри неё статическую переменную int seq_ и передавай этот хендлер просто как есть, без оборачивания в функтор через bind