QGIS API Documentation  3.37.0-Master (a5b4d9743e8)
qgsruntimeprofiler.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsruntimeprofiler.cpp
3  ---------------------
4  begin : June 2016
5  copyright : (C) 2016 by Nathan Woodrow
6  email : woodrow dot nathan at gmail dot com
7  ***************************************************************************
8  * *
9  * This program is free software; you can redistribute it and/or modify *
10  * it under the terms of the GNU General Public License as published by *
11  * the Free Software Foundation; either version 2 of the License, or *
12  * (at your option) any later version. *
13  * *
14  ***************************************************************************/
15 #include "qgsruntimeprofiler.h"
16 #include "qgslogger.h"
17 #include "qgis.h"
18 #include "qgsapplication.h"
19 #include <QSet>
20 #include <QThreadStorage>
21 
22 QgsRuntimeProfiler *QgsRuntimeProfiler::sMainProfiler = nullptr;
23 
24 
25 //
26 // QgsRuntimeProfilerNode
27 //
28 
29 QgsRuntimeProfilerNode::QgsRuntimeProfilerNode( const QString &group, const QString &name, const QString &id )
30  : mId( id )
31  , mName( name )
32  , mGroup( group )
33 {
34 
35 }
36 
38 
40 {
41  QStringList res;
42  if ( mParent )
43  {
44  res = mParent->fullParentPath();
45  const QString parentName = mParent->data( static_cast< int >( CustomRole::Name ) ).toString();
46  const QString parentId = mParent->data( static_cast< int >( CustomRole::Id ) ).toString();
47  if ( !parentId.isEmpty() )
48  res << parentId;
49  else if ( !parentName.isEmpty() )
50  res << parentName;
51  }
52  return res;
53 }
54 
55 QVariant QgsRuntimeProfilerNode::data( int role ) const
56 {
57  switch ( role )
58  {
59  case Qt::DisplayRole:
60  case Qt::ToolTipRole:
61  case static_cast< int >( CustomRole::Name ):
62  return mName;
63 
64  case static_cast< int >( CustomRole::Group ):
65  return mGroup;
66 
67  case static_cast< int >( CustomRole::Id ):
68  return mId;
69 
70  case static_cast< int >( CustomRole::Elapsed ):
71  return mElapsed;
72 
73  case static_cast< int >( CustomRole::ParentElapsed ):
74  return mParent ? ( mParent->elapsed() > 0 ? mParent->elapsed() : mParent->totalElapsedTimeForChildren( mGroup ) ) : 0;
75  }
76  return QVariant();
77 }
78 
79 void QgsRuntimeProfilerNode::addChild( std::unique_ptr<QgsRuntimeProfilerNode> child )
80 {
81  if ( !child )
82  return;
83 
84  Q_ASSERT( !child->mParent );
85  child->mParent = this;
86 
87  mChildren.emplace_back( std::move( child ) );
88 }
89 
91 {
92  Q_ASSERT( child->mParent == this );
93  const auto it = std::find_if( mChildren.begin(), mChildren.end(), [&]( const std::unique_ptr<QgsRuntimeProfilerNode> &p )
94  {
95  return p.get() == child;
96  } );
97  if ( it != mChildren.end() )
98  return std::distance( mChildren.begin(), it );
99  return -1;
100 }
101 
102 QgsRuntimeProfilerNode *QgsRuntimeProfilerNode::child( const QString &group, const QString &name, const QString &id )
103 {
104  for ( auto &it : mChildren )
105  {
106  if ( it->data( static_cast< int >( CustomRole::Group ) ).toString() == group
107  && ( ( !id.isEmpty() && it->data( static_cast< int >( CustomRole::Id ) ) == id )
108  || ( id.isEmpty() && !name.isEmpty() && it->data( static_cast< int >( CustomRole::Name ) ).toString() == name ) ) )
109  return it.get();
110  }
111  return nullptr;
112 }
113 
115 {
116  Q_ASSERT( static_cast< std::size_t >( index ) < mChildren.size() );
117  return mChildren[ index ].get();
118 }
119 
121 {
122  mChildren.clear();
123 }
124 
126 {
127  Q_ASSERT( static_cast< std::size_t >( index ) < mChildren.size() );
128  mChildren.erase( mChildren.begin() + index );
129 }
130 
132 {
133  mProfileTime.restart();
134 }
135 
137 {
138  mElapsed = mProfileTime.elapsed() / 1000.0;
139 }
140 
142 {
143  mElapsed = time;
144 }
145 
147 {
148  return mElapsed;
149 }
150 
151 double QgsRuntimeProfilerNode::totalElapsedTimeForChildren( const QString &group ) const
152 {
153  double total = 0;
154  for ( auto &it : mChildren )
155  {
156  if ( it->data( static_cast< int >( CustomRole::Group ) ).toString() == group )
157  total += it->elapsed();
158  }
159  return total;
160 }
161 
162 //
163 // QgsRuntimeProfiler
164 //
165 
167  : mRootNode( std::make_unique< QgsRuntimeProfilerNode >( QString(), QString() ) )
168 {
169 
170 }
171 
173 
174 QgsRuntimeProfiler *QgsRuntimeProfiler::threadLocalInstance()
175 {
176  static QThreadStorage<QgsRuntimeProfiler> sInstances;
177  QgsRuntimeProfiler *profiler = &sInstances.localData();
178 
179  if ( !qApp || profiler->thread() == qApp->thread() )
180  sMainProfiler = profiler;
181 
182  if ( !profiler->mInitialized )
183  profiler->setupConnections();
184 
185  return profiler;
186 }
187 
188 void QgsRuntimeProfiler::beginGroup( const QString &name )
189 {
190  start( name );
191 }
192 
194 {
195  end();
196 }
197 
198 QStringList QgsRuntimeProfiler::childGroups( const QString &parent, const QString &group ) const
199 {
200  QgsRuntimeProfilerNode *parentNode = pathToNode( group, parent );
201  if ( !parentNode )
202  return QStringList();
203 
204  QStringList res;
205  res.reserve( parentNode->childCount() );
206  for ( int i = 0; i < parentNode->childCount(); ++i )
207  {
208  QgsRuntimeProfilerNode *child = parentNode->childAt( i );
209  if ( child->data( static_cast< int >( QgsRuntimeProfilerNode::CustomRole::Group ) ).toString() == group )
210  res << child->data( static_cast< int >( QgsRuntimeProfilerNode::CustomRole::Name ) ).toString();
211  }
212  return res;
213 }
214 
215 void QgsRuntimeProfiler::start( const QString &name, const QString &group, const QString &id )
216 {
217  std::unique_ptr< QgsRuntimeProfilerNode > node = std::make_unique< QgsRuntimeProfilerNode >( group, name, id );
218  node->start();
219 
220  QgsRuntimeProfilerNode *child = node.get();
221  if ( !mCurrentStack[ group ].empty() )
222  {
223  QgsRuntimeProfilerNode *parent = mCurrentStack[group ].top();
224 
225  const QModelIndex parentIndex = node2index( parent );
226  beginInsertRows( parentIndex, parent->childCount(), parent->childCount() );
227  parent->addChild( std::move( node ) );
228  endInsertRows();
229  }
230  else
231  {
232  beginInsertRows( QModelIndex(), mRootNode->childCount(), mRootNode->childCount() );
233  mRootNode->addChild( std::move( node ) );
234  endInsertRows();
235  }
236 
237  mCurrentStack[group].push( child );
238  emit started( group, child->fullParentPath(), name, id );
239 
240  if ( !mGroups.contains( group ) )
241  {
242  mGroups.insert( group );
243  emit groupAdded( group );
244  }
245 }
246 
247 void QgsRuntimeProfiler::end( const QString &group )
248 {
249  if ( mCurrentStack[group].empty() )
250  return;
251 
252  QgsRuntimeProfilerNode *node = mCurrentStack[group].top();
253  mCurrentStack[group].pop();
254  node->stop();
255 
256  const QModelIndex nodeIndex = node2index( node );
257  const QModelIndex col2Index = index( nodeIndex.row(), 1, nodeIndex.parent() );
258  emit dataChanged( nodeIndex, nodeIndex );
259  emit dataChanged( col2Index, col2Index );
260  // parent item has data changed too, cos the overall time elapsed will have changed!
261  QModelIndex parentIndex = nodeIndex.parent();
262  while ( parentIndex.isValid() )
263  {
264  const QModelIndex parentCol2Index = index( parentIndex.row(), 1, parentIndex.parent() );
265  emit dataChanged( parentIndex, parentIndex );
266  emit dataChanged( parentCol2Index, parentCol2Index );
267  parentIndex = parentIndex.parent();
268  }
269 
270  emit ended( group, node->fullParentPath(), node->data( static_cast< int >( QgsRuntimeProfilerNode::CustomRole::Name ) ).toString(), node->data( static_cast< int >( QgsRuntimeProfilerNode::CustomRole::Id ) ).toString(), node->data( static_cast< int >( QgsRuntimeProfilerNode::CustomRole::Elapsed ) ).toDouble() );
271 }
272 
273 void QgsRuntimeProfiler::record( const QString &name, double time, const QString &group, const QString &id )
274 {
275  std::unique_ptr< QgsRuntimeProfilerNode > node = std::make_unique< QgsRuntimeProfilerNode >( group, name, id );
276 
277  QgsRuntimeProfilerNode *child = node.get();
278  if ( !mCurrentStack[ group ].empty() )
279  {
280  QgsRuntimeProfilerNode *parent = mCurrentStack[group ].top();
281 
282  const QModelIndex parentIndex = node2index( parent );
283  beginInsertRows( parentIndex, parent->childCount(), parent->childCount() );
284  parent->addChild( std::move( node ) );
285  endInsertRows();
286  }
287  else
288  {
289  beginInsertRows( QModelIndex(), mRootNode->childCount(), mRootNode->childCount() );
290  mRootNode->addChild( std::move( node ) );
291  endInsertRows();
292  }
293 
294  emit started( group, child->fullParentPath(), name, id );
295  child->setElapsed( time );
296  emit ended( group, child->fullParentPath(), child->data( static_cast< int >( QgsRuntimeProfilerNode::CustomRole::Name ) ).toString(), child->data( static_cast< int >( QgsRuntimeProfilerNode::CustomRole::Id ) ).toString(), child->data( static_cast< int >( QgsRuntimeProfilerNode::CustomRole::Elapsed ) ).toDouble() );
297 
298  if ( !mGroups.contains( group ) )
299  {
300  mGroups.insert( group );
301  emit groupAdded( group );
302  }
303 }
304 
305 double QgsRuntimeProfiler::profileTime( const QString &name, const QString &group ) const
306 {
307  QgsRuntimeProfilerNode *node = pathToNode( group, name );
308  if ( !node )
309  return 0;
310 
311  return node->data( static_cast< int >( QgsRuntimeProfilerNode::CustomRole::Elapsed ) ).toDouble();
312 }
313 
314 void QgsRuntimeProfiler::clear( const QString &group )
315 {
316  for ( int row = mRootNode->childCount() - 1; row >= 0; row-- )
317  {
318  if ( mRootNode->childAt( row )->data( static_cast< int >( QgsRuntimeProfilerNode::CustomRole::Group ) ).toString() == group )
319  {
320  beginRemoveRows( QModelIndex(), row, row );
321  mRootNode->removeChildAt( row );
322  endRemoveRows();
323  }
324  }
325 }
326 
327 double QgsRuntimeProfiler::totalTime( const QString &group )
328 {
329  if ( QgsRuntimeProfilerNode *node = pathToNode( group, QString() ) )
330  return node->elapsed();
331 
332  return 0;
333 }
334 
335 bool QgsRuntimeProfiler::groupIsActive( const QString &group ) const
336 {
337  return !mCurrentStack.value( group ).empty();
338 }
339 
340 QString QgsRuntimeProfiler::translateGroupName( const QString &group )
341 {
342  if ( group == QLatin1String( "startup" ) )
343  return tr( "Startup" );
344  else if ( group == QLatin1String( "projectload" ) )
345  return tr( "Project Load" );
346  else if ( group == QLatin1String( "rendering" ) )
347  return tr( "Map Render" );
348  return QString();
349 }
350 
351 int QgsRuntimeProfiler::rowCount( const QModelIndex &parent ) const
352 {
353  QgsRuntimeProfilerNode *n = index2node( parent );
354  if ( !n )
355  return 0;
356 
357  return n->childCount();
358 }
359 
360 int QgsRuntimeProfiler::columnCount( const QModelIndex &parent ) const
361 {
362  Q_UNUSED( parent )
363  return 2;
364 }
365 
366 QModelIndex QgsRuntimeProfiler::index( int row, int column, const QModelIndex &parent ) const
367 {
368  if ( column < 0 || column >= columnCount( parent ) ||
369  row < 0 || row >= rowCount( parent ) )
370  return QModelIndex();
371 
372  QgsRuntimeProfilerNode *n = index2node( parent );
373  if ( !n )
374  return QModelIndex(); // have no children
375 
376  return createIndex( row, column, n->childAt( row ) );
377 }
378 
379 QModelIndex QgsRuntimeProfiler::parent( const QModelIndex &child ) const
380 {
381  if ( !child.isValid() )
382  return QModelIndex();
383 
384  if ( QgsRuntimeProfilerNode *n = index2node( child ) )
385  {
386  return indexOfParentNode( n->parent() ); // must not be null
387  }
388  else
389  {
390  Q_ASSERT( false );
391  return QModelIndex();
392  }
393 }
394 
395 QVariant QgsRuntimeProfiler::data( const QModelIndex &index, int role ) const
396 {
397  if ( !index.isValid() || index.column() > 2 )
398  return QVariant();
399 
400  QgsRuntimeProfilerNode *node = index2node( index );
401  if ( !node )
402  return QVariant();
403 
404  switch ( index.column() )
405  {
406  case 0:
407  return node->data( role );
408 
409  case 1:
410  {
411  switch ( role )
412  {
413  case Qt::DisplayRole:
414  case Qt::InitialSortOrderRole:
415  return node->data( static_cast< int >( QgsRuntimeProfilerNode::CustomRole::Elapsed ) );
416 
417  default:
418  break;
419  }
420  return node->data( role );
421  }
422  }
423  return QVariant();
424 }
425 
426 QVariant QgsRuntimeProfiler::headerData( int section, Qt::Orientation orientation, int role ) const
427 {
428  switch ( role )
429  {
430  case Qt::DisplayRole:
431  {
432  if ( orientation == Qt::Horizontal )
433  {
434  switch ( section )
435  {
436  case 0:
437  return tr( "Task" );
438  case 1:
439  return tr( "Time (seconds)" );
440  default:
441  return QVariant();
442  }
443  }
444  else
445  {
446  return QVariant();
447  }
448  }
449 
450  default:
451  return QAbstractItemModel::headerData( section, orientation, role );
452  }
453 }
454 
455 void QgsRuntimeProfiler::otherProfilerStarted( const QString &group, const QStringList &path, const QString &name, const QString &id )
456 {
457  QgsRuntimeProfilerNode *parentNode = mRootNode.get();
458  for ( const QString &part : path )
459  {
460  // part may be name or id. Prefer checking it as id
461  QgsRuntimeProfilerNode *child = parentNode->child( group, QString(), part );
462  if ( !child )
463  child = parentNode->child( group, part );
464 
465  if ( !child )
466  {
467  std::unique_ptr< QgsRuntimeProfilerNode > newChild = std::make_unique< QgsRuntimeProfilerNode >( group, part );
468 
469  const QModelIndex parentIndex = node2index( parentNode );
470  beginInsertRows( parentIndex, parentNode->childCount(), parentNode->childCount() );
471  QgsRuntimeProfilerNode *next = newChild.get();
472  parentNode->addChild( std::move( newChild ) );
473  endInsertRows();
474  parentNode = next;
475  }
476  else
477  {
478  parentNode = child;
479  }
480  }
481 
482  if ( parentNode->child( group, name, id ) )
483  return;
484 
485  const QModelIndex parentIndex = node2index( parentNode );
486  beginInsertRows( parentIndex, parentNode->childCount(), parentNode->childCount() );
487  parentNode->addChild( std::make_unique< QgsRuntimeProfilerNode >( group, name, id ) );
488  endInsertRows();
489 
490  if ( !mGroups.contains( group ) )
491  {
492  mGroups.insert( group );
493  emit groupAdded( group );
494  }
495 }
496 
497 void QgsRuntimeProfiler::otherProfilerEnded( const QString &group, const QStringList &path, const QString &name, const QString &id, double elapsed )
498 {
499  QgsRuntimeProfilerNode *parentNode = mRootNode.get();
500  for ( const QString &part : path )
501  {
502  // part may be name or id. Prefer checking it as id
503  QgsRuntimeProfilerNode *child = parentNode->child( group, QString(), part );
504  if ( !child )
505  child = parentNode->child( group, part );
506 
507  if ( !child )
508  {
509  std::unique_ptr< QgsRuntimeProfilerNode > newChild = std::make_unique< QgsRuntimeProfilerNode >( group, part );
510 
511  const QModelIndex parentIndex = node2index( parentNode );
512  beginInsertRows( parentIndex, parentNode->childCount(), parentNode->childCount() );
513  QgsRuntimeProfilerNode *next = newChild.get();
514  parentNode->addChild( std::move( newChild ) );
515  endInsertRows();
516  parentNode = next;
517  }
518  else
519  {
520  parentNode = child;
521  }
522  }
523 
524  QgsRuntimeProfilerNode *destNode = parentNode->child( group, name, id );
525  if ( !destNode )
526  {
527  std::unique_ptr< QgsRuntimeProfilerNode > node = std::make_unique< QgsRuntimeProfilerNode >( group, name, id );
528  destNode = node.get();
529  const QModelIndex parentIndex = node2index( parentNode );
530  beginInsertRows( parentIndex, parentNode->childCount(), parentNode->childCount() );
531  parentNode->addChild( std::move( node ) );
532  endInsertRows();
533  }
534 
535  destNode->setElapsed( elapsed );
536 
537  const QModelIndex nodeIndex = node2index( destNode );
538  const QModelIndex col2Index = index( nodeIndex.row(), 1, nodeIndex.parent() );
539  emit dataChanged( nodeIndex, nodeIndex );
540  emit dataChanged( col2Index, col2Index );
541  // parent item has data changed too, cos the overall time elapsed will have changed!
542  QModelIndex parentIndex = nodeIndex.parent();
543  while ( parentIndex.isValid() )
544  {
545  const QModelIndex parentCol2Index = index( parentIndex.row(), 1, parentIndex.parent() );
546  emit dataChanged( parentIndex, parentIndex );
547  emit dataChanged( parentCol2Index, parentCol2Index );
548  parentIndex = parentIndex.parent();
549  }
550 }
551 
552 void QgsRuntimeProfiler::setupConnections()
553 {
554  mInitialized = true;
555 
556  Q_ASSERT( sMainProfiler );
557 
558  if ( sMainProfiler != this )
559  {
560  connect( this, &QgsRuntimeProfiler::started, sMainProfiler, &QgsRuntimeProfiler::otherProfilerStarted );
561  connect( this, &QgsRuntimeProfiler::ended, sMainProfiler, &QgsRuntimeProfiler::otherProfilerEnded );
562  }
563 }
564 
565 QgsRuntimeProfilerNode *QgsRuntimeProfiler::pathToNode( const QString &group, const QString &path ) const
566 {
567  const QStringList parts = path.split( '/' );
568  QgsRuntimeProfilerNode *res = mRootNode.get();
569  for ( const QString &part : parts )
570  {
571  if ( part.isEmpty() )
572  continue;
573 
574  // part may be name or id. Prefer checking it as id
575  QgsRuntimeProfilerNode *child = res->child( group, QString(), part );
576  if ( !child )
577  child = res->child( group, part );
578 
579  res = child;
580  if ( !res )
581  break;
582  }
583  return res;
584 }
585 
586 QgsRuntimeProfilerNode *QgsRuntimeProfiler::pathToNode( const QString &group, const QStringList &path ) const
587 {
588  QgsRuntimeProfilerNode *res = mRootNode.get();
589  for ( const QString &part : path )
590  {
591  // part may be name or id. Prefer checking it as id
592  QgsRuntimeProfilerNode *child = res->child( group, QString(), part );
593  if ( !child )
594  child = res->child( group, part );
595 
596  res = child;
597  if ( !res )
598  break;
599  }
600  return res;
601 }
602 
603 QModelIndex QgsRuntimeProfiler::node2index( QgsRuntimeProfilerNode *node ) const
604 {
605  if ( !node || !node->parent() )
606  return QModelIndex(); // this is the only root item -> invalid index
607 
608  const QModelIndex parentIndex = node2index( node->parent() );
609 
610  const int row = node->parent()->indexOf( node );
611  Q_ASSERT( row >= 0 );
612  return index( row, 0, parentIndex );
613 }
614 
615 QModelIndex QgsRuntimeProfiler::indexOfParentNode( QgsRuntimeProfilerNode *parentNode ) const
616 {
617  Q_ASSERT( parentNode );
618 
619  QgsRuntimeProfilerNode *grandParentNode = parentNode->parent();
620  if ( !grandParentNode )
621  return QModelIndex(); // root node -> invalid index
622 
623  const int row = grandParentNode->indexOf( parentNode );
624  Q_ASSERT( row >= 0 );
625 
626  return createIndex( row, 0, parentNode );
627 }
628 
629 QgsRuntimeProfilerNode *QgsRuntimeProfiler::index2node( const QModelIndex &index ) const
630 {
631  if ( !index.isValid() )
632  return mRootNode.get();
633 
634  return reinterpret_cast<QgsRuntimeProfilerNode *>( index.internalPointer() );
635 }
636 
637 void QgsRuntimeProfiler::extractModelAsText( QStringList &lines, const QString &group, const QModelIndex &parent, int level )
638 {
639  const int rc = rowCount( parent );
640  const int cc = columnCount( parent );
641  for ( int r = 0; r < rc; r++ )
642  {
643  QModelIndex rowIndex = index( r, 0, parent );
644  if ( data( rowIndex, static_cast< int >( QgsRuntimeProfilerNode::CustomRole::Group ) ).toString() != group )
645  continue;
646 
647  QStringList cells;
648  for ( int c = 0; c < cc; c++ )
649  {
650  QModelIndex cellIndex = index( r, c, parent );
651  cells << data( cellIndex ).toString();
652  }
653  lines << QStringLiteral( "%1 %2" ).arg( QStringLiteral( "-" ).repeated( level + 1 ), cells.join( QLatin1String( ": " ) ) );
654  extractModelAsText( lines, group, rowIndex, level + 1 );
655  }
656 }
657 
658 QString QgsRuntimeProfiler::asText( const QString &group )
659 {
660  QStringList lines;
661  for ( const QString &g : std::as_const( mGroups ) )
662  {
663  if ( !group.isEmpty() && g != group )
664  continue;
665 
666  const QString groupName = translateGroupName( g );
667  lines << ( !groupName.isEmpty() ? groupName : g );
668  extractModelAsText( lines, g );
669  }
670  return lines.join( QLatin1String( "\r\n" ) );
671 }
672 
673 
674 //
675 // QgsScopedRuntimeProfile
676 //
677 
678 QgsScopedRuntimeProfile::QgsScopedRuntimeProfile( const QString &name, const QString &group, const QString &id )
679  : mGroup( group )
680 {
681  QgsApplication::profiler()->start( name, mGroup, id );
682 }
683 
685 {
686  QgsApplication::profiler()->end( mGroup );
687 }
688 
689 void QgsScopedRuntimeProfile::switchTask( const QString &name )
690 {
691  QgsApplication::profiler()->end( mGroup );
692  QgsApplication::profiler()->start( name, mGroup );
693 }
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, const QString &id=QString())
Finds the child with matching group, name and id (since QGIS 3.34).
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.
@ ParentElapsed
Total elapsed time for node's parent.
@ Id
Internal node ID (since QGIS 3.34)
QgsRuntimeProfilerNode(const QString &group, const QString &name, const QString &id=QString())
Constructor for QgsRuntimeProfilerNode, with the specified group and name.
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.
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
QString asText(const QString &group=QString())
Returns the model as a multi-line text string.
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.
void start(const QString &name, const QString &group="startup", const QString &id=QString())
Start a profile event with the given name.
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
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.
void record(const QString &name, double time, const QString &group="startup", const QString &id=QString())
Manually adds a profile event with the given name and total time (in seconds).
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()
Records the final runtime of the operation in the profiler instance.
QgsScopedRuntimeProfile(const QString &name, const QString &group="startup", const QString &id=QString())
Constructor for QgsScopedRuntimeProfile.
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into c