QGIS API Documentation 3.39.0-Master (73c886ac97c)
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#include "qgslogger.h"
17#include "qgis.h"
18#include "qgsapplication.h"
19#include <QSet>
20#include <QThreadStorage>
21
22QgsRuntimeProfiler *QgsRuntimeProfiler::sMainProfiler = nullptr;
23
24
25//
26// QgsRuntimeProfilerNode
27//
28
29QgsRuntimeProfilerNode::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
55QVariant 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
79void 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
102QgsRuntimeProfilerNode *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
151double 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
174QgsRuntimeProfiler *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
188void QgsRuntimeProfiler::beginGroup( const QString &name )
189{
190 start( name );
191}
192
194{
195 end();
196}
197
198QStringList 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
215void 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
247void 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
273void 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
305double 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
314void 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
327double QgsRuntimeProfiler::totalTime( const QString &group )
328{
329 if ( QgsRuntimeProfilerNode *node = pathToNode( group, QString() ) )
330 return node->elapsed();
331
332 return 0;
333}
334
335bool QgsRuntimeProfiler::groupIsActive( const QString &group ) const
336{
337 return !mCurrentStack.value( group ).empty();
338}
339
340QString 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
351int 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
360int QgsRuntimeProfiler::columnCount( const QModelIndex &parent ) const
361{
362 Q_UNUSED( parent )
363 return 2;
364}
365
366QModelIndex 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
379QModelIndex 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
395QVariant 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
426QVariant 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
455void 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
497void 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
552void 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
565QgsRuntimeProfilerNode *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
586QgsRuntimeProfilerNode *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
603QModelIndex 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
615QModelIndex 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
629QgsRuntimeProfilerNode *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
637void 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
658QString 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
678QgsScopedRuntimeProfile::QgsScopedRuntimeProfile( const QString &name, const QString &group, const QString &id )
679 : mGroup( group )
680{
681 QgsApplication::profiler()->start( name, mGroup, id );
682}
683
688
689void 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.
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.
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