如何改善Qt5程序的启动时间?

时间:2016-02-22 21:35:37

标签: c++ qt

我最近切换到Qt5,我注意到与Qt4相比,初始化QApplication的时间明显更长(大约几分钟)。

调查一下,该计划似乎是在这里花时间:

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++

每次启动初始化Windows平台插件时,基本上花费几分钟。

如何减少或消除这段时间,是否有人知道原因可能是什么?

我正在使用Qt 5.5.1和VS2012 64位。

编辑:不确定它是否相关,但我有QT_QPA_PLATFORM_PLUGIN_PATH =“C:\ Qt-5.5.1 \ plugins \ platforms \”这就是它找到平台插件的方式。

Edit2 :进一步调查显示,原因是在初始化程序的过程中,QFactoryLoader::update()会扫描某些目录中的每个文件以查找模式。因为该目录包含程序目录,所以它扫描整个程序文件(几个gb)。

路径由QCoreApplication::libraryPaths()确定,返回有3个值:

  • C:/Qt-5.5.1/plugins/platforms
  • C:/Qt-5.5.1/plugins
  • C:/ MyProject / x64 / Debug&lt; - 问题

在init进程中调用update()函数7次,但实际上只有前两次调用非常慢。

我还注意到,如果我在init之前调用QCoreApplication::libraryPaths(),那么前4个update()调用只返回前两个路径,这就解决了问题。

我现在有一个解决方案,这很棒,但我想了解为什么这个有效,并找到一个不那么笨拙的解决方案。

3 个答案:

答案 0 :(得分:2)

没有特定环境的答案是一个非常普遍的问题:

  

如何改善Qt5程序的启动时间?

......真的不能在这里给出。大多数Qt开发人员都没有遇到这种延迟。但我们总是可以尝试调试。所以答案是关于如何调试的。根据您发布的代码,代码位于: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++

看起来这个函数叫做:

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;
}

您可以指向Qt 的调试版本或加载Qt5Guid.dll的符号,并使Qt源代码可用于调试器和/或自己构建Qt在用于调试项目的机器上,并将可执行文件与其链接。然后在第70行放一个断点:

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

然后运行该程序并调查阻止插件快速加载的原因。从这个背景来看,它甚至不清楚究竟是什么插件,无论是Qt还是自定义插件。

答案 1 :(得分:1)

我不会从调试开始(因为,我会冒险,你可能会在某个地方遇到高度争议的锁定并且调试赢了很多)

我建议首先对您的代码进行良好的分析,并且我知道没有比Bruce Dawson的工具/文档更好的了解

开始here并继续分析您的应用

答案 2 :(得分:0)

简短答案:将二进制文件部署到子文件夹中。

长答案:我遇到了同样的问题,并查找了Qt源代码,它将附加应用程序目录以查找插件。因此,除非有人提出合并请求,否则别无选择,只能将应用程序放在一个文件夹中(如果我有空闲时间,我会尝试自己做)。