вопрос по реализации
От: milkpot Россия  
Дата: 01.02.22 15:53
Оценка:
Разработка идёт в версии Qt 5.6.2 + mingw-w64, ОС Windows 10 64-bit.
Вывод данных выполняется с помощью QGraphicsView, QGraphicsScene и QOpenGLWidget.
Запускается процедура отображения данных нажатием кнопки "Multiple files" и управление
передаётся в рабочую нить. В нити формируется QImage из которого получается QPixmap и выводится на экран в цикле.
После каждого следующего нажатия кнопки "Multiple files" Heap увеличивается на 80-100 Мб (видно в VMMap).
После восемнадцати запусков по кнопке "Multiple files" Heap заканчивается и отображение изображений при
последующих нажатиях на кнопку не производится.
Вопрос в том, как реализовать функцию prepare_generate_data(), вызываемую в run() рабочей нити, чтобы
Heap так не рос.
void MainWindow::displayPixmap(const QPixmap &pixmap_data)
{
    QString str;
    graphicspixmapItem=pScene->addPixmap(pixmap_data);
    return;
}
void MainWindow::startWorkInAThread()
{
   /* WorkerThread * */workerThread = new WorkerThread;
    connect(workerThread, &WorkerThread::resultReady,this, &MainWindow::appendtoLogListBox);
    connect(workerThread, &WorkerThread::sendData, this, &MainWindow::displayPixmap);
    connect(workerThread,SIGNAL(finished()), workerThread,SLOT(deleteLater()) );
   // connect(this, &MainWindow::fillDataList, workerThread, &WorkerThread::receiveDataList);
    workerThread->initInnerObjects();
    workerThread->start();
    return;
}
void MainWindow::initializeGL()
{
    QGraphicsView* pView =ui->graphicsView;


    QRect viewRect = pView->rect();
    QRectF viewRectF(viewRect);

    pScene = new QGraphicsScene(viewRectF,this);

    pView->setScene(pScene);

    pOpenGLWidget = new QOpenGLWidget( this );
    QSurfaceFormat format_srf;
    format_srf.setDepthBufferSize(32);
    format_srf.setStencilBufferSize(16);
    format_srf.setVersion(3,2);
    format_srf.setProfile( QSurfaceFormat::CoreProfile );

    pOpenGLWidget->setFormat(format_srf);

    pView->setViewport(pOpenGLWidget);
    return;
}




class WorkerThread : public QThread
{
    Q_OBJECT
public:
    QMutex mutex;
    QWaitCondition wtc_worker2;
    void initInnerObjects(/*const CreatedObject *cObjectsPtr*/)
    {
        wait_cnd=false;
        lock_cnd=false;
        fileSize=0;
    }
    void run() Q_DECL_OVERRIDE {
        QString result;
        forever {
            mutex.lock();
            qDebug() << "--- Worker: run() func, after lock call";
            wait_cnd=wtc_worker2.wait(&mutex,/*5000*/one_and_a_half_hour_wait);
            if(false==wait_cnd)
            {
                mutex.unlock();
                continue;
            }
            else if(true==wait_cnd)
            {
//                prepare_data();
                prepare_generate_data();
                result=QString(tr("--- wait_cnd is true"));
                do_send_result(result);
            }
            qDebug() << "--- wait_cnd is " << wait_cnd;
            qDebug() << "--- Worker: run() func, after wait call";
            mutex.unlock();
        }
    }
    void prepare_generate_data()
    {
        QString str;
       // str.append(" --- slot button6Clicked() ");
       // appendtoLogListBox(str);
        QString filePath;
        QFile file;
        QDataStream dstrm;
        int data_quant=0;
        std::vector<unsigned short> buffer_vect;
        QSize rct_size(320,256);

        QPixmap myPixmap;

        QImage loc_img(rct_size,QImage::Format_RGB32 /*QImage::Format_RGBX8888*/);
       // const uint rgb_value=0xFF000000 /*0*/;
//        QRgb q_rgb;
//        int bytesperLine=0;
//        int bytecount=0;
       // QRgb *pixels;
        QRgb *line;

        pixmap_vect.clear();

        QBuffer hr;

        unsigned long/* long */ start_time=GetTickCount();
        for(int i=0;i<256;i++)
        {
            for(int y=0;y<loc_img.height();y++)
            {
               // QRgb *line=reinterpret_cast<QRgb*>(loc_img.scanLine(y));
                line=static_cast<QRgb *>(static_cast<void *>(loc_img.scanLine(y)));
                for(int x=0;x<loc_img.width();x++)
                {
                    if(x<256-i)
                        line[x]=qRgb(x,x,x);
                    else
                        line[x]=qRgb(0x80,0x80,0x80);
                }
            }
            pixmap_copy=QPixmap::fromImage( loc_img);
            emit sendData(pixmap_copy);
        }

        unsigned long/* long */ end_time=GetTickCount();
        unsigned long/* long */ loc_delta=end_time-start_time;
         str=QString(tr("  --- loc_delta = %1")).arg(loc_delta);
         do_send_result(str);
        loc_list.clear();
        return;
    }
public /*slots*/:
    void launch_threadfunc()
    {
        wtc_worker2.wakeOne();
    }
signals:
    void resultReady(const QString &s);
    void sendData(const QPixmap &pixmap);
public slots:
    void do_send_result(const QString &info_msg)
    {
        emit resultReady(info_msg);
    }
...
};
Re: вопрос по реализации
От: K13 http://akvis.com
Дата: 01.02.22 18:26
Оценка: 3 (1) +1
M>После каждого следующего нажатия кнопки "Multiple files" Heap увеличивается на 80-100 Мб (видно в VMMap).
M>После восемнадцати запусков по кнопке "Multiple files" Heap заканчивается и отображение изображений при
M>последующих нажатиях на кнопку не производится.
M>Вопрос в том, как реализовать функцию prepare_generate_data(), вызываемую в run() рабочей нити, чтобы
M>Heap так не рос.

Не хранить старые QPixmap, например?
Проблема не в prepare_genеrated_data() а в displayPixmap()
Кто будет удалять старые варианты картинки?

Или речь идет о "что-то много жрет каждая картинка"?
На каждое нажатие кнопки генеится 256 картинок.
Только пикселы каждой картинки -- 327 680 байтиков, не считая оверхеда на саму структуру, текстуры внутри QGкaphicsView и т.д.
Умножаем на 256 и получаем почти 82 мегабайта только на сами пиксели при каждом нажатии кнопки.
Отредактировано 01.02.2022 18:30 K13 . Предыдущая версия .
Re[2]: вопрос по реализации
От: milkpot Россия  
Дата: 02.02.22 15:52
Оценка:
Здравствуйте, K13, Вы писали:

M>>После каждого следующего нажатия кнопки "Multiple files" Heap увеличивается на 80-100 Мб (видно в VMMap).

M>>После восемнадцати запусков по кнопке "Multiple files" Heap заканчивается и отображение изображений при
M>>последующих нажатиях на кнопку не производится.
M>>Вопрос в том, как реализовать функцию prepare_generate_data(), вызываемую в run() рабочей нити, чтобы
M>>Heap так не рос.

K13>Не хранить старые QPixmap, например?

K13>Проблема не в prepare_genеrated_data() а в displayPixmap()
K13>Кто будет удалять старые варианты картинки?

K13>Или речь идет о "что-то много жрет каждая картинка"?

K13>На каждое нажатие кнопки генеится 256 картинок.
K13>Только пикселы каждой картинки -- 327 680 байтиков, не считая оверхеда на саму структуру, текстуры внутри QGкaphicsView и т.д.
K13>Умножаем на 256 и получаем почти 82 мегабайта только на сами пиксели при каждом нажатии кнопки.

void MainWindow::displayPixmap(const QPixmap &pixmap_data)
{
    QString str;
   // graphicspixmapItem=pScene->addPixmap(pixmap_data);
    return;
}

После четырех запусков "Multiple Files" куча растёт до 40 Мб( по VMMap) и больше не растёт.
Если раскомментировать строки выше и добавить удаление graphicspixmapItem, то у приложения медленнее увеличивается куча (до ~ 81 Мб)
при условии, что процедура запуска "Multiple Files" выполнилась 24 раза, а не по 81 Мб за каждый вызов "Multiple Files"
как было раньше.
void MainWindow::displayPixmap(const QPixmap &pixmap_data)
{
    QString str;
    delete graphicspixmapItem;
    graphicspixmapItem=pScene->addPixmap(pixmap_data);
    return;
}
Re: вопрос по реализации
От: milkpot Россия  
Дата: 11.02.22 15:19
Оценка:
Здравствуйте, milkpot, Вы писали:

M>Разработка идёт в версии Qt 5.6.2 + mingw-w64, ОС Windows 10 64-bit.

M>Вывод данных выполняется с помощью QGraphicsView, QGraphicsScene и QOpenGLWidget.
M>Запускается процедура отображения данных нажатием кнопки "Multiple files" и управление
M>передаётся в рабочую нить. В нити формируется QImage из которого получается QPixmap и выводится на экран в цикле.
M>После каждого следующего нажатия кнопки "Multiple files" Heap увеличивается на 80-100 Мб (видно в VMMap).
M>После восемнадцати запусков по кнопке "Multiple files" Heap заканчивается и отображение изображений при
M>последующих нажатиях на кнопку не производится.
M>Вопрос в том, как реализовать функцию prepare_generate_data(), вызываемую в run() рабочей нити, чтобы
M>Heap так не рос.
M>
M>void MainWindow::displayPixmap(const QPixmap &pixmap_data)
M>{
M>    QString str;
M>    graphicspixmapItem=pScene->addPixmap(pixmap_data);
M>    return;
M>}
M>void MainWindow::startWorkInAThread()
M>{
M>   /* WorkerThread * */workerThread = new WorkerThread;
M>    connect(workerThread, &WorkerThread::resultReady,this, &MainWindow::appendtoLogListBox);
M>    connect(workerThread, &WorkerThread::sendData, this, &MainWindow::displayPixmap);
M>    connect(workerThread,SIGNAL(finished()), workerThread,SLOT(deleteLater()) );
M>   // connect(this, &MainWindow::fillDataList, workerThread, &WorkerThread::receiveDataList);
M>    workerThread->initInnerObjects();
M>    workerThread->start();
M>    return;
M>}
M>void MainWindow::initializeGL()
M>{
M>    QGraphicsView* pView =ui->graphicsView;


M>    QRect viewRect = pView->rect();
M>    QRectF viewRectF(viewRect);

M>    pScene = new QGraphicsScene(viewRectF,this);

M>    pView->setScene(pScene);

M>    pOpenGLWidget = new QOpenGLWidget( this );
M>    QSurfaceFormat format_srf;
M>    format_srf.setDepthBufferSize(32);
M>    format_srf.setStencilBufferSize(16);
M>    format_srf.setVersion(3,2);
M>    format_srf.setProfile( QSurfaceFormat::CoreProfile );

M>    pOpenGLWidget->setFormat(format_srf);

M>    pView->setViewport(pOpenGLWidget);
M>    return;
M>}

M>




M>
M>class WorkerThread : public QThread
M>{
M>    Q_OBJECT
M>public:
M>    QMutex mutex;
M>    QWaitCondition wtc_worker2;
M>    void initInnerObjects(/*const CreatedObject *cObjectsPtr*/)
M>    {
M>        wait_cnd=false;
M>        lock_cnd=false;
M>        fileSize=0;
M>    }
M>    void run() Q_DECL_OVERRIDE {
M>        QString result;
M>        forever {
M>            mutex.lock();
M>            qDebug() << "--- Worker: run() func, after lock call";
M>            wait_cnd=wtc_worker2.wait(&mutex,/*5000*/one_and_a_half_hour_wait);
M>            if(false==wait_cnd)
M>            {
M>                mutex.unlock();
M>                continue;
M>            }
M>            else if(true==wait_cnd)
M>            {
M>//                prepare_data();
M>                prepare_generate_data();
M>                result=QString(tr("--- wait_cnd is true"));
M>                do_send_result(result);
M>            }
M>            qDebug() << "--- wait_cnd is " << wait_cnd;
M>            qDebug() << "--- Worker: run() func, after wait call";
M>            mutex.unlock();
M>        }
M>    }
M>    void prepare_generate_data()
M>    {
M>        QString str;
M>       // str.append(" --- slot button6Clicked() ");
M>       // appendtoLogListBox(str);
M>        QString filePath;
M>        QFile file;
M>        QDataStream dstrm;
M>        int data_quant=0;
M>        std::vector<unsigned short> buffer_vect;
M>        QSize rct_size(320,256);

M>        QPixmap myPixmap;

M>        QImage loc_img(rct_size,QImage::Format_RGB32 /*QImage::Format_RGBX8888*/);
M>       // const uint rgb_value=0xFF000000 /*0*/;
M>//        QRgb q_rgb;
M>//        int bytesperLine=0;
M>//        int bytecount=0;
M>       // QRgb *pixels;
M>        QRgb *line;

M>        pixmap_vect.clear();

M>        QBuffer hr;

M>        unsigned long/* long */ start_time=GetTickCount();
M>        for(int i=0;i<256;i++)
M>        {
M>            for(int y=0;y<loc_img.height();y++)
M>            {
M>               // QRgb *line=reinterpret_cast<QRgb*>(loc_img.scanLine(y));
M>                line=static_cast<QRgb *>(static_cast<void *>(loc_img.scanLine(y)));
M>                for(int x=0;x<loc_img.width();x++)
M>                {
M>                    if(x<256-i)
M>                        line[x]=qRgb(x,x,x);
M>                    else
M>                        line[x]=qRgb(0x80,0x80,0x80);
M>                }
M>            }
M>            pixmap_copy=QPixmap::fromImage( loc_img);
M>            emit sendData(pixmap_copy);
M>        }

M>        unsigned long/* long */ end_time=GetTickCount();
M>        unsigned long/* long */ loc_delta=end_time-start_time;
M>         str=QString(tr("  --- loc_delta = %1")).arg(loc_delta);
M>         do_send_result(str);
M>        loc_list.clear();
M>        return;
M>    }
M>public /*slots*/:
M>    void launch_threadfunc()
M>    {
M>        wtc_worker2.wakeOne();
M>    }
M>signals:
M>    void resultReady(const QString &s);
M>    void sendData(const QPixmap &pixmap);
M>public slots:
M>    void do_send_result(const QString &info_msg)
M>    {
M>        emit resultReady(info_msg);
M>    }
M>...
M>};
M>


void MainWindow::displayPixmap(const QPixmap &pixmap_data)
{
    QString str;
    counter++;
    if(counter==1)
        (0);
    else {
        pScene->removeItem(graphicspixmapItem);
        delete graphicspixmapItem;
    }
    graphicspixmapItem=pScene->addPixmap(pixmap_data);
    return;
}


Сейчас измеряется время выполнения в функции prepare_generate_data().
Возник вопрос: как в дополнение к этому измерить время выполнения слота displayPixmap?
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.