Performance of QUdpSocket writeDatagram between Qt4 and Qt5 in different GNU/Linux platforms
-
Hello,
I am facing an unusual behaviour related to the performance of the method writeDatagram of QUdpSocket using two different version of QT ( Qt4.8.5 vs Qt5.1.1).
I tested the same program both on Ubuntu between 4.8.1 and 5.0 and the results are fine.
While on an emDebian arm platform, Qt5.1.1 performs much worse than Qt4.8.5 (two order of magnitude times slower).Basically, my application is just calling writeDatagram in a for loop and returns the average time writeDatagram calls.
The results after 10000 calls, sending 19bytes of payload are:
Qt 4.8.5 avg 0.000224s each call
Qt 5.1.1 avg 0.033..s (about 30ms each message).I checked in Wireshark and I am able to receive the messages in both cases.
Moreover, I tested vanilla c socket and they perform as good as qt 4.8.5.
I wonder how it is possible, and if you have any suggestion in merit.
I looked a bit in the qt code and saw a bind() inside the QT5 writeDatagram method, which I do not immediately understand but I do not know if might cause the issue.
Should I specify something more in the initialization of the QUdpSocket? Are there any pauses, wait or blocking mechanisms?
Might my ethernet interface configuration be wrong? How should I adjust it in that case?Regards,
Below is my code:
//Util.h
#pragma once
#ifdef linux
#include <time.h>
#else
#define NOMINMAX
#include <windows.h>
#include <time.h>
#endifclass Util
{
public:
inline static float GetTimeSeconds(void)
{
#ifdef linux
static bool initialized = false;
static struct timespec offsetTime;
struct timespec startTime;
clock_gettime( CLOCK_MONOTONIC, &startTime);
if (!initialized)
{
offsetTime.tv_sec = startTime.tv_sec;
offsetTime.tv_nsec = startTime.tv_nsec;
initialized = true;
}
return static_cast<float>( (startTime.tv_sec - offsetTime.tv_sec) + (startTime.tv_nsec - offsetTime.tv_nsec)/1.0e9);
#else
return static_cast<float>(clock())/ static_cast<float>(CLOCKS_PER_SEC);
#endif
}
};//Task.h
#pragma once
#include <QtCore>
#include <QtNetwork>
#include <QUdpSocket>
#include "Util.h"class Task : public QObject
{
Q_OBJECT
public:
Task(QObject *parent = 0) : QObject(parent) {}public slots:
void run()
{
// Do processing here
unsigned int messageNo = 0;
QUdpSocket *udpSocket;
udpSocket = new QUdpSocket(this);
int times = 10000;
QByteArray datagram = "Broadcast message " + QByteArray::number(messageNo);
const double t1 = Util::GetTimeSeconds();
for (int i = 0; i<times; i++)
{
udpSocket->writeDatagram(datagram.data(), datagram.size(), QHostAddress::Broadcast, 45454);
}
const double t2 = Util::GetTimeSeconds();
qDebug(" writeDatagram(): %f s, total %f", (t2 - t1)/times, (t2 - t1));//dt
++messageNo;
emit finished();
delete udpSocket;
}signals:
void finished();
};// main.cpp
#include "Task.h"
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
Task *task = new Task(&a);
QObject::connect(task, SIGNAL(finished()), &a, SLOT(quit()));
QTimer::singleShot(0, task, SLOT(run()));
return a.exec();
} -
Hi and thank you for that analysis. I think people on the development "mailing list":http://lists.qt-project.org/mailman/listinfo might be more interested (that is where hardcore Qt devs are; this forum focuses on users of Qt).
-
Thank you sierdzio.
I will repost it there. -
Nice to see the amount of interest your post is getting. If you are lucky, the bug will be fixed soon.
For future reference: "here":https://bugreports.qt-project.org/browse/QTBUG-37092 is the bug report.
-
I can confirm that this problem exists running bsquask (Qt specific embedded/cross compiler for the RPi)
I've completely lost track of where this problem is being pursued so it may be fixed by now.
Someone suggested that it may be a re-bind issue. I can confirm that binding to a local device address (not localhost) before using the socket seems to fix it.
-
Hi,
I am still interesting in solving the issue in my code.
To overcome that problem I have just used C raw socket but it is not an elegant solution.I did not understand completely what you mean when you are writing about binding to another local address.
Do you mean I should call twice the function bind with different parameters or just once with the local address one?
I use the following syntax:
QUdpSocket* myUdpSocket = new QUdpSocket(this);
myUdpSocket->bind(QHostAddress(QHostAddress::Any), (quint16)0)Should I replace the QHostAddress::Any with my address like 192.168.1.x
I also do not get why if it is a binding issue it affects the sending (UDP) and not the receiving part.
-
My code reads
QUdpSocket* myUdpSocket = new QUdpSocket(this);
myUdpSocket->bind(QHostAddress("192.168.0.31"), 3000);then
while(true)
writeDatagram(etc..192.168.0.31 is the address of my NIC, 3000 is the remote receipt port which is probably irrelevant.
Without bind() writeDatagram takes 25mS, with bind() the delay is nominal.
I don't understand the sending thing either, but hey, it's a bug.