2016-03-14 6 views
7

Ich habe ein Problem mit der Verwendung des QNetworkAccessManager in Qt 5.5 auf Android. Das Herunterladen einer einfachen, kleinen Grafikdatei über http GET führt zu vielen Garbage Collection-Aufrufen und zu einer Sperrung der Benutzeroberfläche während dieser Zeit. Nachfolgende GETs funktionieren einwandfrei und ohne diese GC-Aufrufe. Der Code lautet wie folgt:QNetworkAccessManager - zuerst GET sehr langsam

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 ist eine benutzerdefinierte QObject abgeleitete Klasse ohne besondere Merkmale, die auf die Nehmeranforderung relevant sind. _mgr ist ein QNetworkAccessManager-Objekt, das während des DownloadManagers cTor zugewiesen wird.

Wie Sie sehen können, ist dies nur ein Lehrbuchbeispiel für eine get-Anfrage, nichts Besonderes. Und wie gesagt: Es funktioniert größtenteils. Nur die erste Get-Anforderung endet wie folgt auf:

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 

ich einfach nicht verstehen, was bewirkt, dass viel GC passieren - es dauert etwa eine voll eineinhalb Sekunden für alles zu arbeiten (für eine Download, das sollte einen Bruchteil einer Sekunde dauern und außerdem asynchron sein und die UI nicht sperren).

Weitere Informationen:

  • Es ist immer nur der erste Download, die diese auslöst. Nachfolgende Downloads, sogar für die exakt gleiche Datei, funktionieren fehlerfrei

  • Es spielt keine Rolle, ob es eine Datei an der genauen Position mit dem genauen Namen gibt oder nicht. Das Herunterladen der Datei, das Löschen der Datei, das Zurückgehen in die Anwendung und das erneute Laden derselben liefert die gleichen Ergebnisse - der erste geht langsam und hat den GC, der zweite funktioniert einwandfrei.

  • Ich rufe alles aus einer QML-Datei, die ein Singleton C++ - Objekt ruft DownloadManager :: downloadFile.

  • Außer der QML-Benutzeroberfläche wird in der Anwendung nichts anderes ausgeführt. Kein starker Datenaustausch, keine Hintergrundbelastung für andere Threads, nichts.

Ich wäre dankbar für Hinweise zur Lösung dieses Problems.

+0

Der 'QNetworkAccessManager' erzeugt einen Arbeitsthread mit einer eigenen Ereignisschleife, um die Netzwerkanforderungen zu verarbeiten.Vielleicht führt das Starten dieser Ereignisschleife viele Aufrufe in Java aus? –

Antwort

1

Ich habe nicht auf Android versucht, aber ich hatte das gleiche Problem auf Windows. Da dies die gleichen Symptome sind, würde ich sagen, dass dies wahrscheinlich der gleiche Grund ist, nämlich dass die Implementierung einige gemeinsam genutzte Bibliotheken beim ersten Aufruf von get() lädt. Dies gilt insbesondere, wenn eine verschlüsselte Verbindung verwendet wird. In meinem Fall kann ich in Visual Studio sehen, dass beim ersten Aufruf von get() 19 DLLs geladen werden.

Eine Möglichkeit, dies zu umgehen, besteht darin, eine Verbindung zum Server über connectToHost oder connectToHostEncrypted herzustellen, je nachdem, ob Sie eine verschlüsselte Verbindung (z. B. HTTPS) verwenden oder nicht. Ich rufe das beim Start der Anwendung, aber jederzeit, wenn die Benutzeroberfläche inaktiv ist, sollte es in Ordnung sein. Dann haben nachfolgende Aufrufe von get() alle dieselbe Leistung, einschließlich der ersten, da die Bibliotheken geladen wurden und die Verbindung bereits hergestellt ist. Ich nehme an, dass die Verbindung zu irgendein Server die Bibliotheken lädt.

Weitere Informationen zum generischen Fehler finden Sie unter https://forum.qt.io/topic/65201/qnetworkaccessmanager-first-get-very-slow/14 (nicht für Android).