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

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

Страниц: [1] 2   Вниз
  Печать  
Автор Тема: Qt sockets vs Native sockets (speed comparison)  (Прочитано 15267 раз)
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? Можно ли добиться нормальной скорости работы?
Записан
mutineer
Гость
« Ответ #1 : Апрель 11, 2011, 16:39 »

[оффтоп] ну нельзя делать moveToThread(this); ибо не то он делает, что ты думаешь [//оффтоп]
Записан
Авварон
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3260


Просмотр профиля
« Ответ #2 : Апрель 11, 2011, 16:51 »

вы можете убрать сокеты вообще и оставить только отладочную печать - вообще удивлены будете.
Пример - парсинг хмл (10мб) без печати - 1,5 сек. С печатью - несколько минут (больше минуты не ждал, лениво)
Записан
Пантер
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 5876


Жаждущий знаний


Просмотр профиля WWW
« Ответ #3 : Апрель 11, 2011, 16:54 »

qDebug синканый. Лучше заюзай std::cout, причем вместо std::endl используй "\n". И результаты сюда закинь.
Записан

1. Qt - Qt Development Frameworks; QT - QuickTime
2. Не используйте в исходниках символы кириллицы!!!
3. Пользуйтесь тегом code при оформлении сообщений.
Gabriel.vs
Гость
« Ответ #4 : Апрель 11, 2011, 17:30 »

Заменил qDebug( ) на std::cout, std::endl на "\n", сократил вывод дебажной информации в 10 раз (во время обмена трафика), поправил moveToThread( ).

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

Any other advises?
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #5 : Апрель 11, 2011, 18:06 »

Any other advises?
What kind of advice do you expect?  Улыбающийся

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

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

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

Так что доводите дело до конца и докапывайтесь в чем причина  Улыбающийся
Записан
SABROG
Гость
« Ответ #6 : Апрель 11, 2011, 18:09 »

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

Еще предлагаю провести эксперимент типа: Клиент Qt <-> Server Native, Client Native <-> Server Qt.
« Последнее редактирование: Апрель 11, 2011, 18:14 от SABROG » Записан
Авварон
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3260


Просмотр профиля
« Ответ #7 : Апрель 11, 2011, 18:24 »

поглядел мельком в сорцы, в принципе там особо нечему тормозить - есть лишь несколько уровней абстракции, но в итоге все сводится к нативным вызовам (те на каждый рид идет натив рид). Конечно там могут быть хитрые буферизации, но по логике ф-ий должно быть так. Собственно абстракция тормозить не может, могут тормозить разные проверки - вы уверены что в вашем коде их не будет?
Насчет того, что при убирании дебагов скорость осталась прежней - "а кто такой станиславский?" (с)
Записан
SABROG
Гость
« Ответ #8 : Апрель 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Мб/с с инета льются.
« Последнее редактирование: Апрель 11, 2011, 21:09 от SABROG » Записан
Gabriel.vs
Гость
« Ответ #9 : Апрель 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 реализацию. Возможно есть какие-то интерфейсы с минимальными проверками, которые в меньшей степени затрагивают производительность.

Есть какие-то соображения по теме топика?
Записан
mutineer
Гость
« Ответ #10 : Апрель 12, 2011, 09:39 »

[оффтоп] а откуда тайные сведения про UDP в торренте? [/оффтоп]
Записан
Gabriel.vs
Гость
« Ответ #11 : Апрель 12, 2011, 09:58 »

[оффтоп] а откуда тайные сведения про UDP в торренте? [/оффтоп]

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

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

PS. Сорри, но хочется я увидеть ответы по теме. Если есть вопросы не по теме - пишите в личку. В оффтоп отвечать больше не буду.
Записан
SABROG
Гость
« Ответ #12 : Апрель 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;);
Записан
Gabriel.vs
Гость
« Ответ #13 : Апрель 12, 2011, 10:52 »

Насчет проверок я не сомневаюсь. Если бы их небыло, то программа бы падала. Тут вопрос в другом. Вы уверены, что после того как прочитали size байт буффер опустошился?
На 100 % уверенным быть нельзя нигде. Но Qt гарантирует что при успешном завершении чтения/посылки порции данных, указанных в size, pool уничтожается.

Исходный код приатачил.
Записан
Sanya
Гость
« Ответ #14 : Апрель 12, 2011, 11:12 »

<оффтоп>
   Холливар какой-то, Господа!
   Думаю, тема достаточно серьезная, поэтому предлагаю не уходить в дебри torrent протокола, а разобраться. Думаю мы здесь не ради студиков, а ради Qt. Данный фреймверк лично мне очень нравится, и, хочется верить, что можно его заставить работать гораздо быстрее.
</оффтоп>

Кто знает как отсылаются TCP пакеты в Qt? Через event loop или же экземпляр класса QTcpSocket сам добирается до API функций конкретной платформы и шлет сам?
Записан
Страниц: [1] 2   Вверх
  Печать  
 
Перейти в:  


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