For QGIS there is already a method to measure loading times of plugins ( qgis.utils.plugin_times):

How to tell which QGIS plugins are slow to load?

Is there something similar to measure loading times of the parts of q QGIS-project (layers, composer ...)?

I found something in the cpp part (qgsbench.cpp) https://github.com/qgis/QGIS/blob/530397c1683cc787ef90bc27e2d958779ed0d754/tests/bench/qgsbench.cpp so perhaps there is also a way to get things measured with python/pyqgis.

  • If you create a project with Python, it is possible. No idea how to profile a .qgz. Commented Dec 11, 2019 at 10:08
  • @J.Monticolo: the projects already exists and were created in QGIS. For profiling .qgs is totally fine as the .qgz is only the zipped version of .qgs and .qgd so it can be unzipped before profiling
    – Thomas B
    Commented Dec 11, 2019 at 10:23
  • I don't think you can right now but with qgis 3.15 and the functions that seem to be in the documentation of qgsproject.cpp, i think it will be quite easy. Something like : QgsApplication.instance().profiler().profileTime(name) with name being those who can be seen in qgsproject.cpp such as "Reading project file", "Updating project file", "Creating auxiliary storage", ...
    – Kalak
    Commented Aug 21, 2020 at 12:39
  • @LouisCottereau: In QGIS 3.15 this just returns me the value 0,0
    – Thomas B
    Commented Sep 8, 2020 at 9:53
  • If the new version is out, i'll try to have another look at it
    – Kalak
    Commented Sep 8, 2020 at 13:30

1 Answer 1


An answer for QGIS 3.16 (did not test on previous versions)

You have 3 possibles groups in profiler at the moment in QGIS (startup, projectload, render). You should be aware now, there is a widget with the profiler content (cf screenshot)

QGIS GUI with panel for profiler displayed

To get current used list of group, do QgsApplication.profiler().groups()

To get time for all existing measurements (default or your own)

profiler = QgsApplication.profiler()
for group in profiler.groups():
    translatedGroupName = profiler.translateGroupName(group)
    for child in profiler.childGroups('', group):
        value = profiler.profileTime(child, group)
        childGroup = profiler.childGroups(child, group)
        # group = name in the GUI combobox but human friendly
        # child = name of the first column
        # Time for execution
        print(translatedGroupName, child, value)
        if len(childGroup) > 0:
            for subGroup in childGroup:
                print(subGroup, profiler.profileTime(subGroup, group))
# Weird thing here = order when looping differs from the one in the GUI...

# For global time per group, in theory, you should do the following 
# but does not work (return 0.0)
# Instead, you may sum values in the loop above to get "right" total time
for group in profiler.groups():
    print(group, profiler.totalTime(group))

If you want your own measures with your own group

from time import sleep
profiler = QgsApplication.profiler()

profiler.start('your task name 1', 'your new group name')
# To simulate waiting time but normally, you run your custom code
profiler.end('your new group name')

profiler.start('your task name 2', 'your new group name')
# To simulate waiting time but normally, you run your custom code
profiler.end('your new group name')

# Alternate way to avoid start and end using Python context
# Drawback: you can't log in your own group but only in startup group (default)
with QgsRuntimeProfiler.profile('qwerty'):
    # Do something
  • So this works really well for the first levels, but how would you access the profile Time of a sub - child group? Ex - The 'projectload' group has a child called 'Reading map layers' that I can get a time for, but I can't seem to get a tine for each of the layers nested below it
    – mw2234
    Commented Apr 13, 2023 at 17:38
  • 1
    Try this other approach gist.github.com/ThomasG77/eafff0441de1209802edaacd56203985 but other issues like I'm unable to sort by group (could mix with current approach but would start to be messy)
    – ThomasG77
    Commented Apr 14, 2023 at 22:24
  • Oh this is definitely a new approach for me to try out. Huge thank you. I'll let you know how it goes
    – mw2234
    Commented Apr 17, 2023 at 15:40
  • This was exactly what I needed. Thank you. The row/column thing I just hadn't been able to wrap my head around before, but your example lays it out very well
    – mw2234
    Commented Apr 17, 2023 at 16:35

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.