Tyl*_*r M 6 javascript memory qt memory-leaks qml
创建 的new实例XMLHttpRequest和调用会send()导致垃圾收集器无法清除的内存使用量,也无法清除gc(). 调用delete对象也不会清除内存。
import QtQuick 2.12
import QtQuick.Window 2.12
Window {
visible: true
width: 640
height: 480
Component.onCompleted: {
for(var i = 0; i < 100000; i++) {
console.log("Send request " + i)
var xhttp = new XMLHttpRequest
xhttp.open('get', 'someurl')
xhttp.send()
delete xhttp
}
gc() //why won't this clean the instances of XMLHttpRequest???
}
}
Run Code Online (Sandbox Code Playgroud)
如果我从不打电话,xhttp.send()那么我就没有任何内存泄漏。垃圾收集开始,因为没有对 的引用var xhttp并且内存被释放。我想也许垃圾收集器没有触发,但gc()也不会清除内存。
这个 MRE 将运行 100,000 次迭代并在内存中保存大约 500MB。这可以通过更改为 轻松容纳 5.0GB i < 1000000。
如何修复此内存泄漏并释放内存?
类似问题参考: QTBUG-43005(无解析) QTBUG-50231(无解析)
现在记录在QTBUG-83857 上
在这里,持有 2.0GB 的内存。它保持了将近 4 个小时,直到我杀死了该程序。当我关闭应用程序时,大约 60 秒后释放了整个 2GB 内存
尝试使用 QNetworkAccessManager 类
//main.qml
MyClass {
id: myNetworkClass
Component.onCompleted: {
for(var i = 0; i < 10000; i++) {
myNetworkClass.doDownload()
}
}
}
Run Code Online (Sandbox Code Playgroud)
//myclass.h
#ifndef MYCLASS_H
#define MYCLASS_H
#include <QObject>
#include <QNetworkAccessManager>
#include <QNetworkRequest>
#include <QNetworkReply>
#include <QDebug>
class MyClass : public QObject
{
Q_OBJECT
public:
explicit MyClass(QObject *parent = 0):QObject(){
manager = new QNetworkAccessManager(this);
connect(manager, SIGNAL(finished(QNetworkReply*)),
this, SLOT(replyFinished(QNetworkReply*)));
}
public:
Q_INVOKABLE void doDownload() {
manager->get(QNetworkRequest(QUrl("https://esi.evetech.net/latest/characters/93610700")));
}
public slots:
void replyFinished(QNetworkReply *reply) {};
private:
QNetworkAccessManager *manager;
int count = 0;
};
#endif // MYCLASS_H
Run Code Online (Sandbox Code Playgroud)
不幸的是,根据 htop 的说法,这也会保留内存并且不会释放它。
编辑
在 C++ 中创建一个新的控制类来处理您的 Web 请求,然后设置根上下文属性或在 QML 中注册类型并使用 C++ api。
这是最简单的方法:
在 myclass.cpp 中,您使用此类代码以及适当的处理程序创建一个方法(replyFinished)
QNetworkAccessManager *manager = new QNetworkAccessManager(this);
connect(manager, &QNetworkAccessManager::finished,
this, &MyClass::replyFinished);
manager->get(QNetworkRequest(QUrl("http://qt-project.org")));
Run Code Online (Sandbox Code Playgroud)
--
qmlRegisterType<MyClass>("MyClass", 1,0, "MyClass");
Run Code Online (Sandbox Code Playgroud)
--
并在你的 QML 文件中执行
import MyClass 1.0
Window {
MyClass {
id: myNetworkClass
}
function doLookup() { myNetworkClass.myCustomMethod(); }
}
Run Code Online (Sandbox Code Playgroud)
这将为您提供一种稳定的方法来避免因运行本机 javascript 环境而产生的 QML 问题,该环境是异步且弱类型的强类型框架...
祝你好运!
原来的
首先,您通过创建请求来保留挂起的对象引用,而不保存对所创建对象的引用......
将所有 XMLHttpRequest 对象的数组保留在 Window 的属性中
Window
{
property var requests: []
// ...
Timer {
onTriggered: {
// add request to array
requests.push(xhttp);
}
}
}
Run Code Online (Sandbox Code Playgroud)
然后也许开始删除数组中的对象......
var xhttp = requests.unshift()
xhttp.destroy()
Run Code Online (Sandbox Code Playgroud)
但真正的问题在于以 50 毫秒的间隔发送 http 请求
那就是每秒 20 个或每分钟 1200 个请求
您可能需要调整代码以在前一个请求完成后发送请求..或将间隔设置为更高的值