Create RAII QgsScopedRuntimeProfile class and Python context manager

to ease logging of runtime profiles.

Now it's possible to do:

    with QgsRuntimeProfiler.profile('My operation'):
      # do something

to automatically handle everything required to log the operation runtime
This commit is contained in:
Nyall Dawson 2020-05-18 14:22:16 +10:00
parent 1b4dd484bf
commit a913a6aa5a
6 changed files with 95 additions and 5 deletions

View File

@ -36,6 +36,7 @@ from .additions.qgsgeometry import _geometryNonZero, mapping_geometry
from .additions.qgssettings import _qgssettings_enum_value, _qgssettings_set_enum_value, _qgssettings_flag_value
from .additions.qgstaskwrapper import QgsTaskWrapper
from .additions.readwritecontextentercategory import ReadWriteContextEnterCategory
from .additions.runtimeprofiler import ScopedRuntimeProfileContextManager
from .additions.validitycheck import check
# Injections into classes
@ -47,6 +48,7 @@ QgsProcessingFeatureSourceDefinition.__repr__ = processing_source_repr
QgsProcessingOutputLayerDefinition.__repr__ = processing_output_layer_repr
QgsProject.blockDirtying = ProjectDirtyBlocker
QgsReadWriteContext.enterCategory = ReadWriteContextEnterCategory
QgsRuntimeProfiler.profile = ScopedRuntimeProfileContextManager
QgsSettings.enumValue = _qgssettings_enum_value
QgsSettings.setEnumValue = _qgssettings_set_enum_value
QgsSettings.flagValue = _qgssettings_flag_value

View File

@ -81,6 +81,43 @@ The current total time collected in the profiler.
};
class QgsScopedRuntimeProfile
{
%Docstring
Scoped object for logging of the runtime for a single operation or group of operations.
This class automatically takes care of registering an operation in the :py:func:`QgsApplication.profiler()`
registry upon construction, and recording of the elapsed runtime upon destruction.
Python scripts should not use QgsScopedRuntimeProfile directly. Instead, use :py:func:`QgsRuntimeProfiler.profile()`
.. code-block:: python
with QgsRuntimeProfiler.profile('My operation'):
# do something
.. versionadded:: 3.14
%End
%TypeHeaderCode
#include "qgsruntimeprofiler.h"
%End
public:
QgsScopedRuntimeProfile( const QString &name );
%Docstring
Constructor for QgsScopedRuntimeProfile.
Automatically registers the operation in the QgsApplication.profiler() instance
and starts recording the run time of the operation.
%End
~QgsScopedRuntimeProfile();
};
/************************************************************************
* This file has been generated automatically from *
* *

View File

@ -14979,9 +14979,8 @@ void QgisApp::endProfile()
void QgisApp::functionProfile( void ( QgisApp::*fnc )(), QgisApp *instance, const QString &name )
{
startProfile( name );
QgsScopedRuntimeProfile profile( name );
( instance->*fnc )();
endProfile();
}
void QgisApp::mapCanvas_keyPressed( QKeyEvent *e )

View File

@ -32,6 +32,7 @@
#include "qgslogger.h"
#include "qgsmessagelog.h"
#include "qgsmessagebar.h"
#include "qgsruntimeprofiler.h"
#ifdef WITH_BINDINGS
#include "qgspythonutils.h"

View File

@ -96,10 +96,24 @@ void QgsRuntimeProfiler::clear()
double QgsRuntimeProfiler::totalTime()
{
double total = 0;
QList<QPair<QString, double> >::const_iterator it = mProfileTimes.constBegin();
for ( ; it != mProfileTimes.constEnd(); ++it )
for ( auto it = mProfileTimes.constBegin(); it != mProfileTimes.constEnd(); ++it )
{
total += ( *it ).second;
total += it->second;
}
return total;
}
//
// QgsScopedRuntimeProfile
//
QgsScopedRuntimeProfile::QgsScopedRuntimeProfile( const QString &name )
{
QgsApplication::profiler()->start( name );
}
QgsScopedRuntimeProfile::~QgsScopedRuntimeProfile()
{
QgsApplication::profiler()->end();
}

View File

@ -95,4 +95,41 @@ class CORE_EXPORT QgsRuntimeProfiler
QList< QPair< QString, double > > mProfileTimes;
};
/**
* \ingroup core
*
* Scoped object for logging of the runtime for a single operation or group of operations.
*
* This class automatically takes care of registering an operation in the QgsApplication::profiler()
* registry upon construction, and recording of the elapsed runtime upon destruction.
*
* Python scripts should not use QgsScopedRuntimeProfile directly. Instead, use QgsRuntimeProfiler.profile()
* \code{.py}
* with QgsRuntimeProfiler.profile('My operation'):
* # do something
* \endcode
*
* \since QGIS 3.14
*/
class CORE_EXPORT QgsScopedRuntimeProfile
{
public:
/**
* Constructor for QgsScopedRuntimeProfile.
*
* Automatically registers the operation in the QgsApplication::profiler() instance
* and starts recording the run time of the operation.
*/
QgsScopedRuntimeProfile( const QString &name );
/**
* Records the final runtime of the operation in the profiler instance.
*/
~QgsScopedRuntimeProfile();
};
#endif // QGSRUNTIMEPROFILER_H