QMLを解放する方法



  • CPUのメモリが256MBしかないため、表示していないQMLは解放して、メモリの使用量を削減したいと思っています。
    以下のように実装していますが、この方法では表示前と解放後のメモリの使用量が一致しません。

    Item {
    id:container
    property var objTmp
    function open(){
    if(objTmp === undefined || objTmp === null){
    var component = Qt.createComponent("***.qml")
    if(component.status == Component.Ready){
    objTmp = component.createObject(container)
    }
    }
    }
    }
    function close(){
    if(objTmp !== undefined && objTmp !== null){
    objTmp.destroy()
    }
    }
    }

    Loaderに動的ロード(使用時はsourceにQMLをセットし、未使用時は””をセット)したときも同様に一致しません。

    QMLを完全に解放する方法は無いのでしょうか?
    ご教授願います。



  • QML ではメモリの解放はガベージコレクションによって行われるため destroy() を実行した時点では解放されません。

    手動で解放するには以下のメソッドを(C++ から)実行する必要があります。
    http://doc.qt.io/qt-5/qjsengine.html#collectGarbage

    ドキュメントには書いていない(現時点では非公式な?方法)ですが、ガベージコレクタのソースコードを読むといくつかの環境変数を設定することで使用するメモリの量や GC の戦略の変更が可能のようですので、そちらも試してみてはいかがでしょうか。
    http://git.qt-users.jp/git/?p=mirror/qt/qtdeclarative.git;a=blob;f=src/qml/jsruntime/qv4mm.cpp;h=d5576b400a4af76a861de9abdf2e829f198a6bc6;hb=HEAD#l222



  • ご回答ありがとうございます。

    QJSEngine::collectGarbageはどのように使用すればよいのでしょうか?
    以前trimComponentCache()を使ったときは効果がなかったのですが、
    これとは異なるものでしょうか?

    素人質問で申し訳ありませんが、ご教授願います。



  • QJSEngine は QQmlEngine の基底クラスなので以前に timComponentCache() を使ったことがあるのでしたら同じように collectGarbage() も使えるはずです。

    collectGarbage() はメモリの解放処理で、trimComponentCache() はキャッシュの解放処理なので別々の処理になります。詳細はドキュメントや実際の実装を参照してください。



  • collectGarbage()を実行してみましたがSegmentation faultが発生してしまいました。
    trimComponentCache()は正しく動作します。
    どういった原因が考えられますか?

    度々すみませんが、よろしくお願いします。



  • 実際のコードがないので詳細はわかりませんが、原因は Qt の collectGarbage() にバグがあるか、SAHI さんのコードにバグがあるかでしょう。

    もし Qt 側のバグであれば、バグレポを書いていただけると助かります。



  • かなり時間が経過してしまいました。
    Qt側にバグがあると言えるようなスキルは無いので、自分なりに色々と試してみましたが改善しませんでした。
    ちょっと長いですが、コードを添付しますので、ご助言をお願いします。

    (main.cpp)
    QtQuick2ApplicationViewer viewer;
    QQmlEngine* qengine = viewer.engine();
    waitthread waitproc;
    waitproc.setqengine(qengine);
    waitproc.start();

    (waitthread.h)
    #ifndef WAITTHREAD_H
    #define WAITTHREAD_H

    #include <QThread>
    #include <QMutex>
    #include <QQmlEngine>

    class waitthread : public QThread
    {
    Q_OBJECT
    public:
    explicit waitthread(QObject *parent = 0);
    ~waitthread();
    void stop();
    void setqengine(QQmlEngine *qmlenginepointer);

    public slots:

    protected:
    void run();

    private:
    QString state;
    volatile int running;
    QQmlEngine *qmlenginep;
    };

    #endif // WAITTHREAD_H

    (waitthread.cpp)
    #include <QApplication>
    #include <QDebug>
    #include "waitthread.h"

    waitthread::waitthread(QObject *parent) : QThread(parent)
    {
    state = "Thread Stop";
    running = 0;
    qmlenginep = NULL;
    }

    waitthread::~waitthread()
    {
    }

    void waitthread::run()
    {
    running = 1;
    bool onoff = false;
    while(running == 1){
    state = "Thread Running";

        msleep(10000);
    

    // qmlenginep->trimComponentCache();
    // qmlenginep->collectGarbage();
    // QApplication::processEvents(QEventLoop::AllEvents);

    // qDebug() << "Trim Component Cache !!";

        if(onoff){
            qmlenginep->trimComponentCache();
            qDebug() << "Trim Component Cache !!";
        }
        else{
            qmlenginep->collectGarbage();
            qDebug() << "collectGarbage !!";
        }
        QApplication::processEvents(QEventLoop::AllEvents);
        onoff = !onoff;
    
    }
    state = "Thread Stop";
    

    }

    void waitthread::setqengine(QQmlEngine *qmlenginepointer)
    {
    qmlenginep = qmlenginepointer;
    }

    以上のコードで10秒置きにcollectGarbageとtrimComponentCacheを実行していますが、最初のcollectGarbageでSegmentation faultが発生してプログラムが突然終了します。

    よろしくお願いします。


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.