20#include <QThreadStorage>
44 const QString parentName = mParent->
data(
Name ).toString();
45 if ( !parentName.isEmpty() )
77 Q_ASSERT( !
child->mParent );
78 child->mParent =
this;
80 mChildren.emplace_back( std::move(
child ) );
85 Q_ASSERT(
child->mParent ==
this );
86 const auto it = std::find_if( mChildren.begin(), mChildren.end(), [&](
const std::unique_ptr<QgsRuntimeProfilerNode> &p )
88 return p.get() == child;
90 if ( it != mChildren.end() )
91 return std::distance( mChildren.begin(), it );
97 for (
auto &it : mChildren )
99 if ( it->data(
Group ).toString() == group && it->data(
Name ).toString() == name )
107 Q_ASSERT(
static_cast< std::size_t
>( index ) < mChildren.size() );
108 return mChildren[ index ].get();
118 Q_ASSERT(
static_cast< std::size_t
>( index ) < mChildren.size() );
119 mChildren.erase( mChildren.begin() + index );
124 mProfileTime.restart();
129 mElapsed = mProfileTime.elapsed() / 1000.0;
145 for (
auto &it : mChildren )
147 if ( it->data(
Group ).toString() == group )
148 total += it->elapsed();
167 static QThreadStorage<QgsRuntimeProfiler> sInstances;
170 if ( !qApp || profiler->thread() == qApp->thread() )
171 sMainProfiler = profiler;
173 if ( !profiler->mInitialized )
174 profiler->setupConnections();
193 return QStringList();
197 for (
int i = 0; i < parentNode->
childCount(); ++i )
208 std::unique_ptr< QgsRuntimeProfilerNode > node = std::make_unique< QgsRuntimeProfilerNode >( group, name );
212 if ( !mCurrentStack[ group ].empty() )
216 const QModelIndex parentIndex = node2index(
parent );
217 beginInsertRows( parentIndex,
parent->childCount(),
parent->childCount() );
218 parent->addChild( std::move( node ) );
223 beginInsertRows( QModelIndex(), mRootNode->childCount(), mRootNode->childCount() );
224 mRootNode->addChild( std::move( node ) );
228 mCurrentStack[group].push( child );
231 if ( !mGroups.contains( group ) )
233 mGroups.insert( group );
240 if ( mCurrentStack[group].empty() )
244 mCurrentStack[group].pop();
247 const QModelIndex nodeIndex = node2index( node );
248 const QModelIndex col2Index =
index( nodeIndex.row(), 1, nodeIndex.parent() );
249 emit dataChanged( nodeIndex, nodeIndex );
250 emit dataChanged( col2Index, col2Index );
252 QModelIndex parentIndex = nodeIndex.parent();
253 while ( parentIndex.isValid() )
255 const QModelIndex parentCol2Index =
index( parentIndex.row(), 1, parentIndex.parent() );
256 emit dataChanged( parentIndex, parentIndex );
257 emit dataChanged( parentCol2Index, parentCol2Index );
258 parentIndex = parentIndex.parent();
275 for (
int row = mRootNode->childCount() - 1; row >= 0; row-- )
279 beginRemoveRows( QModelIndex(), row, row );
280 mRootNode->removeChildAt( row );
289 return node->elapsed();
296 return !mCurrentStack.value( group ).empty();
301 if ( group == QLatin1String(
"startup" ) )
302 return tr(
"Startup" );
303 else if ( group == QLatin1String(
"projectload" ) )
304 return tr(
"Project Load" );
305 else if ( group == QLatin1String(
"render" ) )
306 return tr(
"Map Render" );
329 return QModelIndex();
333 return QModelIndex();
335 return createIndex( row, column, n->
childAt( row ) );
340 if ( !child.isValid() )
341 return QModelIndex();
345 return indexOfParentNode( n->parent() );
350 return QModelIndex();
363 switch (
index.column() )
366 return node->
data( role );
372 case Qt::DisplayRole:
373 case Qt::InitialSortOrderRole:
379 return node->
data( role );
389 case Qt::DisplayRole:
391 if ( orientation == Qt::Horizontal )
398 return tr(
"Time (seconds)" );
410 return QAbstractItemModel::headerData( section, orientation, role );
414void QgsRuntimeProfiler::otherProfilerStarted(
const QString &group,
const QStringList &path,
const QString &name )
417 for (
const QString &part : path )
422 std::unique_ptr< QgsRuntimeProfilerNode > newChild = std::make_unique< QgsRuntimeProfilerNode >( group, part );
424 const QModelIndex parentIndex = node2index( parentNode );
427 parentNode->
addChild( std::move( newChild ) );
437 if ( parentNode->
child( group, name ) )
440 const QModelIndex parentIndex = node2index( parentNode );
442 parentNode->
addChild( std::make_unique< QgsRuntimeProfilerNode >( group, name ) );
445 if ( !mGroups.contains( group ) )
447 mGroups.insert( group );
452void QgsRuntimeProfiler::otherProfilerEnded(
const QString &group,
const QStringList &path,
const QString &name,
double elapsed )
455 for (
const QString &part : path )
460 std::unique_ptr< QgsRuntimeProfilerNode > newChild = std::make_unique< QgsRuntimeProfilerNode >( group, part );
462 const QModelIndex parentIndex = node2index( parentNode );
465 parentNode->
addChild( std::move( newChild ) );
478 std::unique_ptr< QgsRuntimeProfilerNode > node = std::make_unique< QgsRuntimeProfilerNode >( group, name );
479 destNode = node.get();
480 const QModelIndex parentIndex = node2index( parentNode );
482 parentNode->
addChild( std::move( node ) );
488 const QModelIndex nodeIndex = node2index( destNode );
489 const QModelIndex col2Index =
index( nodeIndex.row(), 1, nodeIndex.parent() );
490 emit dataChanged( nodeIndex, nodeIndex );
491 emit dataChanged( col2Index, col2Index );
493 QModelIndex parentIndex = nodeIndex.parent();
494 while ( parentIndex.isValid() )
496 const QModelIndex parentCol2Index =
index( parentIndex.row(), 1, parentIndex.parent() );
497 emit dataChanged( parentIndex, parentIndex );
498 emit dataChanged( parentCol2Index, parentCol2Index );
499 parentIndex = parentIndex.parent();
503void QgsRuntimeProfiler::setupConnections()
507 Q_ASSERT( sMainProfiler );
509 if ( sMainProfiler !=
this )
511 connect(
this, &QgsRuntimeProfiler::started, sMainProfiler, &QgsRuntimeProfiler::otherProfilerStarted );
512 connect(
this, &QgsRuntimeProfiler::ended, sMainProfiler, &QgsRuntimeProfiler::otherProfilerEnded );
518 const QStringList parts = path.split(
'/' );
520 for (
const QString &part : parts )
522 if ( part.isEmpty() )
525 res = res->
child( group, part );
532QgsRuntimeProfilerNode *QgsRuntimeProfiler::pathToNode(
const QString &group,
const QStringList &path )
const
535 for (
const QString &part : path )
537 res = res->
child( group, part );
546 if ( !node || !node->
parent() )
547 return QModelIndex();
549 const QModelIndex parentIndex = node2index( node->
parent() );
552 Q_ASSERT( row >= 0 );
553 return index( row, 0, parentIndex );
558 Q_ASSERT( parentNode );
561 if ( !grandParentNode )
562 return QModelIndex();
564 const int row = grandParentNode->
indexOf( parentNode );
565 Q_ASSERT( row >= 0 );
567 return createIndex( row, 0, parentNode );
572 if ( !
index.isValid() )
573 return mRootNode.get();
static QgsRuntimeProfiler * profiler()
Returns the application runtime profiler.
A node representing an entry in a QgsRuntimeProfiler.
void stop()
Stops the node's timer, recording the elapsed time automatically.
QgsRuntimeProfilerNode * child(const QString &group, const QString &name)
Finds the child with matching group and name.
int indexOf(QgsRuntimeProfilerNode *child) const
Returns the index of the specified child node.
void clear()
Clears the node, removing all its children.
QgsRuntimeProfilerNode * childAt(int index)
Returns the child at the specified index.
double elapsed() const
Returns the node's elapsed time, in seconds.
void addChild(std::unique_ptr< QgsRuntimeProfilerNode > child)
Adds a child node to this node.
void removeChildAt(int index)
Removes and deletes the child at the specified index.
double totalElapsedTimeForChildren(const QString &group) const
Returns the total elapsed time in seconds for all children of this node with matching group.
QgsRuntimeProfilerNode(const QString &group, const QString &name)
Constructor for QgsRuntimeProfilerNode, with the specified group and name.
@ Elapsed
Node elapsed time.
@ ParentElapsed
Total elapsed time for node's parent.
QgsRuntimeProfilerNode * parent()
Returns the node's parent node.
int childCount() const
Returns the number of child nodes owned by this node.
QStringList fullParentPath() const
Returns the full path to the node's parent.
void setElapsed(double time)
Manually sets the node's elapsed time, in seconds.
void start()
Starts the node timer.
QVariant data(int role=Qt::DisplayRole) const
Returns the node's data for the specified model role.
~QgsRuntimeProfilerNode()
Provides a method of recording run time profiles of operations, allowing easy recording of their over...
void groupAdded(const QString &group)
Emitted when a new group has started being profiled.
QModelIndex parent(const QModelIndex &child) const override
QVariant headerData(int section, Qt::Orientation orientation, int role=Qt::DisplayRole) const override
double profileTime(const QString &name, const QString &group="startup") const
Returns the profile time for the specified name.
QgsRuntimeProfiler()
Constructor to create a new runtime profiler.
QStringList childGroups(const QString &parent=QString(), const QString &group="startup") const
Returns a list of all child groups with the specified parent.
QModelIndex index(int row, int column, const QModelIndex &parent=QModelIndex()) const override
void end(const QString &group="startup")
End the current profile event.
int rowCount(const QModelIndex &parent=QModelIndex()) const override
void start(const QString &name, const QString &group="startup")
Start a profile event with the given name.
double totalTime(const QString &group="startup")
The current total time collected in the profiler.
bool groupIsActive(const QString &group) const
Returns true if the specified group is currently being logged, i.e.
void clear(const QString &group="startup")
clear Clear all profile data.
Q_DECL_DEPRECATED void beginGroup(const QString &name)
Begin the group for the profiler.
~QgsRuntimeProfiler() override
Q_DECL_DEPRECATED void endGroup()
End the current active group.
static QString translateGroupName(const QString &group)
Returns the translated name of a standard profile group.
QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const override
int columnCount(const QModelIndex &parent=QModelIndex()) const override
void switchTask(const QString &name)
Switches the current task managed by the scoped profile to a new task with the given name.
QgsScopedRuntimeProfile(const QString &name, const QString &group="startup")
Constructor for QgsScopedRuntimeProfile.
~QgsScopedRuntimeProfile()
Records the final runtime of the operation in the profiler instance.