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