Название: 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, либо ОС, что может приводить к тормозам...
Код
Если я правильно посчитал, то общий объем передаваемых данных 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) Название: 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: Кстати алгоритм выбран неудачно, т.к. скорость скачивания и загрузки падает до минимального значения. Думаю надо переписать клиент и сервер, чтобы они не слали данные в виде ответа на полученные данные от клиента. Название: 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Мб/с. |