2016-03-14 26 views
7

Ho un problema con l'utilizzo di QNetworkAccessManager in Qt 5.5 su Android. Il download di un file grafico semplice e di piccole dimensioni tramite http GET genera molte chiamate di garbage collection e un blocco dell'interfaccia utente durante tale periodo. I GET successivi funzionano perfettamente e senza queste chiamate GC. Il codice è il seguente:QNetworkAccessManager: innanzitutto GET molto lento

void DownloadManager::downloadFile(QUrl fromUrl, QString toFilePath) { 

    _currentFilePath = toFilePath; 

    QNetworkRequest request; 
    request.setUrl(fromUrl); 

    qDebug() << "before"; 

    _currentReply = _mgr.get(request); 

    qDebug() << "after"; 

    connect(_currentReply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(downloadError(QNetworkReply::NetworkError))); 
    connect(_currentReply, SIGNAL(downloadProgress(qint64, qint64)), this, SLOT(downloadProgress(qint64,qint64))); 
    connect(_currentReply, SIGNAL(finished()), this, SLOT(downloadFinished())); 

} 

DownloadManager è una classe personalizzata QObject-derivato, senza particolarità che sono rilevanti per la richiesta GET. _mgr è un oggetto QNetworkAccessManager assegnato durante DownloadManagers cTor.

Come potete vedere, questo è solo un esempio da manuale di richiesta get, niente di troppo. E come ho detto: funziona, per la maggior parte. Solo la prima richiesta get finisce così:

D/ .../downloadmanager.cpp:61 (void DownloadManager::downloadFile(QUrl, QString)): before 
D/dalvikvm(13298): GC_CONCURRENT freed 2290K, 25% free 10911K/14407K, paused 2ms+3ms, total 29ms 
D/dalvikvm(13298): GC_CONCURRENT freed 501K, 25% free 10884K/14407K, paused 13ms+2ms, total 35ms 
D/dalvikvm(13298): GC_CONCURRENT freed 524K, 25% free 10892K/14407K, paused 12ms+3ms, total 36ms 
D/dalvikvm(13298): WAIT_FOR_CONCURRENT_GC blocked 6ms 
D/dalvikvm(13298): GC_CONCURRENT freed 537K, 25% free 10887K/14407K, paused 2ms+9ms, total 32ms 
D/dalvikvm(13298): WAIT_FOR_CONCURRENT_GC blocked 14ms 
D/dalvikvm(13298): GC_CONCURRENT freed 840K, 25% free 10899K/14407K, paused 12ms+3ms, total 38ms 
D/dalvikvm(13298): WAIT_FOR_CONCURRENT_GC blocked 11ms 
D/dalvikvm(13298): GC_CONCURRENT freed 1294K, 25% free 10901K/14407K, paused 2ms+2ms, total 27ms 
D/dalvikvm(13298): WAIT_FOR_CONCURRENT_GC blocked 11ms 
D/dalvikvm(13298): GC_CONCURRENT freed 1187K, 22% free 11330K/14407K, paused 2ms+2ms, total 30ms 
D/dalvikvm(13298): WAIT_FOR_CONCURRENT_GC blocked 15ms 
D/dalvikvm(13298): GC_CONCURRENT freed 1459K, 19% free 11919K/14535K, paused 13ms+4ms, total 64ms 
D/dalvikvm(13298): WAIT_FOR_CONCURRENT_GC blocked 18ms 
D/ .../downloadmanager.cpp:65 (void DownloadManager::downloadFile(QUrl, QString)): after 

ho semplicemente non capisco che cosa causa che molto GC accada - ci vuole circa un pieno per un anno e mezzo secondo per tutto quello di elaborare (per un download che dovrebbe richiedere una frazione di secondo e, inoltre, essere asincrono e non bloccare l'interfaccia utente).

Informazioni aggiuntive:

  • E 'sempre solo il primo download che fa scattare questo. Download successivi, anche per lo stesso file, funzionano perfettamente

  • Non importa se esiste un file nella posizione esatta con il nome esatto oppure no. Scaricare il file, eliminarlo, tornare nell'applicazione e riscaricarlo fornisce gli stessi risultati: il primo get è lento e ha il GC, il secondo funziona perfettamente.

  • Io chiamo tutto questo da un file QML, che causa un oggetto C++ singleton per chiamare DownloadManager :: downloadFile.

  • Oltre all'interfaccia utente QML, nient'altro è in esecuzione all'interno dell'applicazione. Nessun pesante scambio di dati, nessun caricamento in background su altri thread, niente.

Sarei grato per qualsiasi suggerimento per risolvere questo.

+0

Il 'QNetworkAccessManager' genera un thread di lavoro con il proprio loop di eventi per elaborare le richieste di rete.Forse l'avvio di questo ciclo di eventi comporta molte chiamate in Java? –

risposta

1

Non ho provato su Android, ma ho avuto lo stesso problema su Windows. Poiché si tratta degli stessi sintomi, direi che probabilmente è la stessa ragione, ovvero che l'implementazione sta caricando pigramente alcune librerie condivise sulla prima chiamata get(). Questo è particolarmente vero quando si utilizza una connessione crittografata; nel mio caso posso vedere in Visual Studio che 19 DLL sono caricate sulla prima chiamata get().

Un modo per aggirare che è preconnettersi al server utilizzando connectToHost o connectToHostEncrypted, a seconda se si sta utilizzando una connessione crittografata (ad esempio HTTPS) o meno. Lo sto chiamando all'avvio dell'applicazione, ma ogni volta che l'interfaccia utente è inattiva dovrebbe andare bene. Quindi le successive chiamate get() avranno tutte le stesse prestazioni, inclusa la prima, poiché le librerie sono state caricate e la connessione è già stata stabilita. Suppongo che la connessione a qualsiasi server caricherà le librerie.

Vedere https://forum.qt.io/topic/65201/qnetworkaccessmanager-first-get-very-slow/14 per dettagli sull'errore generico (non specifico per Android).