Qtアプリのバイナリサイズを削減する(5)
Qtアプリのバイナリサイズを削減する(4) ではQt から不必要な機能をごっそり削除することで27%程度サンプルアプリのバイナリサイズを削減することができました。
今まではバイナリのサイズのみに着目してきましたが、今回は起動時間の変化を調査してみました。
Qt アプリの起動時間の最適化
基本的な方針は Qt Blog の Fast-Booting Qt Devices, Part 2: Optimizing Qt Application で紹介されています。weather アプリでは、以下の対応をしました。
- Loader を利用して優先度順に段階的に必要なものをロードしていく
- 背景
- フォントのロード
- それ以外の UI のロード
それから、最初の1フレームが表示されるまでにかかった時間を測定するため、main.cpp を少し改造しています。
if (argc > 1 && QString("-close") == argv[1]) { QQuickWindow *window = qobject_cast<QQuickWindow *>(engine.rootObjects().first()); if (window) { QObject::connect(window, &QQuickWindow::frameSwapped, [&app]() { #ifdef Q_OS_LINUX rusage usage; if (getrusage(RUSAGE_SELF, &usage) == 0) { qInfo() << usage.ru_utime.tv_sec * 1000 + usage.ru_utime.tv_usec / 1000; } #endif QMetaObject::invokeMethod(&app, "quit", Qt::QueuedConnection); }); } }
-close オプションが渡された際に、最初の1フレームが表示されたタイミングで getrusage を利用して、ユーザー空間の使用時間を表示するようにしました。
測定結果
100回の平均時間(ミリ秒)と標準偏差を示します。
-static 化で大幅に起動時間が削減されていますが、-optimize-size や -ltcg は起動時間的には指定しない方が良さそうです。-no-feature-* も起動時間の削減に貢献していますね。
-static -no-feature-…
上記の結果を受けて、-optimize-size, -ltcg を抜かしたものでも測定してみました。
ビルド方法 | shared | static | lite |
起動時間(ミリ秒) | 674 | 192 | 149 |
標準偏差 | 23 | 14 | 16 |
今回のケースでは、150ms まで削減することができました。
まとめ
デフォルトのビルドに対して、78% も起動時間を高速化することができました。
静的リンク化に伴う、動的なライブラリのリンクやシンボルの解決、プラグインのロードなどの時間の削減と、Qt Lite によるバイナリサイズの削減が大きく寄与していました。
今回は、-optimize-size や -ltcg は起動時間的にはマイナスという結果になりましたが、アプリケーションの作りや、規模、動かすハードウェアやプラットフォームによってこの結果は異なると思うので、実機環境で実際に試して、どれがベストになるのかを確認すると良いと思います。
また、今回は getrusage を利用して起動時間を計測しましたが、time (1) や GNU Time など、より正確に測れる可能性のある方法もあるかと思いますので、そこも工夫をすると良いと思います。
Qt 5.11 で導入された、新しい Qt Quick Compiler も試してみましたが、weather の場合は起動時間的にはマイナスでした。アプリケーションによっては高速化に寄与すると思います。試す場合は、Compiling QML Ahead of Time のドキュメントをご覧ください。
Qt 5.12 で導入された、Distance Field Generator は、今回の場合は改善には寄与しないと思い試しませんでした。場合によっては改善に繋がることもあります。試す場合は、Qt Distance Field Generator Manual をご覧ください。