Russian Qt Forum
Май 19, 2024, 13:19 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1] 2   Вниз
  Печать  
Автор Тема: QUdpSocket + пакеты большого размера.  (Прочитано 10780 раз)
eugene.n
Гость
« : Апрель 28, 2014, 15:23 »

Есть сеть 10 Гбит/с (комп-комп). Nuttcp показывает максимальную скорость 1 Гбит/с при пакетах размером 1000 байт. При паккетах 8000 байт - скорость 6-7 Гбит/с. В настройках сетевой карты включена функция jumboframe (разрешено отправлять пакеты большого размера (<9000) без фрагментации IP-пакета).



C:\>ping 192.168.13.1 -f -l 8000

Обмен пакетами с 192.168.13.1 по с 8000 байтами данных:
Ответ от 192.168.13.1: число байт=8000 время<1мс TTL=128
Ответ от 192.168.13.1: число байт=8000 время<1мс TTL=128
Ответ от 192.168.13.1: число байт=8000 время<1мс TTL=128
Ответ от 192.168.13.1: число байт=8000 время<1мс TTL=128

Статистика Ping для 192.168.13.1:
    Пакетов: отправлено = 4, получено = 4, потеряно = 0
    (0% потерь)
Приблизительное время приема-передачи в мс:
    Минимальное = 0мсек, Максимальное = 0 мсек, Среднее = 0 мсек



Видно что IP-пакеты не фрагментированы. То есть, тратиться время на фрагментацию не должно.

Пробуем послать пакеты такого же размера с помощью QUdpSocket.

Код:
QByteArray packet;
QUdpSocket *udpSocket = new QUdpSocket(this);
while(udpSocket->writeDatagram(packet.data(), packet.size(), QHostAddress("192.168.13.1"), 3333) == -1);

При размере пакета 1000 байт получаем скорость 1 Гбит, но при размере пакета 8000 байт - скорость падает до 300 Мбит/с.

В описании функции writeDatagram() говорится, что пакеты по 8000 байт шлются без проблем, нужно лишь убедиться в том, что не будут фрагментированы ip-пакеты.

Так в чем же проблема? Почему writeDatagram() работает так медленно с большими пакетами или почему я не могу достичь скорости хотя бы 6 Гб/с (даже при пакетах маленького размера)?
« Последнее редактирование: Апрель 29, 2014, 10:25 от eugene.n » Записан
LisandreL
Птица говорун
*****
Offline Offline

Сообщений: 984


Надо улыбаться


Просмотр профиля
« Ответ #1 : Апрель 28, 2014, 23:01 »

Цитировать
QByteArray packet;
QUdpSocket *udpSocket = new QUdpSocket(this);
while(udpSocket->writeDatagram(packet.data(), packet.size(), QHostAddress("192.168.13.1"), 3333) == -1);
Может побольше кусок кода дадите?
В принципе вполне возможно, что из цикла вываливаетесь и что дальше происходит - не понятно.
Ну и кроме QHostAddress("192.168.13.1") - заменить на константу / переменную. Иначе каждый раз разбор адреса происходит из сторки.
А packet.data() => packet.constData() - так быстрее. Или вообще в пользу массива char посмотреть.
В общем советую по профилировать - совсем не факт, что тормозит именно сокет.

P.S. Может быть стоит вызывать waitForBytesWritten, а может наоборот хуже сделает, не знаю.
Записан
eugene.n
Гость
« Ответ #2 : Апрель 29, 2014, 08:58 »

А packet.data() => packet.constData() - так быстрее. Или вообще в пользу массива char посмотреть.

Не помогло Грустный

Код:

int packetCnt = 100000;  // кол-во пакетов
QByteArray packet;       // пакет каких-то данных
quint64 byteCnt = 0;     // кол-во переданных байт
QUdpSocket *udpSocket = new QUdpSocket(this);    // сокет UDP
QHostAddress host = QHostAddress("192.168.13.1");
int port = 3333;

packet.resize(8000);      // размер пакета 8000 байт

quint64 t0 = curTime.elapsed();
for(int i = 0; i < packetCnt; i++) {

    while(udpSocket->writeDatagram(packet.constData(), packet.size(), host, port) == -1);    // пытаемся отправить данные, пока не удастся
    
    byteCnt += packet.size();
    quint64 t1 = curTime.elapsed();
    if(t1 >= t0 + 1000) {          
        std::cout << "Передано " << byteCnt << " за 1 с." << std::endl;    // если прошла 1 секунда - выводим кол-во переданных байт
        byteCnt = 0;
        t0 = curTime.elapsed();
    }
}


Дело в том, что на пакетах маленького размера (1000-2000 байт) программа показывает скорость чуть больше 1 Гб/с, а на больших пакетах (5000 - 8000) скорость падает. в 3 -4 раза (Сторонние программы показывают пропускную способность канала до 7 - 7,5 Гб/с).

P.S. Может быть стоит вызывать waitForBytesWritten, а может наоборот хуже сделает, не знаю.
Кажется, это работает на сокетах с соединением. У меня без соединения.

« Последнее редактирование: Апрель 29, 2014, 09:39 от eugene.n » Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4349



Просмотр профиля
« Ответ #3 : Апрель 29, 2014, 09:02 »

Посмотрите снифером, что реально отправляется в каждом из случаев.
Записан
eugene.n
Гость
« Ответ #4 : Апрель 29, 2014, 09:10 »

Посмотрите снифером, что реально отправляется в каждом из случаев.

Смотрел wireshark'ом. Всё ок. Пакеты не фрагментированы и данные целые (и со стороны клиента и со стороны сервера).
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4349



Просмотр профиля
« Ответ #5 : Апрель 29, 2014, 09:14 »

Смотрел wireshark'ом. Всё ок. Пакеты не фрагментированы и данные целые (и со стороны клиента и со стороны сервера).
Хм, чудеса. Попробуйте сокету делать flush.
Записан
eugene.n
Гость
« Ответ #6 : Апрель 29, 2014, 09:18 »

Смотрел wireshark'ом. Всё ок. Пакеты не фрагментированы и данные целые (и со стороны клиента и со стороны сервера).
Хм, чудеса. Попробуйте сокету делать flush.

Тот же результат Грустный
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4349



Просмотр профиля
« Ответ #7 : Апрель 29, 2014, 09:35 »

Посмотрел исходники, каких то тяжёлый операций не нашел, быстренько вызывается sendto.  Непонимающий
Странно.
Записан
LisandreL
Птица говорун
*****
Offline Offline

Сообщений: 984


Надо улыбаться


Просмотр профиля
« Ответ #8 : Апрель 29, 2014, 09:36 »

Код:
    quint64 t1 = curTime.elapsed();
    if(t1 >= t0 + 1000) {          
        std::cout << "Передано " << byteCnt << " за 1 с." << std::endl;    // если прошла 1 секунда - выводим кол-во переданных байт
        byteCnt = 0;
    }
Вы тут t0 = t1; не потеряли? А то, насколько я понимаю код, после 1 секунды лог будет выводиться на каждой итерациии, что вполне может тормозить передачу.
Записан
eugene.n
Гость
« Ответ #9 : Апрель 29, 2014, 09:40 »

Код:
    quint64 t1 = curTime.elapsed();
    if(t1 >= t0 + 1000) {          
        std::cout << "Передано " << byteCnt << " за 1 с." << std::endl;    // если прошла 1 секунда - выводим кол-во переданных байт
        byteCnt = 0;
    }
Вы тут t0 = t1; не потеряли? А то, насколько я понимаю код, после 1 секунды лог будет выводиться на каждой итерациии, что вполне может тормозить передачу.

Да, потерял. Спасибо. Исправил. Но не в этом дело)
Записан
eugene.n
Гость
« Ответ #10 : Апрель 29, 2014, 10:23 »

Немного переформулировал вопрос. Почему я не могу достичь скорости хотя бы 6 Гб/с?   Непонимающий Непонимающий Непонимающий
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4349



Просмотр профиля
« Ответ #11 : Апрель 29, 2014, 10:29 »

Немного переформулировал вопрос. Почему я не могу достичь скорости хотя бы 6 Гб/с?   Непонимающий Непонимающий Непонимающий
Стоп. Я думал у вас есть программа, которая умеет отправлять датаграммы быстрее, чем такая же на Qt и вы хотите разобраться почему. Или вы просто предполагали, что с увеличением размера данных возрастет и скорость?
Записан
eugene.n
Гость
« Ответ #12 : Апрель 29, 2014, 10:34 »

Немного переформулировал вопрос. Почему я не могу достичь скорости хотя бы 6 Гб/с?   Непонимающий Непонимающий Непонимающий
Стоп. Я думал у вас есть программа, которая умеет отправлять датаграммы быстрее, чем такая же на Qt и вы хотите разобраться почему. Или вы просто предполагали, что с увеличением размера данных возрастет и скорость?

Да, есть. В первом посте я писал что тестировал сеть с помощью nuttcp и получил скорость 1 Гб при пакетах ~1000Б. У моей программы выходит такая же скорость. У nuttcp при размере пакетов 8000Б получается скорость 6-7 Гб/с, а у моей программы она получается даже ниже чем 1 Гб/с при таких пакетах (8000Б).

А с увеличением размера пакетов скорость растет так как 10 Гбитная сетевая карточка лучше справляется с отправкой больших сегментов, нежели маленьких (при которых она сильно грузится).
« Последнее редактирование: Апрель 29, 2014, 10:52 от eugene.n » Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4349



Просмотр профиля
« Ответ #13 : Апрель 29, 2014, 10:57 »

Попробуйте посмотреть с помощью strace , как отправляет и как настраивает сокет nuttcp.
А потом сравните со своей, может что-то прояснимся.
Может они срочные сообщения отправляют или открывают сокет в неблокирующем режиме?
Записан
Bepec
Гость
« Ответ #14 : Апрель 29, 2014, 11:46 »

Или расширяют буфер на принимающей стороне...
Записан
Страниц: [1] 2   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.05 секунд. Запросов: 20.