QNetworkAccessManager - 第一次 GET 很慢
Posted
技术标签:
【中文标题】QNetworkAccessManager - 第一次 GET 很慢【英文标题】:QNetworkAccessManager - first GET very slow 【发布时间】:2016-03-14 16:56:20 【问题描述】:我在 android 上使用 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 派生类,没有任何与获取请求相关的特殊功能。 _mgr
是在 DownloadManagers cTor 期间分配的 QNetworkAccessManager 对象。
如您所见,这只是一个获取请求的教科书示例,并没有什么花哨的地方。正如我所说:它在大多数情况下都有效。只有第一个 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?
【参考方案1】:
我没有在 Android 上尝试过,但我在 Windows 上遇到了同样的问题。因为这些是相同的症状,我会说这可能是相同的原因,即实现在第一次 get() 调用时延迟加载一些共享库。使用加密连接时尤其如此;在我的例子中,我可以在 Visual Studio 中看到在第一次 get() 调用时加载了 19 个 DLL。
解决此问题的一种方法是使用 connectToHost 或 connectToHostEncrypted 预连接到服务器,具体取决于您是否使用加密连接(例如 HTTPS)。我在应用程序启动时调用它,但任何时候 UI 空闲都应该没问题。然后后续的 get() 调用将具有相同的性能,包括第一个调用,因为库已经加载并且连接已经建立。我假设连接到 any 服务器将加载库。
请参阅https://forum.qt.io/topic/65201/qnetworkaccessmanager-first-get-very-slow/14 了解有关一般错误(非特定于 Android)的详细信息。
【讨论】:
以上是关于QNetworkAccessManager - 第一次 GET 很慢的主要内容,如果未能解决你的问题,请参考以下文章
错误:没有用于调用“QNetworkAccessManager::QNetworkAccessManager(Networking* const)”的匹配函数