Сейчас на форуме: tyns777, zds, JustLife (+3 невидимых)

 eXeL@B —› Программирование —› Высокоскоростной UDP-генератор
Посл.ответ Сообщение

Ранг: 47.1 (посетитель), 2thx
Активность: 0.030
Статус: Участник

Создано: 29 января 2010 14:10
· Личное сообщение · #1

Столкнулся с такой проблемой, необходимо генерировать UDP трафик на максимальной скорости близкой к гигабиту, при этом каждый пакет для передачи в сеть генерируется отдельно и может иметь различный размер, т.е. размер != MTU.

Я пробовал писать все это дело через WSASendTo, вначале пробовал писать синхронно, но в итоге средние издержки на отсылку одного пакета были порядка 200-400 микросекунд что катастрафически много, ес-но с такими издержками быстродействием тут и не пахнет, зато дропа пакетов при этом не наблюдается.

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

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

Вобщем мой вопрос в том, возможно ли увеличить скорость в рамках юзер мода? и если возможно, то как?
В идеале, чтобы слать гигабит время отправки одного пакета должно быть порядка 12 микросекунд - но думаю меня бы устроил результат в пределах 50 микросекунд, только бы остаться в пределах юзермода и не писать драйверов.



Ранг: 237.0 (наставник), 20thx
Активность: 0.130
Статус: Участник
sysenter

Создано: 29 января 2010 14:42 · Поправил: HiEndsoft
· Личное сообщение · #2

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

-----
продавец резиновых утёнков




Ранг: 369.8 (мудрец), 400thx
Активность: 0.390
Статус: Участник

Создано: 29 января 2010 15:01
· Личное сообщение · #3

Code:
  1. int main(int argc, char* argv[])
  2. {
  3.          SOCKADDR_IN ina;
  4.          SOCKET      sock;
  5.          WSADATA     wsa_d;
  6.          char        buff[1024];
  7.          int         i;
  8.  
  9.          WSAStartup(MAKEWORD(2,2), &wsa_d);
  10.  
  11.          ina.sin_family           = AF_INET;
  12.          ina.sin_addr.S_un.S_addr = inet_addr("192.168.1.1");
  13.          ina.sin_port             = htons(123);
  14.          
  15.          for (= 0; i < sizeof(buff); i++) {
  16.                  buff[i] = i;
  17.          }
  18.          if ( (sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == SOCKET_ERROR ) {
  19.                  return 1;
  20.          }
  21.          for (;;) {
  22.                  sendto(sock, buff, sizeof(buff), 0, (void*)&ina, sizeof(ina));
  23.          }
  24.          
  25.          return 0;
  26. }

У меня этот код спокойно выдает 500мбит/c трафика.

-----
PGP key <0x1B6A24550F33E44A>




Ранг: 369.8 (мудрец), 400thx
Активность: 0.390
Статус: Участник

Создано: 29 января 2010 15:20
· Личное сообщение · #4

Попробовал отсылать асинхронно через IO Completion Ports, добился 923 мбит/сек при одновременной отсылке 100 пакетов.

-----
PGP key <0x1B6A24550F33E44A>




Ранг: 512.7 (!), 360thx
Активность: 0.270.03
Статус: Модератор

Создано: 29 января 2010 15:49
· Личное сообщение · #5

ntldr
можно пример?(как в пред. посте)
Спс



Ранг: 369.8 (мудрец), 400thx
Активность: 0.390
Статус: Участник

Создано: 29 января 2010 17:04
· Личное сообщение · #6

sendersu пишет:
можно пример?(как в пред. посте)

Извини, я писал тест не на API, а на коммерческой библиотеке асинхронного ввода-вывода, исходники которой открывать не имею права.

З.Ы. ещё можно отправить много UDP пакетов сразу через ф-ю TransmitPackets

-----
PGP key <0x1B6A24550F33E44A>




Ранг: 47.1 (посетитель), 2thx
Активность: 0.030
Статус: Участник

Создано: 29 января 2010 18:36
· Личное сообщение · #7

ntldr
хм, у меня посути такой же код, с той лишь что у меня дополнительно еще весит тред который слушает и отвечает на том же сокете, НО интенсивность трафика там практически нулевая(раз в пол секнуды могут приходить и уходить пакеты по 50-100 байт).

Я замеряю время следующим образом
QueryPerformanceFrequency(&fq);
...
QueryPerformanceCounter(&t1);
//Send buffer...
QueryPerformanceCounter(&t2);
n++; //количество пакетов
t += (t2.QuadPart-t1.QuadPart)*1000000/fq.QuadPart; //t - суммарное время отправки в микросекундах
...
и вконце нахожу средение время dt = t/n которое оказывается >100 мкс.

Мультипоточная отсылка с использованием IO Completion Port в данном случае слишком громоздка так как важна очередность пакетов, и следовательно очень сложно синхранизировать патоки правильным образом.

TransmitPackets еще не пробовал, но сча попробую с ним разобраться, спс за идею.



Ранг: 369.8 (мудрец), 400thx
Активность: 0.390
Статус: Участник

Создано: 29 января 2010 18:43
· Личное сообщение · #8

Vol4ok пишет:
с той лишь что у меня дополнительно еще весит тред который слушает и отвечает на том же сокете

Никогда не используй блокирующие сокеты одновременно в двух тредах, ибо вызванная одним тредом операция будет блокировать другие. Используй select и делай всё в одном потоке, или переходи на IOCP модель.

Vol4ok пишет:
так как важна очередность пакетов

В таком случае ты выбрал не тот протокол. UDP не гарантирует сохранение порядка доставки пакетов. Используй TCP или делай свой протокол нечувствительным к порядку доставки. Конечно можно отправлять пакеты строго последовательно, и надеяться что сетевое оборудование не изменит их порядок, но хорошей производительности не добьешся даже в kernel mode, т.к. сетевая карта наиболее эффективно отсылает пакеты пулом из нескольких сотен штук.

-----
PGP key <0x1B6A24550F33E44A>




Ранг: 47.1 (посетитель), 2thx
Активность: 0.030
Статус: Участник

Создано: 29 января 2010 19:15 · Поправил: Vol4ok
· Личное сообщение · #9

ntldr пишет:
Никогда не используй блокирующие сокеты одновременно в двух тредах, ибо вызванная одним тредом операция будет блокировать другие. Используй select и делай всё в одном потоке, или переходи на IOCP модель.

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

ntldr пишет:
В таком случае ты выбрал не тот протокол. UDP не гарантирует сохранение порядка доставки пакетов. Используй TCP или делай свой протокол нечувствительным к порядку доставки.

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

ntldr пишет:
Конечно можно отправлять пакеты строго последовательно, и надеяться что сетевое оборудование не изменит их порядок, но хорошей производительности не добьешся даже в kernel mode, т.к. сетевая карта наиболее эффективно отсылает пакеты пулом из нескольких сотен штук.

Именно такая модель была бы эффективнее всего, если была возможность отправлять сразу пул пакетов и как раз по несколько сотен штук, но пока я не вижу как это можно было бы реализовать в юзер моде с помощью имеющегося АПИ.



Ранг: 237.0 (наставник), 20thx
Активность: 0.130
Статус: Участник
sysenter

Создано: 29 января 2010 19:22
· Личное сообщение · #10

Vol4ok пишет:
ь в юзер моде с помощью имеющегося АПИ

можно собирать пакеты и пулы в raw моде

-----
продавец резиновых утёнков




Ранг: 369.8 (мудрец), 400thx
Активность: 0.390
Статус: Участник

Создано: 29 января 2010 19:22
· Личное сообщение · #11

Vol4ok пишет:
изменение порядка доставки на практике я не встречал

Это так, если дело касается локалки с простой топологией (без хитровыебанных маршрутизаторов), а в интернете может что угодно твориться. Если в RFC написано, что порядок доставки не гарантируется, то следует считать, что он может быть произвольным, хотя это уже претензии к разработчикам протокола.

Vol4ok пишет:
Именно такая модель была бы эффективнее всего, если была возможность отправлять сразу пул пакетов и как раз по несколько сотен штук, но пока я не вижу как это можно было бы реализовать в юзер моде с помощью имеющегося АПИ.

TransmitPackets или IOCP. IOCP прекрасно подходит везде, где нужна производительность. Если тебе не нужно поддерживать чужой ректально-ориентированный код, то используй IOCP.

-----
PGP key <0x1B6A24550F33E44A>




Ранг: 47.1 (посетитель), 2thx
Активность: 0.030
Статус: Участник

Создано: 01 февраля 2010 17:50
· Личное сообщение · #12

ntldr
спасибо, TransmitPackets - это то что мне было нужно, была достигнута загрузка сети на отправку - 94% от гигабита, при загрузке проца 20-30%, причем большинство процессорного времени уходило на генерацию трафика, отправка потребляет очень мало, что не может не радовать

Закрыто.


 eXeL@B —› Программирование —› Высокоскоростной UDP-генератор
Эта тема закрыта. Ответы больше не принимаются.
   Для печати Для печати