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