Skip to content

Commit f871544

Browse files
committed
[feature] Add runtime profiler class to profile code
1 parent 6258209 commit f871544

7 files changed

+311
-15
lines changed

python/core/core.sip

+1
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,7 @@
122122
%Include qgsrenderchecker.sip
123123
%Include qgsrendercontext.sip
124124
%Include qgsrunprocess.sip
125+
%Include qgsruntimeprofiler.sip
125126
%Include qgsscalecalculator.sip
126127
%Include qgsscaleexpression.sip
127128
%Include qgsscaleutils.sip

python/core/qgsruntimeprofiler.sip

+56
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
class QgsRuntimeProfiler
2+
{
3+
%TypeHeaderCode
4+
#include <qgsruntimeprofiler.h>
5+
%End
6+
public:
7+
/**
8+
* @brief Instance of the run time profiler. To use the main profiler
9+
* use this instance.
10+
* @return The instance of the run time profiler
11+
*/
12+
QgsRuntimeProfiler();
13+
14+
/**
15+
* @brief Begin the group for the profiler. Groups will append {GroupName}/ to the
16+
* front of the profile tag set using start.
17+
* @param name The name of the group.
18+
*/
19+
static QgsRuntimeProfiler * instance();
20+
21+
/**
22+
* @brief Begin the group for the profiler. Groups will append {GroupName}/ to the
23+
* front of the profile tag set using start.
24+
* @param name The name of the group.
25+
*/
26+
void beginGroup( const QString& name );
27+
28+
/**
29+
* @brief End the current active group.
30+
*/
31+
void endGroup();
32+
33+
/**
34+
* @brief Start a profile event with the given name.
35+
* @param name The name of the profile event. Will have the name of
36+
* the active group appened after ending.
37+
*/
38+
void start( const QString& name );
39+
40+
/**
41+
* @brief End the current profile event.
42+
*/
43+
void end();
44+
45+
/**
46+
* @brief clear Clear all profile data.
47+
*/
48+
void clear();
49+
50+
/**
51+
* @brief The current total time collected in the profiler.
52+
* @return The current total time collected in the profiler.
53+
*/
54+
double totalTime();
55+
56+
};

src/app/qgisapp.cpp

+95-15
Original file line numberDiff line numberDiff line change
@@ -587,14 +587,20 @@ QgisApp::QgisApp( QSplashScreen *splash, bool restorePlugins, bool skipVersionCh
587587
}
588588

589589
smInstance = this;
590+
profiler = QgsRuntimeProfiler::instance();
590591

591592
namSetup();
592593

593594
// load GUI: actions, menus, toolbars
595+
profiler->beginGroup( "qgisapp" );
596+
profiler->beginGroup( "startup" );
597+
startProfile( "Setting up UI" );
594598
setupUi( this );
599+
endProfile();
595600

596601
//////////
597602

603+
startProfile( "Checking database" );
598604
mSplash->showMessage( tr( "Checking database" ), Qt::AlignHCenter | Qt::AlignBottom );
599605
qApp->processEvents();
600606
// Do this early on before anyone else opens it and prevents us copying it
@@ -603,17 +609,22 @@ QgisApp::QgisApp( QSplashScreen *splash, bool restorePlugins, bool skipVersionCh
603609
{
604610
QMessageBox::critical( this, tr( "Private qgis.db" ), dbError );
605611
}
612+
endProfile();
606613

614+
startProfile( "Initializing authentication" );
607615
mSplash->showMessage( tr( "Initializing authentication" ), Qt::AlignHCenter | Qt::AlignBottom );
608616
qApp->processEvents();
609617
QgsAuthManager::instance()->init( QgsApplication::pluginPath() );
610618
if ( !QgsAuthManager::instance()->isDisabled() )
611619
{
612620
masterPasswordSetup();
613621
}
622+
endProfile();
614623

615624
// Create the themes folder for the user
625+
startProfile( "Creating theme folder" );
616626
QgsApplication::createThemeFolder();
627+
endProfile();
617628

618629
mSplash->showMessage( tr( "Reading settings" ), Qt::AlignHCenter | Qt::AlignBottom );
619630
qApp->processEvents();
@@ -623,18 +634,21 @@ QgisApp::QgisApp( QSplashScreen *splash, bool restorePlugins, bool skipVersionCh
623634

624635
QSettings settings;
625636

637+
startProfile( "Building style sheet" );
626638
// set up stylesheet builder and apply saved or default style options
627639
mStyleSheetBuilder = new QgisAppStyleSheet( this );
628640
connect( mStyleSheetBuilder, SIGNAL( appStyleSheetChanged( const QString& ) ),
629641
this, SLOT( setAppStyleSheet( const QString& ) ) );
630642
mStyleSheetBuilder->buildStyleSheet( mStyleSheetBuilder->defaultOptions() );
643+
endProfile();
631644

632645
QWidget *centralWidget = this->centralWidget();
633646
QGridLayout *centralLayout = new QGridLayout( centralWidget );
634647
centralWidget->setLayout( centralLayout );
635648
centralLayout->setContentsMargins( 0, 0, 0, 0 );
636649

637650
// "theMapCanvas" used to find this canonical instance later
651+
startProfile( "Creating map canvas" );
638652
mMapCanvas = new QgsMapCanvas( centralWidget, "theMapCanvas" );
639653
connect( mMapCanvas, SIGNAL( messageEmitted( const QString&, const QString&, QgsMessageBar::MessageLevel ) ),
640654
this, SLOT( displayMessage( const QString&, const QString&, QgsMessageBar::MessageLevel ) ) );
@@ -646,11 +660,15 @@ QgisApp::QgisApp( QSplashScreen *splash, bool restorePlugins, bool skipVersionCh
646660
int myGreen = settings.value( "/qgis/default_canvas_color_green", 255 ).toInt();
647661
int myBlue = settings.value( "/qgis/default_canvas_color_blue", 255 ).toInt();
648662
mMapCanvas->setCanvasColor( QColor( myRed, myGreen, myBlue ) );
663+
endProfile();
649664

650665
// what type of project to auto-open
651666
mProjOpen = settings.value( "/qgis/projOpenAtLaunch", 0 ).toInt();
652667

668+
669+
startProfile( "Welcome page" );
653670
mWelcomePage = new QgsWelcomePage( skipVersionCheck );
671+
endProfile();
654672

655673
mCentralContainer = new QStackedWidget;
656674
mCentralContainer->insertWidget( 0, mMapCanvas );
@@ -663,59 +681,75 @@ QgisApp::QgisApp( QSplashScreen *splash, bool restorePlugins, bool skipVersionCh
663681
mCentralContainer->setCurrentIndex( mProjOpen ? 0 : 1 );
664682

665683
// a bar to warn the user with non-blocking messages
684+
startProfile( "Message bar" );
666685
mInfoBar = new QgsMessageBar( centralWidget );
667686
mInfoBar->setSizePolicy( QSizePolicy::Minimum, QSizePolicy::Fixed );
668687
centralLayout->addWidget( mInfoBar, 0, 0, 1, 1 );
688+
endProfile();
669689

690+
startProfile( "User input dock" );
670691
// User Input Dock Widget
671692
mUserInputDockWidget = new QgsUserInputDockWidget( this );
672693
mUserInputDockWidget->setObjectName( "UserInputDockWidget" );
694+
endProfile();
673695

674696
//set the focus to the map canvas
675697
mMapCanvas->setFocus();
676698

699+
startProfile( "Layer tree" );
677700
mLayerTreeView = new QgsLayerTreeView( this );
678701
mLayerTreeView->setObjectName( "theLayerTreeView" ); // "theLayerTreeView" used to find this canonical instance later
702+
endProfile();
679703

680704
// create undo widget
705+
startProfile( "Undo dock" );
681706
mUndoDock = new QDockWidget( tr( "Undo/Redo Panel" ), this );
682707
mUndoWidget = new QgsUndoWidget( mUndoDock, mMapCanvas );
683708
mUndoWidget->setObjectName( "Undo" );
684709
mUndoDock->setWidget( mUndoWidget );
685710
mUndoDock->setObjectName( "undo/redo dock" );
711+
endProfile();
686712

687713
// Advanced Digitizing dock
714+
startProfile( "Advanced digitize panel" );
688715
mAdvancedDigitizingDockWidget = new QgsAdvancedDigitizingDockWidget( mMapCanvas, this );
689716
mAdvancedDigitizingDockWidget->setObjectName( "AdvancedDigitizingTools" );
717+
endProfile();
690718

691719
// Statistical Summary dock
720+
startProfile( "Stats dock" );
692721
mStatisticalSummaryDockWidget = new QgsStatisticalSummaryDockWidget( this );
693722
mStatisticalSummaryDockWidget->setObjectName( "StatistalSummaryDockWidget" );
723+
endProfile();
694724

695725
// Bookmarks dock
726+
startProfile( "Bookmarks widget" );
696727
mBookMarksDockWidget = new QgsBookmarks( this );
697728
mBookMarksDockWidget->setObjectName( "BookmarksDockWidget" );
729+
endProfile();
698730

731+
startProfile( "Snapping utils" );
699732
mSnappingUtils = new QgsMapCanvasSnappingUtils( mMapCanvas, this );
700733
mMapCanvas->setSnappingUtils( mSnappingUtils );
701734
connect( QgsProject::instance(), SIGNAL( snapSettingsChanged() ), mSnappingUtils, SLOT( readConfigFromProject() ) );
702735
connect( this, SIGNAL( projectRead() ), mSnappingUtils, SLOT( readConfigFromProject() ) );
703-
704-
createActions();
705-
createActionGroups();
706-
createMenus();
707-
createToolBars();
708-
createStatusBar();
709-
createCanvasTools();
736+
endProfile();
737+
738+
functionProfile( &QgisApp::createActions, this, "Create actions" );
739+
functionProfile( &QgisApp::createActionGroups, this, "Create action group" );
740+
functionProfile( &QgisApp::createMenus, this, "Create menus" );
741+
functionProfile( &QgisApp::createToolBars, this, "Toolbars" );
742+
functionProfile( &QgisApp::createStatusBar, this, "Status bar" );
743+
functionProfile( &QgisApp::createCanvasTools, this, "Create canvas tools" );
710744
mMapCanvas->freeze();
711-
initLayerTreeView();
712-
createOverview();
713-
createMapTips();
714-
createDecorations();
715-
readSettings();
716-
updateRecentProjectPaths();
717-
updateProjectFromTemplates();
718-
legendLayerSelectionChanged();
745+
functionProfile( &QgisApp::initLayerTreeView, this, "Init Layer tree view" );
746+
functionProfile( &QgisApp::createOverview, this, "Create overview" );
747+
functionProfile( &QgisApp::createMapTips, this, "Create map tips" );
748+
functionProfile( &QgisApp::createDecorations, this, "Create decorations" );
749+
functionProfile( &QgisApp::readSettings, this, "Read settings" );
750+
functionProfile( &QgisApp::updateRecentProjectPaths, this, "Update recent project paths" );
751+
functionProfile( &QgisApp::updateProjectFromTemplates, this, "Update project from templates" );
752+
functionProfile( &QgisApp::legendLayerSelectionChanged, this, "Legend layer selection changed" );
719753
mSaveRollbackInProgress = false;
720754

721755
QFileSystemWatcher* projectsTemplateWatcher = new QFileSystemWatcher( this );
@@ -725,11 +759,14 @@ QgisApp::QgisApp( QSplashScreen *splash, bool restorePlugins, bool skipVersionCh
725759
connect( projectsTemplateWatcher, SIGNAL( directoryChanged( QString ) ), this, SLOT( updateProjectFromTemplates() ) );
726760

727761
// initialize the plugin manager
762+
startProfile( "Plugin manager" );
728763
mPluginManager = new QgsPluginManager( this, restorePlugins );
764+
endProfile();
729765

730766
addDockWidget( Qt::LeftDockWidgetArea, mUndoDock );
731767
mUndoDock->hide();
732768

769+
startProfile( "Map Style dock" );
733770
mMapStylingDock = new QDockWidget( this );
734771
mMapStylingDock->setWindowTitle( tr( "Map Styling" ) );
735772
mMapStylingDock->setObjectName( "MapStyling" );
@@ -740,9 +777,12 @@ QgisApp::QgisApp( QSplashScreen *splash, bool restorePlugins, bool skipVersionCh
740777

741778
addDockWidget( Qt::RightDockWidgetArea, mMapStylingDock );
742779
mMapStylingDock->hide();
780+
endProfile();
743781

782+
startProfile( "Snapping dialog" );
744783
mSnappingDialog = new QgsSnappingDialog( this, mMapCanvas );
745784
mSnappingDialog->setObjectName( "SnappingOption" );
785+
endProfile();
746786

747787
mBrowserWidget = new QgsBrowserDockWidget( tr( "Browser Panel" ), this );
748788
mBrowserWidget->setObjectName( "Browser" );
@@ -864,11 +904,13 @@ QgisApp::QgisApp( QSplashScreen *splash, bool restorePlugins, bool skipVersionCh
864904

865905
if ( mPythonUtils && mPythonUtils->isEnabled() )
866906
{
907+
startProfile( "initPluginInstaller" );
867908
// initialize the plugin installer to start fetching repositories in background
868909
QgsPythonRunner::run( "import pyplugin_installer" );
869910
QgsPythonRunner::run( "pyplugin_installer.initPluginInstaller()" );
870911
// enable Python in the Plugin Manager and pass the PythonUtils to it
871912
mPluginManager->setPythonUtils( mPythonUtils );
913+
endProfile();
872914
}
873915
else if ( mActionShowPythonDialog )
874916
{
@@ -911,10 +953,14 @@ QgisApp::QgisApp( QSplashScreen *splash, bool restorePlugins, bool skipVersionCh
911953
//
912954
mSplash->showMessage( tr( "Restoring window state" ), Qt::AlignHCenter | Qt::AlignBottom );
913955
qApp->processEvents();
956+
startProfile( "Restore window state" );
914957
restoreWindowState();
958+
endProfile();
915959

916960
// do main window customization - after window state has been restored, before the window is shown
961+
startProfile( "Update customiziation on main window" );
917962
QgsCustomization::instance()->updateMainWindow( mToolbarMenu );
963+
endProfile();
918964

919965
mSplash->showMessage( tr( "QGIS Ready!" ), Qt::AlignHCenter | Qt::AlignBottom );
920966

@@ -936,8 +982,10 @@ QgisApp::QgisApp( QSplashScreen *splash, bool restorePlugins, bool skipVersionCh
936982

937983
mFullScreenMode = false;
938984
mPrevScreenModeMaximized = false;
985+
startProfile( "Show main window" );
939986
show();
940987
qApp->processEvents();
988+
endProfile();
941989

942990
mMapCanvas->freeze( false );
943991
mMapCanvas->clearExtentHistory(); // reset zoomnext/zoomlast
@@ -994,7 +1042,9 @@ QgisApp::QgisApp( QSplashScreen *splash, bool restorePlugins, bool skipVersionCh
9941042
// notify user if authentication system is disabled
9951043
( void )QgsAuthGuiUtils::isDisabled( messageBar() );
9961044

1045+
startProfile( "New project" );
9971046
fileNewBlank(); // prepare empty project, also skips any default templates from loading
1047+
endProfile();
9981048

9991049
// request notification of FileOpen events (double clicking a file icon in Mac OS X Finder)
10001050
// should come after fileNewBlank to ensure project is properly set up to receive any data source files
@@ -1004,6 +1054,19 @@ QgisApp::QgisApp( QSplashScreen *splash, bool restorePlugins, bool skipVersionCh
10041054
#ifdef ANDROID
10051055
toggleFullScreen();
10061056
#endif
1057+
profiler->endGroup();
1058+
profiler->endGroup();
1059+
1060+
QgsDebugMsg( "PROFILE TIMES" );
1061+
QgsDebugMsg( QString( "PROFILE TIMES TOTAL - %1 " ).arg( profiler->totalTime() ) );
1062+
QList<QPair<QString, double> >::const_iterator it = profiler->profileTimes().constBegin();
1063+
for ( ; it != profiler->profileTimes().constEnd(); ++it )
1064+
{
1065+
QString name = ( *it ).first;
1066+
double time = ( *it ).second;
1067+
QgsDebugMsg( QString( " - %1 - %2" ).arg( name ).arg( time ) );
1068+
}
1069+
10071070
} // QgisApp ctor
10081071

10091072
QgisApp::QgisApp()
@@ -10960,6 +11023,23 @@ void QgisApp::keyPressEvent( QKeyEvent * e )
1096011023
}
1096111024
}
1096211025

11026+
void QgisApp::startProfile( const QString& name )
11027+
{
11028+
profiler->start( name );
11029+
}
11030+
11031+
void QgisApp::endProfile()
11032+
{
11033+
profiler->end();
11034+
}
11035+
11036+
void QgisApp::functionProfile( void ( QgisApp::*fnc )(), QgisApp* instance, QString name )
11037+
{
11038+
startProfile( name );
11039+
( instance->*fnc )();
11040+
endProfile();
11041+
}
11042+
1096311043
void QgisApp::mapCanvas_keyPressed( QKeyEvent *e )
1096411044
{
1096511045
// Delete selected features when it is possible and KeyEvent was not managed by current MapTool

src/app/qgisapp.h

+7
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ class QgsDiagramProperties;
118118
#include "qgsmessagebar.h"
119119
#include "qgsbookmarks.h"
120120
#include "qgswelcomepageitemsmodel.h"
121+
#include "qgsruntimeprofiler.h"
121122

122123

123124
#include "ui_qgisapp.h"
@@ -1374,6 +1375,12 @@ class APP_EXPORT QgisApp : public QMainWindow, private Ui::MainWindow
13741375
void layerSavedAs( QgsMapLayer* l, const QString& path );
13751376

13761377
private:
1378+
void startProfile( const QString &name );
1379+
void endProfile();
1380+
void functionProfile( void ( QgisApp::*fnc )(), QgisApp *instance, QString name );
1381+
1382+
QgsRuntimeProfiler* profiler;
1383+
13771384
/** This method will open a dialog so the user can select GDAL sublayers to load
13781385
* @returns true if any items were loaded
13791386
*/

src/core/CMakeLists.txt

+2
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,7 @@ SET(QGIS_CORE_SRCS
186186
qgsrendercontext.cpp
187187
qgsrulebasedlabeling.cpp
188188
qgsrunprocess.cpp
189+
qgsruntimeprofiler.cpp
189190
qgsscalecalculator.cpp
190191
qgsscaleexpression.cpp
191192
qgsscaleutils.cpp
@@ -693,6 +694,7 @@ SET(QGIS_CORE_HDRS
693694
qgsrelation.h
694695
qgsrenderchecker.h
695696
qgsrendercontext.h
697+
qgsruntimeprofiler.h
696698
qgsscalecalculator.h
697699
qgsscaleexpression.h
698700
qgsscaleutils.h

0 commit comments

Comments
 (0)