Www
Www

Reputation: 442

How can I improve the startup time of Qt5 programs?

I recently switched to Qt5 and I noticed that initializing QApplication is taking noticeably longer (on the order of minutes) compared to Qt4.

Looking into it, the program seems to be spending its time here:

Qt5Guid.dll!QGlobalStatic<QFactoryLoader,&`anonymous namespace'::Q_QGS_directLoader::innerFunction,A0x95ca5a10::Q_QGS_directLoader::guard>::operator()() Line 129   C++
Qt5Guid.dll!QPlatformIntegrationFactory::create(const QString & platform, const QStringList & paramList, int & argc, char * * argv, const QString & platformPluginPath) Line 70 C++
Qt5Guid.dll!init_platform(const QString & pluginArgument, const QString & platformPluginPath, const QString & platformThemeName, int & argc, char * * argv) Line 1019   C++
Qt5Guid.dll!QGuiApplicationPrivate::createPlatformIntegration() Line 1176   C++
Qt5Guid.dll!QGuiApplicationPrivate::createEventDispatcher() Line 1196   C++
Qt5Widgetsd.dll!QApplicationPrivate::createEventDispatcher() Line 197   C++
Qt5Cored.dll!QCoreApplication::init() Line 769  C++
Qt5Cored.dll!QCoreApplication::QCoreApplication(QCoreApplicationPrivate & p) Line 689   C++
Qt5Guid.dll!QGuiApplication::QGuiApplication(QGuiApplicationPrivate & p) Line 570   C++
Qt5Widgetsd.dll!QApplication::QApplication(int & argc, char * * argv, int _internal) Line 569   C++

It's basically spending several minutes every startup initializing the windows platform plugin.

How can I reduce or remove this time and does anyone know what the cause might be?

I'm using Qt 5.5.1 with VS2012 64 bit.

Edit: Not sure if it's relevant, but I have QT_QPA_PLATFORM_PLUGIN_PATH="C:\Qt-5.5.1\plugins\platforms\" which is how it finds the platform plugin.

Edit2: Further investigation shows that the cause is that in the process of initializing the program, QFactoryLoader::update() scans through every file in some directories looking for a pattern. Because the directory includes the program directory it scans through the entirety of my program file (several gb).

The paths are determined by QCoreApplication::libraryPaths() which returns has 3 values:

The update() function is called 7 times in the init process, but it's actually only the first two calls that are very slow.

I've also noticed that if I call QCoreApplication::libraryPaths() before the init, then only the first two paths are returned for the first 4 update() calls, which solves the problem.

It's great that I have a solution now, but I would like to understand why this works and find a less hacky one.

Upvotes: 4

Views: 3317

Answers (3)

Pato Sanda&#241;a
Pato Sanda&#241;a

Reputation: 659

Short answer: Deploy your binary file into a subfolder.

Long answer: I had the very same issue and looking up the Qt source code, it will append the application directory in order to look up for plugins. So there is no choice but to leave the application alone in a folder unless someone do a merge request (if I have spare time, I will try to do it myself).

Upvotes: 0

Severin Pappadeux
Severin Pappadeux

Reputation: 20130

I would not start with the debugging (because, I would venture, you might have hit highly contested lock somewhere and debugging won't help much)

I would advise to start with good profiling of your code, and I know none better than tools/docs from Bruce Dawson

Start here and proceed with profiling your app

Upvotes: 0

Alexander V
Alexander V

Reputation: 8718

The answer without specific environment to quite a general question:

How can I improve the startup time of Qt5 programs?

... cannot really be given here. Most of Qt developers don't experience such delay. But we can always try to debug. So the answer is on how to debug. From what you posted the code is located at: qtbase/src/gui/kernel/qplatformintegrationfactory.cpp:

Qt5Guid.dll!QGlobalStatic<QFactoryLoader,&`anonymous namespace'::Q_QGS_directLoader::innerFunction,A0x95ca5a10::Q_QGS_directLoader::guard>::operator()() Line 129   C++
Qt5Guid.dll!QPlatformIntegrationFactory::create(const QString & platform, const QStringList & paramList, int & argc, char * * argv, const QString & platformPluginPath) Line 70 C++

It appears that the function called:

QPlatformIntegration *QPlatformIntegrationFactory::create(const QString &platform, const QStringList &paramList, int &argc, char **argv, const QString &platformPluginPath)
{
#ifndef QT_NO_LIBRARY
    // Try loading the plugin from platformPluginPath first:
    if (!platformPluginPath.isEmpty()) {
        QCoreApplication::addLibraryPath(platformPluginPath);
        if (QPlatformIntegration *ret = loadIntegration(directLoader(), platform, paramList, argc, argv))
            return ret;
    }
    if (QPlatformIntegration *ret = loadIntegration(loader(), platform, paramList, argc, argv))
        return ret;
#endif
    return 0;
}

You can either point to debug version of Qt or load symbols for Qt5Guid.dll and make the Qt source code available to debugger and/or build Qt yourself at the machine you use for debugging of your project and link the executable with it. Then put a breakpoint on line 70:

if (QPlatformIntegration *ret = loadIntegration(directLoader(), platform, paramList, argc, argv))

And then run the program and investigate what prevents the plugin from being loaded quickly. From this context it is not even clear what exact plugin it is, either it comes with Qt or a custom one.

Upvotes: 1

Related Questions