Remove application directory from QCoreApplication::libraryPaths()
ClosedPublic

Authored by fvogt on Aug 11 2017, 6:11 PM.

Details

Summary

The directory containing the main application (read through argv[0]) is
by default added to the list of paths containing libraries.
This causes various methods to iterate through all entries of the plasmashell
install location, usually /usr/bin.
By explicitly removing the path, those unnecessary lookups can be avoided,
resulting in around 100ms quicker startup on a system with 4000 entries in
/usr/bin.

Test Plan

Ran plasmashell with and without this fix, no changes except for a slightly
quicker startup and much less strace noise.

Diff Detail

Repository
R120 Plasma Workspace
Branch
libfix
Lint
No Linters Available
Unit
No Unit Test Coverage
fvogt created this revision.Aug 11 2017, 6:11 PM
Restricted Application added a project: Plasma. · View Herald TranscriptAug 11 2017, 6:11 PM

Reading through your description I think that KWin must also be affected and many, many more applications. Actually probably everything distributed in the classic "sysadmin style" (to reference a today's blog post). I'm wondering whether it would make sense to have this in either Qt directly (maybe not?) or a wrapper in KCoreAddons which can easily handle situations like run as flatpack where it's not needed or not wanted.

Anyway: +1 to the change, that sounds awesome improvement.

fvogt added a comment.Aug 11 2017, 6:42 PM

Reading through your description I think that KWin must also be affected and many, many more applications. Actually probably everything distributed in the classic "sysadmin style" (to reference a today's blog post). I'm wondering whether it would make sense to have this in either Qt directly (maybe not?) or a wrapper in KCoreAddons which can easily handle situations like run as flatpack where it's not needed or not wanted.

Anyway: +1 to the change, that sounds awesome improvement.

It gets even "better": QQmlEngines have the applicationDirPath set as first(!) entry of the importPathList as well by default, so strace gets spammed with

[pid 21876] stat("/usr/bin/QtQuick.2.1", 0x7f8faf5a42b0) = -1 ENOENT (No such file or directory)
[pid 21876] stat("/usr/bin/QtQuick.2", 0x7f8faf5a42b0) = -1 ENOENT (No such file or directory)
[pid 21876] stat("/usr/bin/QtQuick/Controls.1.0", 0x7f8faf5a42b0) = -1 ENOENT (No such file or directory)
[pid 21876] stat("/usr/bin/QtQuick.1.0/Controls", 0x7f8faf5a42b0) = -1 ENOENT (No such file or directory)

I'll look whether it's possible to override that in a sane place as well.

I would also like to see this fixed directly in Qt as well, but it's not so easy IMO.
The default addition of the path to the various path lists is only useful for applications shipped as a single directory,
not supposed to be installed linux-style. I'm not sure how Qt could distinguish those cases... At least I'm against hardcoding
blacklisted paths inside Qt.

I'll look whether it's possible to override that in a sane place as well.

KDeclarative QmlObject, maybe? I think the single QuickViewSharedEngine used in most of Plasma should already give a significant improvement.

fvogt added a comment.Aug 11 2017, 8:43 PM

I'll look whether it's possible to override that in a sane place as well.

KDeclarative QmlObject, maybe? I think the single QuickViewSharedEngine used in most of Plasma should already give a significant improvement.

I'd rather not change that in any framework, as applications linking to it can be deployed in whatever way they prefer.
IMO it should be specified by the application itself.

This diff to plasma-framework seems to work for some quick experiments (pun not intended) though:

diff --git a/src/plasmaquick/appletquickitem.cpp b/src/plasmaquick/appletquickitem.cpp
index 39facc613..29f0f7e69 100644
--- a/src/plasmaquick/appletquickitem.cpp
+++ b/src/plasmaquick/appletquickitem.cpp
@@ -66,6 +66,12 @@ void AppletQuickItemPrivate::init()
         PackageUrlInterceptor *interceptor = new PackageUrlInterceptor(qmlObject->engine(), Plasma::Package());
         qmlObject->engine()->setUrlInterceptor(interceptor);
     }
+
+    // Remove the unnecessary applicationDirPath from the front of the import path list
+    auto importPathList = qmlObject->engine()->importPathList();
+    // Only set the import path if it actually changed, we might have removed it already.
+    if (importPathList.removeAll(QCoreApplication::applicationDirPath()) > 0)
+        qmlObject->engine()->setImportPathList(importPathList);
 }
 
 void AppletQuickItemPrivate::connectLayoutAttached(QObject *item)
mart accepted this revision.Aug 17 2017, 10:01 AM
This revision is now accepted and ready to land.Aug 17 2017, 10:01 AM
This revision was automatically updated to reflect the committed changes.