Разработка идёт в версии 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);
}
...
};
Здравствуйте, 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;
}
Здравствуйте, 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?