I have a task of processing UDP data with ~10kHz read rate. I'm working with Qt 5.13.1 (MinGW32), so I tried to use a QUdpSocket
.
I made a simple test program, but the results are a bit frustrating. The readyRead()
signal is just too slow. For some reason I'm getting delays over 1 or 2 ms every 2-4 signals.
I made a simple packet counter and compare it with what I see in wireshark. Sure enough there is a packet loss.
What can I do to enhance perfomance? Or maybe it's just the limit of the Qt event loop?
I run it with Qt Creator 4.10.0. On Windows 7.
Update: With your advices: I tried:
Moving socket in different thread. This gives a bit more perfomance .. a very bit
LowDelayOption = 1 - I did not notice any changes
ReceiveBufferSizeSocketOption - I did not notice any changes
- No usage of QDebug while reading - I did not check it, just use for collecting statistics
udpproc.h
#ifndef UDPPROC_H
#define UDPPROC_H
#include "QObject"
#include "QUdpSocket"
#include "QHostAddress"
#include "QThread"
#include "QDebug"
#include "networker.h"
class UDPProc : public QObject
{
Q_OBJECT
public:
UDPProc();
~UDPProc();
private:
QUdpSocket dataServerSocket;
NetWorker* netWorker;
QThread netThread;
};
#endif // UDPPROC_H
udpproc.cpp
UDPProc::UDPProc() {
netWorker = new NetWorker(&dataServerSocket);
netWorker->moveToThread(&netThread);
netWorker->getInnerLoop()->moveToThread(&netThread);
connect(&netThread, SIGNAL(started()), netWorker, SLOT(serverSocketProccessing()));
connect(&this->dataServerSocket, SIGNAL(readyRead()), netWorker->getInnerLoop(), SLOT(quit()));
QString address = "127.0.0.3:16402";
QHostAddress ip(address.split(":").at(0));
quint16 port = address.split(":").at(1).toUShort();
dataServerSocket.bind(ip, port);
//dataServerSocket.setSocketOption(QAbstractSocket::LowDelayOption, 1);
dataServerSocket.moveToThread(&netThread);
netThread.start();
//dataServerSocket.setSocketOption(QAbstractSocket::ReceiveBufferSizeSocketOption, 128000);
//qDebug()<<dataServerSocket.socketOption(QAbstractSocket::ReceiveBufferSizeSocketOption).toInt();
}
networker.h
#ifndef NETWORKER_H
#define NETWORKER_H
#include <QObject>
#include "QElapsedTimer"
#include "QEventLoop"
#include "QUdpSocket"
#include "QVector"
class NetWorker : public QObject
{
Q_OBJECT
private:
QElapsedTimer timer;
QVector<long long> times;
QEventLoop loop;
QUdpSocket *dataServerSocket;
char buffer[16286];
int cnt = 0;
public:
NetWorker(QUdpSocket *dataServerSocket);
~NetWorker();
QEventLoop * getInnerLoop();
public slots:
void serverSocketProccessing();
};
#endif // NETWORKER_H
networker.cpp
#include "networker.h"
NetWorker::NetWorker(QUdpSocket *dataServerSocket)
{
this->dataServerSocket = dataServerSocket;
}
NetWorker::~NetWorker()
{
delete dataServerSocket;
}
QEventLoop *NetWorker::getInnerLoop()
{
return &loop;
}
void NetWorker::serverSocketProccessing()
{
while(true){
timer.start();
loop.exec();
times<<timer.nsecsElapsed();
while(dataServerSocket->hasPendingDatagrams()){
dataServerSocket->readDatagram(buffer, dataServerSocket->pendingDatagramSize());
}
if (times.size() >= 10000){
long long sum = 0;
for (int x : times){
//qDebug()<<x;
sum += x;
}
qDebug() << "mean: "<<sum/times.size();
break;
}
}
}