File indexing completed on 2024-05-19 04:39:23
0001 /* 0002 SPDX-FileCopyrightText: 2010 Andreas Pakulat <apaku@gmx.de> 0003 0004 SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #include "projectmodelperformancetest.h" 0008 0009 #include <QApplication> 0010 #include <QDebug> 0011 #include <QElapsedTimer> 0012 #include <QGridLayout> 0013 #include <QPushButton> 0014 #include <QTimer> 0015 #include <QTreeView> 0016 0017 #include <projectmodel.h> 0018 #include <path.h> 0019 #include <tests/testcore.h> 0020 #include <tests/autotestshell.h> 0021 #include <tests/testplugincontroller.h> 0022 0023 // Knobs to increase/decrease the amount of items being generated 0024 #define SMALL_DEPTH 2 0025 #define SMALL_WIDTH 10 0026 #define BIG_DEPTH 3 0027 #define BIG_WIDTH 10 0028 #define INIT_WIDTH 10 0029 #define INIT_DEPTH 3 0030 0031 using KDevelop::ProjectModel; 0032 using KDevelop::ProjectFolderItem; 0033 using KDevelop::ProjectBaseItem; 0034 using KDevelop::ProjectFileItem; 0035 using KDevelop::Path; 0036 0037 void generateChilds( ProjectBaseItem* parent, int count, int depth ) 0038 { 0039 for( int i = 0; i < 10; i++ ) { 0040 if( depth > 0 ) { 0041 auto* item = new ProjectFolderItem( QStringLiteral( "f%1" ).arg( i ), parent ); 0042 generateChilds( item, count, depth - 1 ); 0043 } else { 0044 new ProjectFileItem( QStringLiteral( "f%1" ).arg( i ), parent ); 0045 } 0046 } 0047 } 0048 0049 ProjectModelPerformanceTest::ProjectModelPerformanceTest(QWidget* parent ) 0050 : QWidget(parent) 0051 { 0052 auto * l = new QGridLayout( this ); 0053 setLayout( l ); 0054 view = new QTreeView( this ); 0055 // This is used so the treeview layout performance is not influencing the test 0056 view->setUniformRowHeights( true ); 0057 0058 auto* b = new QPushButton(QStringLiteral("Expand All"), this); 0059 connect( b, &QPushButton::clicked, view, &QTreeView::expandAll ); 0060 l->addWidget( b, 0, 0 ); 0061 b = new QPushButton( QStringLiteral("Collapse All"), this ); 0062 connect( b, &QPushButton::clicked, view, &QTreeView::collapseAll ); 0063 l->addWidget( b, 0, 1 ); 0064 b = new QPushButton( QStringLiteral("Add Small Subtree"), this ); 0065 connect( b, &QPushButton::clicked, this, &ProjectModelPerformanceTest::addSmallTree ); 0066 l->addWidget( b, 0, 2 ); 0067 b = new QPushButton( QStringLiteral("Add Big Subtree"), this ); 0068 connect( b, &QPushButton::clicked, this, &ProjectModelPerformanceTest::addBigTree ); 0069 l->addWidget( b, 0, 3 ); 0070 b = new QPushButton( QStringLiteral("Add Big Subtree in Chunks"), this ); 0071 connect( b, &QPushButton::clicked, this, &ProjectModelPerformanceTest::addBigTreeDelayed ); 0072 l->addWidget( b, 0, 4 ); 0073 0074 l->addWidget( view, 1, 0, 1, 6 ); 0075 } 0076 0077 void ProjectModelPerformanceTest::init() 0078 { 0079 QElapsedTimer timer; 0080 timer.start(); 0081 KDevelop::AutoTestShell::init(); 0082 auto* core = new KDevelop::TestCore; 0083 core->setPluginController(new KDevelop::TestPluginController(core)); 0084 core->initialize(); 0085 0086 qDebug() << "init core" << timer.elapsed(); 0087 timer.start(); 0088 0089 model = new KDevelop::ProjectModel( this ); 0090 0091 qDebug() << "create model" << timer.elapsed(); 0092 timer.start(); 0093 0094 for( int i = 0; i < INIT_WIDTH; i++ ) { 0095 auto* item = new ProjectFolderItem( nullptr, Path( QUrl::fromLocalFile( QStringLiteral( "/f%1" ).arg( i ) ) ) ); 0096 generateChilds( item, INIT_WIDTH, INIT_DEPTH ); 0097 model->appendRow( item ); 0098 } 0099 0100 qDebug() << "init model" << timer.elapsed(); 0101 timer.start(); 0102 0103 view->setModel( model ); 0104 qDebug() << "set model" << timer.elapsed(); 0105 timer.start(); 0106 0107 } 0108 0109 ProjectModelPerformanceTest::~ProjectModelPerformanceTest() 0110 { 0111 KDevelop::TestCore::shutdown(); 0112 QApplication::quit(); 0113 } 0114 0115 void ProjectModelPerformanceTest::addBigTree() 0116 { 0117 QElapsedTimer timer; 0118 timer.start(); 0119 for( int i = 0; i < BIG_WIDTH; i++ ) { 0120 auto* item = new ProjectFolderItem( nullptr, Path( QUrl::fromLocalFile( QStringLiteral( "/f%1" ).arg( i ) ) ) ); 0121 generateChilds( item, BIG_WIDTH, BIG_DEPTH ); 0122 model->appendRow( item ); 0123 } 0124 qDebug() << "addBigTree" << timer.elapsed(); 0125 } 0126 0127 void ProjectModelPerformanceTest::addBigTreeDelayed() 0128 { 0129 originalWidth = model->rowCount(); 0130 QTimer::singleShot( 0, this, &ProjectModelPerformanceTest::addItemDelayed ); 0131 } 0132 0133 void ProjectModelPerformanceTest::addItemDelayed() 0134 { 0135 QElapsedTimer timer; 0136 timer.start(); 0137 ProjectBaseItem* parent = nullptr; 0138 Path path; 0139 if( !currentParent.isEmpty() ) { 0140 parent = currentParent.top(); 0141 path = Path(parent->path(), QStringLiteral("f%1").arg(parent->rowCount())); 0142 } else { 0143 path = Path(QUrl::fromLocalFile(QStringLiteral("/f%1").arg(model->rowCount()))); 0144 } 0145 ProjectBaseItem* item = nullptr; 0146 if( currentParent.size() < BIG_DEPTH ) { 0147 item = new ProjectFolderItem(nullptr, path, parent); 0148 } else { 0149 item = new ProjectFileItem( nullptr, path, parent ); 0150 } 0151 if( currentParent.isEmpty() ) { 0152 model->appendRow( item ); 0153 } 0154 0155 // Abort/Continue conditions are: 0156 // Go one level deeper (by pushing item on stack) as long as we haven't reached the max depth or the max width 0157 // else if we've reached the max width then pop, i.e go one level up 0158 // else the next run will add a sibling to the just-generated item 0159 if( currentParent.size() < BIG_DEPTH && ( currentParent.isEmpty() || currentParent.top()->rowCount() < BIG_WIDTH ) ) { 0160 currentParent.push( item ); 0161 } else if( !currentParent.isEmpty() && currentParent.top()->rowCount() >= BIG_WIDTH ) { 0162 currentParent.pop(); 0163 } 0164 if( ( currentParent.isEmpty() && ( model->rowCount() - originalWidth ) < BIG_WIDTH ) || !currentParent.isEmpty() ) { 0165 QTimer::singleShot( 0, this, &ProjectModelPerformanceTest::addItemDelayed ); 0166 } 0167 qDebug() << "addBigTreeDelayed" << timer.elapsed(); 0168 } 0169 0170 void ProjectModelPerformanceTest::addSmallTree() 0171 { 0172 QElapsedTimer timer; 0173 timer.start(); 0174 for( int i = 0; i < SMALL_WIDTH; i++ ) { 0175 auto* item = new ProjectFolderItem( nullptr, Path(QUrl::fromLocalFile( QStringLiteral( "/f%1" ).arg( i ) )) ); 0176 generateChilds( item, SMALL_WIDTH, SMALL_DEPTH ); 0177 model->appendRow( item ); 0178 } 0179 qDebug() << "addSmallTree" << timer.elapsed(); 0180 } 0181 0182 int main( int argc, char** argv ) 0183 { 0184 QApplication a( argc, argv ); 0185 auto* w = new ProjectModelPerformanceTest; 0186 w->show(); 0187 w->setAttribute(Qt::WA_DeleteOnClose); 0188 0189 QMetaObject::invokeMethod(w, "init"); 0190 return a.exec(); 0191 } 0192 0193 #include "moc_projectmodelperformancetest.cpp"