Skip to content

Commit

Permalink
Don't condense profile results from duplicate layers with the same
Browse files Browse the repository at this point in the history
name into one entry in the renderer profile chart
  • Loading branch information
nyalldawson committed Oct 23, 2023
1 parent f426999 commit 6a6f233
Show file tree
Hide file tree
Showing 9 changed files with 95 additions and 44 deletions.
15 changes: 12 additions & 3 deletions python/core/auto_generated/qgsruntimeprofiler.sip.in
Original file line number Diff line number Diff line change
Expand Up @@ -64,22 +64,28 @@ Returns a list of all child groups with the specified ``parent``.
.. versionadded:: 3.14
%End

void start( const QString &name, const QString &group = "startup" );
void start( const QString &name, const QString &group = "startup", const QString &id = QString() );
%Docstring
Start a profile event with the given name.
The ``name`` of the profile event. Will have the name of
the active ``group`` appended after ending.

Since QGIS 3.34, the optional ``id`` argument can be used to provider a unique
ID to disambiguate nodes with the same ``name``.
%End

void end( const QString &group = "startup" );
%Docstring
End the current profile event.
%End

void record( const QString &name, double time, const QString &group = "startup" );
void record( const QString &name, double time, const QString &group = "startup", const QString &id = QString() );
%Docstring
Manually adds a profile event with the given name and total ``time`` (in seconds).

The optional ``id`` argument can be used to provider a unique
ID to disambiguate nodes with the same ``name``.

.. versionadded:: 3.34
%End

Expand Down Expand Up @@ -176,12 +182,15 @@ Python scripts should not use :py:class:`QgsScopedRuntimeProfile` directly. Inst
%End
public:

QgsScopedRuntimeProfile( const QString &name, const QString &group = "startup" );
QgsScopedRuntimeProfile( const QString &name, const QString &group = "startup", const QString &id = QString() );
%Docstring
Constructor for QgsScopedRuntimeProfile.

Automatically registers the operation in the :py:func:`QgsApplication.profiler()` instance
and starts recording the run time of the operation.

Since QGIS 3.34, the optional ``id`` argument can be used to provider a unique
ID to disambiguate nodes with the same ``name``.
%End

~QgsScopedRuntimeProfile();
Expand Down
2 changes: 1 addition & 1 deletion src/core/mesh/qgsmeshlayerrenderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -310,7 +310,7 @@ bool QgsMeshLayerRenderer::render()
std::unique_ptr< QgsScopedRuntimeProfile > preparingProfile;
if ( mEnableProfile )
{
profile = std::make_unique< QgsScopedRuntimeProfile >( mLayerName, QStringLiteral( "rendering" ) );
profile = std::make_unique< QgsScopedRuntimeProfile >( mLayerName, QStringLiteral( "rendering" ), layerId() );
if ( mPreparationTime > 0 )
QgsApplication::profiler()->record( QObject::tr( "Create renderer" ), mPreparationTime / 1000.0, QStringLiteral( "rendering" ) );
preparingProfile = std::make_unique< QgsScopedRuntimeProfile >( QObject::tr( "Preparing render" ), QStringLiteral( "rendering" ) );
Expand Down
2 changes: 1 addition & 1 deletion src/core/pointcloud/qgspointcloudlayerrenderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ bool QgsPointCloudLayerRenderer::render()
std::unique_ptr< QgsScopedRuntimeProfile > profile;
if ( mEnableProfile )
{
profile = std::make_unique< QgsScopedRuntimeProfile >( mLayerName, QStringLiteral( "rendering" ) );
profile = std::make_unique< QgsScopedRuntimeProfile >( mLayerName, QStringLiteral( "rendering" ), layerId() );
if ( mPreparationTime > 0 )
QgsApplication::profiler()->record( QObject::tr( "Create renderer" ), mPreparationTime / 1000.0, QStringLiteral( "rendering" ) );
}
Expand Down
77 changes: 52 additions & 25 deletions src/core/qgsruntimeprofiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,9 @@ QgsRuntimeProfiler *QgsRuntimeProfiler::sMainProfiler = nullptr;
// QgsRuntimeProfilerNode
//

QgsRuntimeProfilerNode::QgsRuntimeProfilerNode( const QString &group, const QString &name )
: mName( name )
QgsRuntimeProfilerNode::QgsRuntimeProfilerNode( const QString &group, const QString &name, const QString &id )
: mId( id )
, mName( name )
, mGroup( group )
{

Expand All @@ -42,7 +43,10 @@ QStringList QgsRuntimeProfilerNode::fullParentPath() const
{
res = mParent->fullParentPath();
const QString parentName = mParent->data( Name ).toString();
if ( !parentName.isEmpty() )
const QString parentId = mParent->data( Id ).toString();
if ( !parentId.isEmpty() )
res << parentId;
else if ( !parentName.isEmpty() )
res << parentName;
}
return res;
Expand All @@ -60,6 +64,9 @@ QVariant QgsRuntimeProfilerNode::data( int role ) const
case Group:
return mGroup;

case Id:
return mId;

case Elapsed:
return mElapsed;

Expand Down Expand Up @@ -92,11 +99,13 @@ int QgsRuntimeProfilerNode::indexOf( QgsRuntimeProfilerNode *child ) const
return -1;
}

QgsRuntimeProfilerNode *QgsRuntimeProfilerNode::child( const QString &group, const QString &name )
QgsRuntimeProfilerNode *QgsRuntimeProfilerNode::child( const QString &group, const QString &name, const QString &id )
{
for ( auto &it : mChildren )
{
if ( it->data( Group ).toString() == group && it->data( Name ).toString() == name )
if ( it->data( Group ).toString() == group
&& ( ( !id.isEmpty() && it->data( Id ) == id )
|| ( id.isEmpty() && !name.isEmpty() && it->data( Name ).toString() == name ) ) )
return it.get();
}
return nullptr;
Expand Down Expand Up @@ -203,9 +212,9 @@ QStringList QgsRuntimeProfiler::childGroups( const QString &parent, const QStrin
return res;
}

void QgsRuntimeProfiler::start( const QString &name, const QString &group )
void QgsRuntimeProfiler::start( const QString &name, const QString &group, const QString &id )
{
std::unique_ptr< QgsRuntimeProfilerNode > node = std::make_unique< QgsRuntimeProfilerNode >( group, name );
std::unique_ptr< QgsRuntimeProfilerNode > node = std::make_unique< QgsRuntimeProfilerNode >( group, name, id );
node->start();

QgsRuntimeProfilerNode *child = node.get();
Expand All @@ -226,7 +235,7 @@ void QgsRuntimeProfiler::start( const QString &name, const QString &group )
}

mCurrentStack[group].push( child );
emit started( group, child->fullParentPath(), name );
emit started( group, child->fullParentPath(), name, id );

if ( !mGroups.contains( group ) )
{
Expand Down Expand Up @@ -258,12 +267,12 @@ void QgsRuntimeProfiler::end( const QString &group )
parentIndex = parentIndex.parent();
}

emit ended( group, node->fullParentPath(), node->data( QgsRuntimeProfilerNode::Name ).toString(), node->data( QgsRuntimeProfilerNode::Elapsed ).toDouble() );
emit ended( group, node->fullParentPath(), node->data( QgsRuntimeProfilerNode::Name ).toString(), node->data( QgsRuntimeProfilerNode::Id ).toString(), node->data( QgsRuntimeProfilerNode::Elapsed ).toDouble() );
}

void QgsRuntimeProfiler::record( const QString &name, double time, const QString &group )
void QgsRuntimeProfiler::record( const QString &name, double time, const QString &group, const QString &id )
{
std::unique_ptr< QgsRuntimeProfilerNode > node = std::make_unique< QgsRuntimeProfilerNode >( group, name );
std::unique_ptr< QgsRuntimeProfilerNode > node = std::make_unique< QgsRuntimeProfilerNode >( group, name, id );

QgsRuntimeProfilerNode *child = node.get();
if ( !mCurrentStack[ group ].empty() )
Expand All @@ -282,9 +291,9 @@ void QgsRuntimeProfiler::record( const QString &name, double time, const QString
endInsertRows();
}

emit started( group, child->fullParentPath(), name );
emit started( group, child->fullParentPath(), name, id );
child->setElapsed( time );
emit ended( group, child->fullParentPath(), child->data( QgsRuntimeProfilerNode::Name ).toString(), child->data( QgsRuntimeProfilerNode::Elapsed ).toDouble() );
emit ended( group, child->fullParentPath(), child->data( QgsRuntimeProfilerNode::Name ).toString(), child->data( QgsRuntimeProfilerNode::Id ).toString(), child->data( QgsRuntimeProfilerNode::Elapsed ).toDouble() );

if ( !mGroups.contains( group ) )
{
Expand Down Expand Up @@ -443,12 +452,16 @@ QVariant QgsRuntimeProfiler::headerData( int section, Qt::Orientation orientatio
}
}

void QgsRuntimeProfiler::otherProfilerStarted( const QString &group, const QStringList &path, const QString &name )
void QgsRuntimeProfiler::otherProfilerStarted( const QString &group, const QStringList &path, const QString &name, const QString &id )
{
QgsRuntimeProfilerNode *parentNode = mRootNode.get();
for ( const QString &part : path )
{
QgsRuntimeProfilerNode *child = parentNode->child( group, part );
// part may be name or id. Prefer checking it as id
QgsRuntimeProfilerNode *child = parentNode->child( group, QString(), part );
if ( !child )
child = parentNode->child( group, part );

if ( !child )
{
std::unique_ptr< QgsRuntimeProfilerNode > newChild = std::make_unique< QgsRuntimeProfilerNode >( group, part );
Expand All @@ -466,12 +479,12 @@ void QgsRuntimeProfiler::otherProfilerStarted( const QString &group, const QStri
}
}

if ( parentNode->child( group, name ) )
if ( parentNode->child( group, name, id ) )
return;

const QModelIndex parentIndex = node2index( parentNode );
beginInsertRows( parentIndex, parentNode->childCount(), parentNode->childCount() );
parentNode->addChild( std::make_unique< QgsRuntimeProfilerNode >( group, name ) );
parentNode->addChild( std::make_unique< QgsRuntimeProfilerNode >( group, name, id ) );
endInsertRows();

if ( !mGroups.contains( group ) )
Expand All @@ -481,12 +494,16 @@ void QgsRuntimeProfiler::otherProfilerStarted( const QString &group, const QStri
}
}

void QgsRuntimeProfiler::otherProfilerEnded( const QString &group, const QStringList &path, const QString &name, double elapsed )
void QgsRuntimeProfiler::otherProfilerEnded( const QString &group, const QStringList &path, const QString &name, const QString &id, double elapsed )
{
QgsRuntimeProfilerNode *parentNode = mRootNode.get();
for ( const QString &part : path )
{
QgsRuntimeProfilerNode *child = parentNode->child( group, part );
// part may be name or id. Prefer checking it as id
QgsRuntimeProfilerNode *child = parentNode->child( group, QString(), part );
if ( !child )
child = parentNode->child( group, part );

if ( !child )
{
std::unique_ptr< QgsRuntimeProfilerNode > newChild = std::make_unique< QgsRuntimeProfilerNode >( group, part );
Expand All @@ -504,10 +521,10 @@ void QgsRuntimeProfiler::otherProfilerEnded( const QString &group, const QString
}
}

QgsRuntimeProfilerNode *destNode = parentNode->child( group, name );
QgsRuntimeProfilerNode *destNode = parentNode->child( group, name, id );
if ( !destNode )
{
std::unique_ptr< QgsRuntimeProfilerNode > node = std::make_unique< QgsRuntimeProfilerNode >( group, name );
std::unique_ptr< QgsRuntimeProfilerNode > node = std::make_unique< QgsRuntimeProfilerNode >( group, name, id );
destNode = node.get();
const QModelIndex parentIndex = node2index( parentNode );
beginInsertRows( parentIndex, parentNode->childCount(), parentNode->childCount() );
Expand Down Expand Up @@ -554,7 +571,12 @@ QgsRuntimeProfilerNode *QgsRuntimeProfiler::pathToNode( const QString &group, co
if ( part.isEmpty() )
continue;

res = res->child( group, part );
// part may be name or id. Prefer checking it as id
QgsRuntimeProfilerNode *child = res->child( group, QString(), part );
if ( !child )
child = res->child( group, part );

res = child;
if ( !res )
break;
}
Expand All @@ -566,7 +588,12 @@ QgsRuntimeProfilerNode *QgsRuntimeProfiler::pathToNode( const QString &group, co
QgsRuntimeProfilerNode *res = mRootNode.get();
for ( const QString &part : path )
{
res = res->child( group, part );
// part may be name or id. Prefer checking it as id
QgsRuntimeProfilerNode *child = res->child( group, QString(), part );
if ( !child )
child = res->child( group, part );

res = child;
if ( !res )
break;
}
Expand Down Expand Up @@ -648,10 +675,10 @@ QString QgsRuntimeProfiler::asText( const QString &group )
// QgsScopedRuntimeProfile
//

QgsScopedRuntimeProfile::QgsScopedRuntimeProfile( const QString &name, const QString &group )
QgsScopedRuntimeProfile::QgsScopedRuntimeProfile( const QString &name, const QString &group, const QString &id )
: mGroup( group )
{
QgsApplication::profiler()->start( name, mGroup );
QgsApplication::profiler()->start( name, mGroup, id );
}

QgsScopedRuntimeProfile::~QgsScopedRuntimeProfile()
Expand Down
35 changes: 25 additions & 10 deletions src/core/qgsruntimeprofiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,15 @@ class CORE_EXPORT QgsRuntimeProfilerNode
Group, //!< Node group
Elapsed, //!< Node elapsed time
ParentElapsed, //!< Total elapsed time for node's parent
Id, //!< Internal node ID (since QGIS 3.34)
};

/**
* Constructor for QgsRuntimeProfilerNode, with the specified \a group and \a name.
*
* Since QGIS 3.34 an internal \a id can be specified to disambiguate entries with duplicate names.
*/
QgsRuntimeProfilerNode( const QString &group, const QString &name );
QgsRuntimeProfilerNode( const QString &group, const QString &name, const QString &id = QString() );

//! QgsRuntimeProfilerNode cannot be copied
QgsRuntimeProfilerNode( const QgsRuntimeProfilerNode &other ) = delete;
Expand All @@ -70,6 +73,8 @@ class CORE_EXPORT QgsRuntimeProfilerNode

/**
* Returns the full path to the node's parent.
*
* This will contain node IDs if set, otherwise node names.
*/
QStringList fullParentPath() const;

Expand All @@ -96,10 +101,10 @@ class CORE_EXPORT QgsRuntimeProfilerNode
int indexOf( QgsRuntimeProfilerNode *child ) const;

/**
* Finds the child with matching \a group and \a name. Returns NULLPTR if
* Finds the child with matching \a group, \a name and \a id (since QGIS 3.34). Returns NULLPTR if
* a matching child was not found.
*/
QgsRuntimeProfilerNode *child( const QString &group, const QString &name );
QgsRuntimeProfilerNode *child( const QString &group, const QString &name, const QString &id = QString() );

/**
* Returns the child at the specified \a index.
Expand Down Expand Up @@ -151,6 +156,7 @@ class CORE_EXPORT QgsRuntimeProfilerNode
QElapsedTimer mProfileTime;
double mElapsed = 0;

QString mId;
QString mName;
QString mGroup;

Expand Down Expand Up @@ -211,8 +217,11 @@ class CORE_EXPORT QgsRuntimeProfiler : public QAbstractItemModel
* \brief Start a profile event with the given name.
* The \a name of the profile event. Will have the name of
* the active \a group appended after ending.
*
* Since QGIS 3.34, the optional \a id argument can be used to provider a unique
* ID to disambiguate nodes with the same \a name.
*/
void start( const QString &name, const QString &group = "startup" );
void start( const QString &name, const QString &group = "startup", const QString &id = QString() );

/**
* \brief End the current profile event.
Expand All @@ -222,9 +231,12 @@ class CORE_EXPORT QgsRuntimeProfiler : public QAbstractItemModel
/**
* Manually adds a profile event with the given name and total \a time (in seconds).
*
* The optional \a id argument can be used to provider a unique
* ID to disambiguate nodes with the same \a name.
*
* \since QGIS 3.34
*/
void record( const QString &name, double time, const QString &group = "startup" );
void record( const QString &name, double time, const QString &group = "startup", const QString &id = QString() );

/**
* Returns the profile time for the specified \a name.
Expand Down Expand Up @@ -281,8 +293,8 @@ class CORE_EXPORT QgsRuntimeProfiler : public QAbstractItemModel
///@cond PRIVATE
signals:

void started( const QString &group, const QStringList &path, const QString &name );
void ended( const QString &group, const QStringList &path, const QString &name, double elapsed );
void started( const QString &group, const QStringList &path, const QString &name, const QString &id );
void ended( const QString &group, const QStringList &path, const QString &name, const QString &id, double elapsed );
///@endcond
#endif

Expand All @@ -293,8 +305,8 @@ class CORE_EXPORT QgsRuntimeProfiler : public QAbstractItemModel

private slots:

void otherProfilerStarted( const QString &group, const QStringList &path, const QString &name );
void otherProfilerEnded( const QString &group, const QStringList &path, const QString &name, double elapsed );
void otherProfilerStarted( const QString &group, const QStringList &path, const QString &name, const QString &id );
void otherProfilerEnded( const QString &group, const QStringList &path, const QString &name, const QString &id, double elapsed );

private:

Expand Down Expand Up @@ -348,8 +360,11 @@ class CORE_EXPORT QgsScopedRuntimeProfile
*
* Automatically registers the operation in the QgsApplication::profiler() instance
* and starts recording the run time of the operation.
*
* Since QGIS 3.34, the optional \a id argument can be used to provider a unique
* ID to disambiguate nodes with the same \a name.
*/
QgsScopedRuntimeProfile( const QString &name, const QString &group = "startup" );
QgsScopedRuntimeProfile( const QString &name, const QString &group = "startup", const QString &id = QString() );

/**
* Records the final runtime of the operation in the profiler instance.
Expand Down
2 changes: 1 addition & 1 deletion src/core/raster/qgsrasterlayerrenderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -326,7 +326,7 @@ bool QgsRasterLayerRenderer::render()
std::unique_ptr< QgsScopedRuntimeProfile > profile;
if ( mEnableProfile )
{
profile = std::make_unique< QgsScopedRuntimeProfile >( mLayerName, QStringLiteral( "rendering" ) );
profile = std::make_unique< QgsScopedRuntimeProfile >( mLayerName, QStringLiteral( "rendering" ), layerId() );
if ( mPreparationTime > 0 )
QgsApplication::profiler()->record( QObject::tr( "Create renderer" ), mPreparationTime / 1000.0, QStringLiteral( "rendering" ) );
}
Expand Down
2 changes: 1 addition & 1 deletion src/core/tiledscene/qgstiledscenelayerrenderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ bool QgsTiledSceneLayerRenderer::render()
std::unique_ptr< QgsScopedRuntimeProfile > profile;
if ( mEnableProfile )
{
profile = std::make_unique< QgsScopedRuntimeProfile >( mLayerName, QStringLiteral( "rendering" ) );
profile = std::make_unique< QgsScopedRuntimeProfile >( mLayerName, QStringLiteral( "rendering" ), layerId() );
if ( mPreparationTime > 0 )
QgsApplication::profiler()->record( QObject::tr( "Create renderer" ), mPreparationTime / 1000.0, QStringLiteral( "rendering" ) );
}
Expand Down
Loading

0 comments on commit 6a6f233

Please sign in to comment.