Russian Qt Forum

Qt => Работа с сетью => Тема начата: Gabriel.vs от Апрель 11, 2011, 16:25



Название: Qt sockets vs Native sockets (speed comparison)
Отправлено: Gabriel.vs от Апрель 11, 2011, 16:25
Имеется некое приложение для обмена данными, в условиях "постоянной актуальности" этих данных. В связи с этим вытекает необходимость максимальной скорости передачи информации по сети.

Написал для начала простое тестовое приложение на Qt (используя QTcpSocket/QTcpServer) и Visual Studio (используя Native Sockets). Оба приложения протестировал на скорость передачи 10 млн. пакетов данных по 64 байт каждый. Результат показался весьма странным - приложение на Qt работало в 3 раза медленнее. Приложение на VS справилось с этой задачей за 7 минут 40 секунд. Приложение на Qt справилось с этой задачей за 28 минут 23 секунды.

Исходный код реализации на Qt:

server.h    : http://goo.gl/ohCWx
server.cpp : http://goo.gl/jjfza

client.h    : http://goo.gl/DtgE9
client.cpp : http://goo.gl/ZeTx9

Исходный код реализации в VS:

server.cpp : http://goo.gl/2sUh4
client.cpp  : http://goo.gl/Sk7ce

Примечание: реализацию на Qt так же переписывал со слот/сигнального механизма в обычный обработчик в лупе - результат был тот же.

Вопрос: задавался ли кто-то ещё вопросом о скорости работы сетевых интерфейсов в Qt? Можно ли добиться нормальной скорости работы?


Название: Re: Qt sockets vs Native sockets (speed comparison)
Отправлено: mutineer от Апрель 11, 2011, 16:39
[оффтоп] ну нельзя делать moveToThread(this); ибо не то он делает, что ты думаешь [//оффтоп]


Название: Re: Qt sockets vs Native sockets (speed comparison)
Отправлено: Авварон от Апрель 11, 2011, 16:51
вы можете убрать сокеты вообще и оставить только отладочную печать - вообще удивлены будете.
Пример - парсинг хмл (10мб) без печати - 1,5 сек. С печатью - несколько минут (больше минуты не ждал, лениво)


Название: Re: Qt sockets vs Native sockets (speed comparison)
Отправлено: Пантер от Апрель 11, 2011, 16:54
qDebug синканый. Лучше заюзай std::cout, причем вместо std::endl используй "\n". И результаты сюда закинь.


Название: Re: Qt sockets vs Native sockets (speed comparison)
Отправлено: Gabriel.vs от Апрель 11, 2011, 17:30
Заменил qDebug( ) на std::cout, std::endl на "\n", сократил вывод дебажной информации в 10 раз (во время обмена трафика), поправил moveToThread( ).

Результат: скорость выполнения осталась такая же.

Any other advises?


Название: Re: Qt sockets vs Native sockets (speed comparison)
Отправлено: Igors от Апрель 11, 2011, 18:06
Any other advises?
What kind of advice do you expect?  :)

Прикинем варианты:

1) да, Qt действительно (здесь) медленнее. А кому понравится это говорить? Ведь столько времени было потрачено на чтение Assistant, а теперь "какой-то чувак" говорит что "медленно" ??? Несомненно это проблемы того чувака и.т.п. (не учить же мне др. фреймворк)

2) разобраться почему. Ну это непросто и небыстро. А главное - зачем? Подавляющее большинство - студенты, которые от вопросов производительности далеки как Земля от Марса. Что-то делает - и ладно, курсовой сдан. 

Так что доводите дело до конца и докапывайтесь в чем причина  :)


Название: Re: Qt sockets vs Native sockets (speed comparison)
Отправлено: SABROG от Апрель 11, 2011, 18:09
Автор, выложи хотябы исходные коды в виде архива, чтобы другие люди могли поэкспериментировать.

Еще предлагаю провести эксперимент типа: Клиент Qt <-> Server Native, Client Native <-> Server Qt.


Название: Re: Qt sockets vs Native sockets (speed comparison)
Отправлено: Авварон от Апрель 11, 2011, 18:24
поглядел мельком в сорцы, в принципе там особо нечему тормозить - есть лишь несколько уровней абстракции, но в итоге все сводится к нативным вызовам (те на каждый рид идет натив рид). Конечно там могут быть хитрые буферизации, но по логике ф-ий должно быть так. Собственно абстракция тормозить не может, могут тормозить разные проверки - вы уверены что в вашем коде их не будет?
Насчет того, что при убирании дебагов скорость осталась прежней - "а кто такой станиславский?" (с)


Название: Re: Qt sockets vs Native sockets (speed comparison)
Отправлено: SABROG от Апрель 11, 2011, 18:45
Тут, имхо, достаточно самонадеянно читать конкретное количество данных из буффера сокета в то время как их там может быть либо меньше, либо гораздо больше. При переполнении буффера возможно выделение дополнительной памяти либо самой Qt, либо ОС, что может приводить к тормозам...

Код
C++ (Qt)
void Q_Client::NewData(void)
{
   qm_sock->read(buffer,size);
   if (current < maxAttemprs)
   {
       qm_sock->write(forSend,size);
   }
 

Если я правильно посчитал, то общий объем передаваемых данных 610Мб. Как фильм. Тогда скорость для нативных сокетов составила 1,37Мб/с. Что очень мало для сокетов созданных на локалхосте. У меня даже торренты в среднем со скоростью 6Мб/с с инета льются.


Название: Re: Qt sockets vs Native sockets (speed comparison)
Отправлено: Gabriel.vs от Апрель 12, 2011, 09:34
 1. Вызывая метод “read( )” класса QTcpSocket, производится много проверок, цель которых – контроль доступа к сокету на чтение/запись и другие атрибуты. Так же идёт сопоставление аргумента size, переданного в “read( )” с возвращаемым значением функции bytesAvailable( ) и другие семимильные проверки, которые можно посмотреть в qiodevise.h/cpp, qtcpsocket.h/cpp. Так что переполнение тут маловероятно. При том что у Qt сокетов свой механизм пулов (см. Qt исходники).

 2. Сравнивать данный поток трафика с трафиком торрента весьма опрометчиво (см. спецификацию bitTorrent). Торрент трафик основан на p2p архитектуре и UDP протоколе (в противовес TCP, который в моём приложении). Весь контент, который скачивается в торренте, режется кусками (много больше чем мои 64-битные данные). Машине гораздо менее затратнее обработать небольшое количество пакетов большого размера (главное что бы под MTU влезали; что бы не было фрагментации), чем огромного числа пакетов малого размера.

 3. Тестировать QtClient < - > NativeServer и т.д. пробовал. Скорость возрастала. Но это не вариант. Необходимо оптимизировать Qt реализацию. Возможно есть какие-то интерфейсы с минимальными проверками, которые в меньшей степени затрагивают производительность.

Есть какие-то соображения по теме топика?


Название: Re: Qt sockets vs Native sockets (speed comparison)
Отправлено: mutineer от Апрель 12, 2011, 09:39
[оффтоп] а откуда тайные сведения про UDP в торренте? [/оффтоп]


Название: Re: Qt sockets vs Native sockets (speed comparison)
Отправлено: Gabriel.vs от Апрель 12, 2011, 09:58
[оффтоп] а откуда тайные сведения про UDP в торренте? [/оффтоп]

http://ru.wikipedia.org/wiki/BitTorrent

+ немного логики и всё станет ясно - без UDP было бы сложно осуществлять обмен данными с теми, кто за NAT'ом.

PS. Сорри, но хочется я увидеть ответы по теме. Если есть вопросы не по теме - пишите в личку. В оффтоп отвечать больше не буду.


Название: Re: Qt sockets vs Native sockets (speed comparison)
Отправлено: SABROG от Апрель 12, 2011, 10:20
Так что переполнение тут маловероятно. При том что у Qt сокетов свой механизм пулов (см. Qt исходники).
Насчет проверок я не сомневаюсь. Если бы их небыло, то программа бы падала. Тут вопрос в другом. Вы уверены, что после того как прочитали size байт буффер опустошился?

2. Сравнивать данный поток трафика с трафиком торрента весьма опрометчиво
Насчет размера порции данных я соглашусь. Если поток идет непрерывно, то и скорость должна быть побольше. Однако если бы дело было только в использовании TCP или UDP, то я бы не получал скорость 12Мб/с в DirectConnect (StrongDC++) клиенте, где UDP используется только для поиска и передачи протокольных опкодов.

Скорость возрастала. Но это не вариант. Необходимо оптимизировать Qt реализацию. Возможно есть какие-то интерфейсы с минимальными проверками, которые в меньшей степени затрагивают производительность.
Я не предлагал использовать такую связку "как вариант". Я лишь предложил провести такую проверку, чтобы понять какая часть (клиент или сервер) является узким местом. Может быть проблема не в самом QTcpSocket.

Есть какие-то соображения по теме топика?
Чтобы они появились нужны исходные коды, которые можно будет собрать не занимаясь копи-пастингом из html сервисов для подсветки синтаксиса, т.к. судя по всему они "замусоривают" код экранирующими символами.

Код:
if(connect(sock,(struct sockaddr*)&sockaddr;,sizeof(sockaddr))<0)
...
 if (bind(srv,(const sockaddr*)&srv;_addr,sizeof(srv_addr)) < 0 )
...
  client = accept(srv, (struct sockaddr*)&client;_addr,&clientLen;);


Название: Re: Qt sockets vs Native sockets (speed comparison)
Отправлено: Gabriel.vs от Апрель 12, 2011, 10:52
Насчет проверок я не сомневаюсь. Если бы их небыло, то программа бы падала. Тут вопрос в другом. Вы уверены, что после того как прочитали size байт буффер опустошился?
На 100 % уверенным быть нельзя нигде. Но Qt гарантирует что при успешном завершении чтения/посылки порции данных, указанных в size, pool уничтожается.

Исходный код приатачил.


Название: Re: Qt sockets vs Native sockets (speed comparison)
Отправлено: Sanya от Апрель 12, 2011, 11:12
<оффтоп>
   Холливар какой-то, Господа!
   Думаю, тема достаточно серьезная, поэтому предлагаю не уходить в дебри torrent протокола, а разобраться. Думаю мы здесь не ради студиков, а ради Qt. Данный фреймверк лично мне очень нравится, и, хочется верить, что можно его заставить работать гораздо быстрее.
</оффтоп>

Кто знает как отсылаются TCP пакеты в Qt? Через event loop или же экземпляр класса QTcpSocket сам добирается до API функций конкретной платформы и шлет сам?


Название: Re: Qt sockets vs Native sockets (speed comparison)
Отправлено: mutineer от Апрель 12, 2011, 11:31
Если выполнять flush(), то добирается тут же до АПИ и отправляет. Если не выполнять, то через очередь сообщений система выполняет ему flush() когда считает нужным


Название: Re: Qt sockets vs Native sockets (speed comparison)
Отправлено: kuzulis от Апрель 12, 2011, 12:56
Если выполнять flush(), то добирается тут же до АПИ и отправляет. Если не выполнять, то через очередь сообщений система выполняет ему flush() когда считает нужным
Или же в режиме Unbuffered оно без очереди сообщений сразу через АПИ шлет.


Название: Re: Qt sockets vs Native sockets (speed comparison)
Отправлено: SABROG от Апрель 12, 2011, 13:54
Пересобрал MSVCшные нативные сокеты с помощью MinGW, чтобы исключить разницу в оптимизации компиляторов. В итоге все приложения собраны с помощью g++ 4.4.0. Закомментировал отключение алгоритма Nagle, т.к. в нативном примере их отключения нет. Пока результаты такие.

Код:
MinGW Native:
Duration is: 4 min
CPU Load: 36% (18% client, 18% server)

Qt:
Duration is: 28 min
CPU Load: 60% (30% client, 30% server)

Qt Client <-> Server Native:
Duration is: 17 min
CPU Load: 55% (50% Client, 5% server)

Qt Server <-> Client Native:
Duration is: 14 min
CPU Load: 55% (10% Client, 45% Server)

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


Название: Re: Qt sockets vs Native sockets (speed comparison)
Отправлено: Gabriel.vs от Апрель 12, 2011, 14:04
Если выполнять flush(), то добирается тут же до АПИ и отправляет. Если не выполнять, то через очередь сообщений система выполняет ему flush() когда считает нужным

Сделал, время сократилось на 3 минуты 30 секунд.


Название: Re: Qt sockets vs Native sockets (speed comparison)
Отправлено: mutineer от Апрель 12, 2011, 14:05
Пересобрал MSVCшные нативные сокеты с помощью MinGW, чтобы исключить...

Оно запустилось? У меня Qt-шный клиент при запуске выдает
Цитировать
QSocketNotifier: socket notifiers cannot be enabled from another thread
Ну и естественно никуда не подключается


Название: Re: Qt sockets vs Native sockets (speed comparison)
Отправлено: Gabriel.vs от Апрель 12, 2011, 15:01
Написал свои обработчики write( ) и read( ). Внутри них посылка данных идёт через getChar( ) и putChar( ). Выполняться стало ещё быстрее, на пару минут.


Название: Re: Qt sockets vs Native sockets (speed comparison)
Отправлено: SABROG от Апрель 13, 2011, 00:05
Написал свою реализацию клиента на Qt. Сервер взял нативный подправленный для MinGW.

Результат 2 минуты. Это где-то 5Мб/с.

Завтра попробую написать свою версию сервера на Qt.
---
До написания сервера не дошли руки, много работы.


Название: Re: Qt sockets vs Native sockets (speed comparison)
Отправлено: SABROG от Апрель 15, 2011, 22:57
Дописал сервер. Теперь одно приложение можно запускать как клиент так и сервером. Причем если дефолтный порт свободен, то приложение запускается как сервер, если занят, то как клиент. Таким образом для теста нужно просто два раза запустить одну и ту же программу.

Новый результат: 30 секунд. Т.е. около 20Мб/с.