How can I improve the startup time of Qt5 programs? - c++

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:
C:/Qt-5.5.1/plugins/platforms
C:/Qt-5.5.1/plugins
C:/MyProject/x64/Debug <-- the problem
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.

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.

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

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).

Related

Launching a second Linux program and exit current one from C/C++?

Is it possible from a C or C++ Linux program (say /usr/bin/foo), to programmatically launch another program (say /usr/bin/bar), and have foo exit normally and for bar to keep running?
system(3) isn't suitable as it blocks until the other program completes. I'd like something that returns immediately.
The programs are both GUI programs, but I suspect that isn't relevant.
Is there anything in Qt or boost::process that can help?
Is there any common Linux wrapper program I could run through system(3) to achieve this? I tried xdg-open but I don't think it's the right thing.
Basically I want the second program to "detach" from the first, and behave as if the user launched it via the system UI. (On MacOS, for example, there is an open command, so it would be like system("open /usr/bin/bar"))
With Qt, you can use bool QProcess::startDetached(const QString &program, const QStringList &arguments, const QString &workingDirectory = QString(), qint64 *pid = nullptr) as described here https://doc.qt.io/qt-5/qprocess.html#startDetached
Here is a minimal example of how to use it :
#include <QCoreApplication>
#include <QProcess>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
/*
* starting netstat with args
* in case the main event loop is exited
* netstat will be parented to init ( pid 1 ) and continue running
*/
QProcess::startDetached("/bin/netstat", QStringList() << "-pla" << "-ntuc");
return a.exec();
}
The classic way is using Fork-Exec: https://en.wikipedia.org/wiki/Fork%E2%80%93exec which is available in any Unix derived OS, including Linux. No need to add any library, framework, etc.

Qlist<QCameraInfo> causes access violation in QList destructor

I am writing a video grabbing application in c++ using Qt5. I am following their example code and looking at the documentation for getting the camera info:
http://doc.qt.io/qt-5/qcamerainfo.html
The problem I have is that after I use the prescribed technique for getting camera data (which works perfectly):
QList<QCameraInfo>cameraInfos = QCameraInfo::availableCameras();
I get an Access violation error whenever cameraInfos goes out of scope.
For example, if I do:
void readDeviceInfo(void) {
// Camera devices:
QList<QCameraInfo>cameraInfos = QCameraInfo::availableCameras()
for (QList<QCameraInfo>::Iterator it = cameraInfos.begin();
it != cameraInfos.end(); ++it)
std::cout << it->description().toStdString().c_str() << std::endl;
}
The crash occurs on the return of this function. If I do:
foreach(const QCameraInfo &ci, QCameraInfo::availableCameras());
The crash occurs in the evaluation of the foreach loop. Likewise, if I declare QList<QCameraInfo> cameraInfos as a field in a class, the crash happens when the class is destroyed. This is verified by the output of my call stack:
ntdll.dll!000000007750eef1() Unknown
kernel32.dll!00000000773c1a0a() Unknown
> VideoCapture.exe!free(void * pBlock) Line 51 C
VideoCapture.exe!QCameraInfo::`scalar deleting destructor'(unsigned int) C++
VideoCapture.exe!QList<QCameraInfo>::node_destruct(QList<QCameraInfo>::Node * from, QList<QCameraInfo>::Node * to) Line 484 C++
VideoCapture.exe!QList<QCameraInfo>::dealloc(QListData::Data * data) Line 857 C++
VideoCapture.exe!QList<QCameraInfo>::~QList<QCameraInfo>() Line 817 C++
I am using Visual Studio 2013 (windows obviously).
You need to compile Qt yourself, then run your test case under a debugger and see where it crashes. You also need a minimal, self-contained test case for this - and that must be the part of the question (SSCCE). As it is, it's more likely that you're corrupting memory elsewhere and the failure you're seeing is the outcome of a corrupted heap, not a Qt bug.
Sidebar: You need to be proficient in running small examples in Qt Creator. Arguably, the templates Qt Creator comes with aren't very good for that. You can use this template, available as Other Projects->Simple qmake, to make quick prototypes.
The following works fine for me with 1 camera on current Qt on both OS X 10.9 and Windows 10/VS 2015. The std::cout you're using is red herring, you can use qDebug() as well.
// https://github.com/KubaO/stackoverflown/tree/master/questions/camlist-37603946
#include <QtWidgets>
#include <QtMultimedia>
int main(int argc, char ** argv) {
QApplication app{argc, argv};
QComboBox combo;
QObject::connect(&combo, &QComboBox::currentTextChanged, [&]{
std::cout << combo.currentText().toStdString() << std::endl;
});
for (auto const & info : QCameraInfo::availableCameras())
combo.addItem(info.description());
combo.show();
return app.exec();
}
So after following Kuba's advice and running his test program in my environment with a freshly built Qt library, I got the same errors. Then I had the bright idea to run it in release mode rather than debug. Lo and behold, it worked perfectly, with both the freshly built Qt5 (x86, as it happened) and the pre-built binaries (64 bit) gotten from Qt's downloads page.
It seems that linking to the qt debug libraries was causing this behavior. I'm now linking to the non-debug libraries in debug mode and am nice and happy -- for the most part -- I am still a little annoyed that the qt libs suffixed with 'd' don't seem to work properly on my system. Nevertheless, I can move on with developing this project.
Thanks to all that commented and answered!

Problem :Debuging in Visual C++ 2008 for opencv C++

I am using openCV 2.1 on visual c++ 2008, I made a simple program and when I tried to debug it in an step into manner, since I want to know the source of the function but cvLoadImage, Its gives an error "the source is not found for this function " and it automatically goes to the next statement. This happens all the time for each line of the program.
I am new to this kind of setting to be specified for the debug to go into the libraries and work properly. can any one please help me on this.
the code I used is
int _tmain(int argc, _TCHAR* argv[])
{
IplImage *img = cvLoadImage("funny-pictures-cat-goes-pew.jpg");
cvNamedWindow("Image:",1);
cvShowImage("Image:",img);
cvWaitKey();
cvDestroyWindow("Image:");
cvReleaseImage(&img);
return 0;
}
I saw this on the OpenCV homepage. Did you include the headers and the picture? You might want to revise and check your code to see if it matches with the one on the bottom of http://opencv.willowgarage.com/wiki/VisualC%2B%2B_VS2010.

UnitTest++ and main

I want to give TDD a try and I've chosen the UnitTest++ framework, but the documentations is almost non-existent (to my knowledge).
My concern is this: in all the tutorials I've seen, they put UnitTest::RunAllTests() in the main() function. I'm guessing they do it only to simplify the explanation, but I wouldn't want that with my software. Where should I put UnitTest::RunAllTests() so that I can have it executed every time I build the software but not when I run it?
UnitTest::RunAllTests() should be put into the main function of a separate program, which you compile and run as part of your build process.
One thing we've done in the past is to add a command line argument which makes the main executable run all the tests and then exit. It's fairly easy to arrange some #ifdefs such that this code gets compiled out on release builds. Something like this (it's not very C++ but if you weren't parsing command line arguments already this is the simplest way to do it):
int main (int argc, char *argv[])
{
#ifdef DEBUG
if (argc > 1 && !strcmp(argv[2], "-t"))
{
return UnitTest::RunAllTests();
}
#endif
[rest of program]
}

two main in visual c++

how can I run two main Visual Studio (Visual C ++)..
I would like to have a main that represents the server and a main that is
the client and run them running on two different consoles.
how can I do?
It is possible to create two separate projects within a single Visual Studio solution. Each one can be an independent console application with its own main entrypoint. However, the simplest way to do that if you are wanting to debug both projects at the same time is to open two separate instances of Visual Studio, one with the client solution and one with the server.
Create two functions:
int server_main( int argc, char* argv[] );
int client_main( int argc, char* argv[] );
in the actual
int main( int argc, char* argv[] )
check for a command line argument ( --server or --client ) and then depending on which one is present, delegate to server_main or client_main.
When it comes to debugging, do what they've already suggested which is run two different instances of VS.
Everybody else is right in pointing out that there can be only one "main", but I think this answers what you actually wanted to ask.
You can't have two main functions. Either have separate builds with ifdef guards or a command line argument.
You have to create two separate programs. Each program will have its separate main() function.
Create a library with the shared code (assuming that's what you're after here) and create two separate binaries, one for the server and one for the client.