Sto scrivendo server TCP in Qt che servirà file di grandi dimensioni. logica dell'applicazione è la seguente:QTcpServer lento con molti client simultanei
- ho sottoclasse QTcpServer e reimplementata incomingConnection (int)
- In incomingConnection, sto creando istanza di "Streamer" classe
- "Streamer" sta usando QTcpSocket che è inizializzato con setSocketDescriptor da incomingConnection
- Quando i dati da cliente arriva, sto rimandando prima risposta dall'interno readyRead() slot, quindi sto collegando bytesWritten segnale di presa (qint64) allo slot bytesWritten Streamer()
bytesWritten sembra qualcosa di simile:
Streamer.h:
...
private:
QFile *m_file;
char m_readBuffer[64 * 1024];
QTcpSocket *m_socket;
...
Streamer.cpp
...
void Streamer::bytesWritten() {
if (m_socket->bytesToWrite() <= 0) {
const int bytesRead = m_file->read(m_readBuffer, 64 * 1024);
m_socket->write(m_readBuffer, bytesRead);
}
}
...
Quindi, fondamentalmente sto solo scrivendo nuovi dati quando tutti i dati in sospeso viene completamente scritto. Penso che sia il modo più asincrono di farlo.
E tutto funziona correttamente, tranne che è piuttosto lento quando ci sono molti client simultanei.
Con circa 5 clienti - Sto scaricando da quel server con velocità di circa 1 MB/s (max della mia casa connessione internet)
Con circa 140 clienti - la velocità di download è di circa 100-200 KB/s .
La connessione Internet del server è 10 Gbps e con 140 client il suo utilizzo è di circa 100 Mbps, quindi non penso che questo sia il problema.
utilizzo della memoria del server con 140 clienti - 100 MB di 2GB disponibili
utilizzo della CPU del server - max 20%
sto usando la porta 800.
Quando ci sono stati 140 i clienti sulla porta 800 e la velocità di download era simile a 100-200 KB/s, ho eseguito una copia separata sulla porta 801 e stavo scaricando a 1 MB/s senza problemi.
La mia ipotesi è che in qualche modo, l'invio di eventi di Qt (oi notificatori di socket?) Sia troppo lento per gestire tutti quegli eventi.
ho provato:
- Compilazione tutta Qt e la mia app con -O3
- Installazione libglib2.0-dev e ricompilazione Qt (perché QCoreApplication utilizza QEventDispatcherGlib o QEventDispatcherUNIX, quindi volevo vedere se c'è qualche differenza)
- Creazione di alcuni thread e in incomingConnection (int) utilizzando streamer-> moveToThread() a seconda di quanti client sono attualmente in particolare filo - che non ha fatto alcun cambiamento (anche se ho osservato che le velocità erano molto più variare)
- processi di lavoro La deposizione delle uova usando
Codice:
main.cpp:
#include <sched.h>
int startWorker(void *argv) {
int argc = 1;
QCoreApplication a(argc, (char **)argv);
Worker worker;
worker.Start();
return a.exec();
}
in main():
...
long stack[16 * 1024];
clone(startWorker, (char *)stack + sizeof(stack) - 64, CLONE_FILES, (void *)argv);
e poi a partire un QLoc alServer nel processo principale e passando socketDescriptors da incomingConnection (int socketDescriptor) ai processi worker. Ha funzionato correttamente, ma le velocità di download erano ancora lente.
cercato anche:
- fork() - processo ing in incomingConnection() - che quasi ucciso il server :)
- Creazione di thread separato per ogni cliente - velocità è sceso a 50-100 KB/s
- utilizzando QThreadPool con QRunnable - nessuna differenza
sto usando Qt 4.8.1
Ho esaurito le idee.
E 'correlato a Qt o forse qualcosa con la configurazione del server?
O forse dovrei usare un diverso linguaggio/framework/server? Ho bisogno del server TCP che servirà i file, ma ho anche bisogno di svolgere alcune attività specifiche tra i pacchetti, quindi ho bisogno di implementare quella parte da solo.
E l'utilizzo del disco del server? Potrebbe essere il collo di bottiglia? –
È abbastanza possibile. Sembra che l'hardware del server sia difettoso. Ne sarò sicuro lunedì, e te lo farò sapere. Grazie! – AdrianEddy
Il collo di bottiglia è sicuramente le operazioni IO del disco. Sopra i 80 file aperti si verifica un carico del server> 1 e una velocità di download di circa 150 KB/s. C'è qualcosa che posso cambiare nel mio programma, o devo giocare con configurazione/hardware del server? – AdrianEddy