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 );
 
  414 void 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 );
 
  452 void 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();
 
  503 void 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 );
 
  532 QgsRuntimeProfilerNode *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.
QgsRuntimeProfilerNode * parent()
Returns the node's parent node.
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.
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.