QNetworkAccessManager - 第一次 GET 请求非常缓慢

7

我在安卓平台上使用Qt 5.5的QNetworkAccessManager时遇到问题。通过HTTP GET方式下载一个简单且小的图形文件会导致大量垃圾回收调用和UI锁死。随后的GET请求运行良好且不会有这些GC调用。代码如下:

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是一个自定义的QObject衍生类,没有任何与get请求相关的特殊功能。 _mgr是在DownloadManagers cTor期间分配的QNetworkAccessManager对象。

正如您所看到的,这只是一个标准的get请求示例,没有太多花哨的东西。就像我说的那样:它可以工作,至少大部分情况下是这样的。只有第一个get请求会以这种方式结束:

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

我不明白是什么原因导致了如此多的GC发生-这需要大约一秒到一秒半的时间才能完成所有操作(对于一个应该在瞬间完成且是异步的下载,而且不会锁定UI)。

附加信息:

  • 总是只有第一次下载会触发这个问题。即使是对于完全相同的文件,后续的下载都可以完美地工作。

  • 无论是否存在具有完全相同名称和位置的文件,都没有影响。下载文件、删除文件、重新进入应用程序并重新下载文件会得到相同的结果-第一次获取速度慢,有GC,第二次正常工作。

  • 我从一个QML文件中调用所有内容,这会导致一个单例C++对象调用DownloadManager::downloadFile。

  • 除了QML UI之外,应用程序内没有其他运行内容。没有大量数据交换、没有其他线程的后台加载,什么都没有。

如果有任何解决此问题的指针,我将非常感谢。


QNetworkAccessManager 会生成一个带有自己事件循环的工作线程来处理网络请求。也许启动该事件循环会产生许多对 Java 的调用? - Kuba hasn't forgotten Monica
1个回答

1
我没有在Android上尝试过,但在Windows上遇到了相同的问题。因为这些都是相同的症状,我认为这可能是同样的原因,即实现在第一次get()调用时懒加载某些共享库。当使用加密连接时特别如此;在我的情况下,我可以在Visual Studio中看到在第一次get()调用时加载了19个DLL。

解决这个问题的方法之一是使用connectToHostconnectToHostEncrypted预连接到服务器,具体取决于您是否使用加密连接(例如HTTPS)。我在应用程序启动时调用它,但任何时候UI处于空闲状态都可以。然后,随后的get()调用将拥有相同的性能,包括第一个调用,因为库已经加载并且连接已经建立。我假设连接到任何服务器都会加载库。

详见https://forum.qt.io/topic/65201/qnetworkaccessmanager-first-get-very-slow/14,了解通用错误的详情(非Android特定)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,