【发布时间】:2021-01-09 12:10:07
【问题描述】:
我正在开发一个涉及使用实时、连续、音频输入的应用程序,为此我使用的是 portaudio。我首先创建了简单的 cli 版本以进行设置,并且 cli 版本中的内存使用情况似乎很好。在 CLI 版本中,当录制打开时,除了初始缓冲区之外没有分配额外的内存。
但是,在将相同代码从 CLI 应用到 GUI(为此,我使用 Qt)的过程中,我注意到随着录制的进行,应用程序使用的内存不断增加(大约3 mb/秒)。由于我的应用程序在未定义的时间内涉及音频输入,因此这种行为可能非常致命,因此,我开始从代码中剥离段,以检查哪个区域负责使用该内存。 (请注意,在 cli 版本中没有观察到这种行为,并且在 qt 中使用了几乎相同的代码,除了添加了 Q_OBJECT 宏)
我尝试了一段时间,但找不到任何东西。
我对使用 Qt 比较陌生,非常感谢一些帮助
我的小部件应用程序头文件
#ifndef DETECTORMAIN_H
#define DETECTORMAIN_H
#include <QMainWindow>
#include <QThread>
#include <QPointer>
#include "utils/rectools.h" /*Custom header file, the implementation of
which has been carried over from the cli version
which worked with constant memory usage.
Contains a class Recorder with the Q_OBJECT macro*/
QT_BEGIN_NAMESPACE
namespace Ui { class detectorMain; }
QT_END_NAMESPACE
class detectorMain : public QMainWindow
{
Q_OBJECT
public:
detectorMain(QWidget *parent = nullptr);
~detectorMain();
private slots:
void on_beginRecordingButton_clicked();
void on_stopRecordingButton_clicked();
void updateVolLabel(std::string);
private:
Ui::detectorMain *ui;
QPointer<Recorder> recorder;
QThread* thread;
};
#endif // DETECTORMAIN_H
源文件
#include "detectormain.h"
#include "ui_detectormain.h"
detectorMain::detectorMain(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::detectorMain)
{
ui->setupUi(this);
recorder = new Recorder;
thread = new QThread;
recorder->moveToThread(thread);
thread->start();
ui->beginRecordingButton->setEnabled(true);
ui->stopRecordingButton->setEnabled(false);
connect(recorder, SIGNAL(UpdateVols(std::string)), this, SLOT(updateVolLabel(std::string)));
}
detectorMain::~detectorMain()
{
delete ui;
}
void detectorMain::on_beginRecordingButton_clicked()
{
ui->beginRecordingButton->setEnabled(false);
ui->stopRecordingButton->setEnabled(true);
recorder->begin_recording();
}
void detectorMain::on_stopRecordingButton_clicked()
{
recorder->stop_recording();
ui->beginRecordingButton->setEnabled(true);
ui->stopRecordingButton->setEnabled(false);
}
void detectorMain::updateVolLabel(std::string vol)
{
ui->VolLabel->setText(QString::fromStdString(vol));
QCoreApplication::processEvents();
}
函数 Recorder::begin_recording() 发出 UpdateVols(std::string) 其中 UpdateVols 是 Recorder 类中的一个信号。它以相当快的速度发射(每毫秒大约 1 次)。这是否与内存使用量增加有关? 在 CLI 版本中,我可以根据需要计算任何内容,这是 CLI 版本和 Qt 版本之间代码的最大区别。
begin_recording() 函数执行完成后内存使用量并没有减少,这让我很困惑。
例如,应用程序以 9 mb 的内存使用量开始,当 begin_recording() 运行 10 秒时增加到大约 39,之后不做任何事情时保持在 39 mb。
如果是快发射率,我假设不再发射时内存使用会恢复正常。
另外,在上面的代码中,当点击 beginRecordingButton 时,应用程序变得无响应,但在函数 recorder->begin_recording() 执行完成后恢复。我想这与内存不断增加有关,但我不太确定。
我认为错误存在于我如何使用 QThread 对象并将记录器对象移动到它的某个地方,但我不确定如何修复它。
在找出内存使用量增加的过程中,我尝试运行一个只有按钮和标签的裸应用程序,根本不涉及记录器类。在简单地以零功能打开此应用程序时,只要显示非零 CPU 利用率,内存使用量就会持续增加约 0.5mb。增加后即使cpu利用率为0也不会下降。
总的来说,我想问一下,
1)如何解决内存使用量不断增加的问题? (我认为错误不在于 Recorder 类,因为相同的代码在没有 qt 的情况下在常量内存中运行)
2)最后一段提到的行为是否正常?
【问题讨论】:
-
在哪个操作系统上?什么样的计算机(单核 RasberryPi 或多核 Linux/x86-64 笔记本电脑,例如运行 Debian...)?请在您的问题中提供一些minimal reproducible example(因此简化您的代码,但请提供一些
main功能)。对于 Linux,另请参阅 linuxatemyram.com 并考虑使用 valgrind.org -
recorder和detectorMain实例之间的连接将使用排队连接,所以如果你真的以 1kHz 发出UpdateVols信号,那么我怀疑事件队列正在逐渐填满待处理请求——因此内存使用量不断增加。您可以尝试限制UpdateVols信号的发射速率吗? -
我现在就试试@G.M.是否有一些关于使用 emit 的文档以及这样做的频率如何?考虑到它的音频信号,我想把损失降到最低