- 引言
- 测试思路
- 测试结果
- 测试中所遇问题
- 测试代码
项目中大量使用了设备树,代码是通过Model/View实现的。当设备数量达到1w+时,主界面出现明显卡顿,十有八九是代码实现问题,但在这之前需要先验证Model/View框架的性能,确保重构的基础是牢靠的。
测试思路依项目需要,测试的model大小应远大于1w+且考虑树形结构,目前设置为10w的初始节点,每个初始节点下再挂上5个子节点,也就是总量为60w。
为模拟设备变化情况,设置了定时器每个1s中随机生成一类事件(添加、修改、删除),同时随机生成一个目标节点,“添加”需要成为该节点的子节点,“修改”需要改变该节点的文字及背景颜色,“删除”则删除该节点。
测试结果对上述环节的时间分别进行打印,结果如下:
上图中“init time”时间为数据初始化时间,耗时11s。添加、删除、修改分别为“add item time”、“modify item time”、“delete item time”,可见这些操作的耗时是随机的,取决于查找节点的时间,节点越靠前耗时越少。那么我们需要找到最大耗时也就是遍历所有的时间进行估算,可以从图中看到有一个“parent name:root”的打印,这是代码中生成的随机节点不在当前model中的标志,这就意味着查找函数需要遍历全部节点,该次操作的耗时为最长耗时,按照正态分布,该值的中间值0.1s可以近似认为是平均耗时。
上述数据为60w节点的数据,相当于实际项目60倍左右,所以远远高于项目的需求。
测试中所遇问题测试过程中遇到了QTreeView浏览节点卡顿的问题,而且随着所展示行数的增加,卡顿的现象明显加强。经过搜索得知,需要增加如下代码:
m_treeView->setUniformRowHeights(true);
需要设置为统一的行号,否则qt代码中会不断查询当前所展示行的行高,导致浏览的过程异常卡顿。
测试代码class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private:
Ui::MainWindow *ui;
protected:
void showEvent(QShowEvent* event) Q_DECL_OVERRIDE;
private slots:
void slot_timeout();
private:
void initModel();
int creatItemID();
QStandardItem* findItemByID(int id);
void randomAdd(int randomID);
void randomModify(int randomID);
void randomDelete(int randomID);
QString parentName(QStandardItem* item);
private:
class QTreeView* m_treeView;
class QStandardItemModel* m_model;
class QTimer* m_timer;
int m_count;
int m_subCount;
int m_itemID;
int m_interval;
};
#include#include #include #include #include MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) , m_count(100000) , m_subCount(5) , m_itemID(0) , m_interval(1000) { ui->setupUi(this); m_timer = new QTimer(this); connect(m_timer, &QTimer::timeout, this, &MainWindow::slot_timeout); m_model = new QStandardItemModel(this); m_treeView = new QTreeView(this); m_treeView->setModel(m_model); m_treeView->header()->hide(); m_treeView->setUniformRowHeights(true); setCentralWidget(m_treeView); } MainWindow::~MainWindow() { delete ui; } void MainWindow::showEvent(QShowEvent *) { initModel(); m_timer->start(m_interval); } void MainWindow::slot_timeout() { int randomType = QRandomGenerator::global()->bounded(0, 3); int randomIndex = QRandomGenerator::global()->bounded(m_itemID); if(randomType == 1){ randomModify(randomIndex); } else if(randomType == 2){ randomDelete(randomIndex); } else{ randomAdd(randomIndex); } } void MainWindow::initModel() { QTime time; time.start(); for (int i=0; i setText(QString::number(i)); tmpItem->setData(creatItemID()); for (int j=0; j setText(tmpItem->text() + "_" + QString::number(j)); subItem->setData(creatItemID()); tmpItem->appendRow(subItem); } m_model->appendRow(tmpItem); } qDebug() << "init time:" < match(m_model->index(0,0), Qt::UserRole + 1, id, 1, Qt::MatchRecursive); if(!indexList.isEmpty()){ qDebug() << "found, ID:" << id; return m_model->itemFromIndex(indexList.first()); } qDebug() << "not found, ID:" << id; return nullptr; } void MainWindow::randomAdd(int randomID) { QTime time; time.start(); auto item = new QStandardItem(); item->setText(QDateTime::currentDateTime().toString("MM:ss.zzz")); item->setData(creatItemID()); auto parentItem = findItemByID(randomID); if(parentItem == nullptr){ m_model->appendRow(item); }else{ parentItem->appendRow(item); } qDebug()<< "add row:" << item->row() << "parent name:" << parentName(item); qDebug()<< "add item time:" << time.elapsed()/1000.0<<"s"; } void MainWindow::randomModify(int randomID) { QTime time; time.start(); auto item = findItemByID(randomID); if(item != nullptr){ qDebug()<< "modify row:" << item->row() << "parent name:" << parentName(item); item->setText(item->text() + "_modify"); item->setData(QVariant(QColor(237,100,100,180)),Qt::BackgroundRole); } qDebug()<< "modify item time:" << time.elapsed()/1000.0<<"s"; } void MainWindow::randomDelete(int randomID) { QTime time; time.start(); auto item = findItemByID(randomID); if(item != nullptr){ qDebug()<< "delete row:" << item->row() << "parent name:" << parentName(item); auto parent = item->parent() ? item->parent() : m_model->invisibleRootItem(); parent->removeRow(item->row()); } qDebug()<< "delete item time:" << time.elapsed()/1000.0<<"s"; } QString MainWindow::parentName(QStandardItem *item) { auto parentItem = item->parent(); if(parentItem == nullptr){ return "root"; } else{ return parentItem->text(); } }



