У меня есть задача обработки данных UDP со скоростью чтения ~ 10 кГц. Я работаю с Qt 5.13.1 (MinGW32), поэтому я попытался использовать QUdpSocket
. Я сделал простую тестовую программу, но результаты немного разочаровывают. Сигнал readyRead()
слишком медленный. По какой-то причине я получаю задержки более 1 или 2 мс каждые 2-4 сигнала. Я сделал простой счетчик пакетов и сравнил его с тем, что вижу в wireshark. Конечно же, есть потеря пакета.
Что я могу сделать, чтобы улучшить производительность? Или, может быть, это просто предел цикла событий Qt?
Я запускаю его с Qt Creator 4.10.0. На Windows 7.
Обновление: С вашими советами: Я попробовал:
Перемещение сокета в другой поток. Это дает немного больше производительности .. очень немного
LowDelayOption = 1 - я не заметил никаких изменений
ReceiveBufferSizeSocketOption - я не сделалзаметить любые изменения
- Не использовать QDebug во время чтения - я не проверял его, просто используйте для сбора статистики
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;
}
}
}