Skip to content

perf(appstream): reuse metadata pool - #792

Merged
deepin-bot[bot] merged 1 commit into
linuxdeepin:masterfrom
mhduiy:fixappstream
Aug 6, 2026
Merged

perf(appstream): reuse metadata pool#792
deepin-bot[bot] merged 1 commit into
linuxdeepin:masterfrom
mhduiy:fixappstream

Conversation

@mhduiy

@mhduiy mhduiy commented Aug 6, 2026

Copy link
Copy Markdown
Contributor
  1. Load AppStream metadata once and reuse the pool for application queries.
  2. Monitor metadata changes and notify QML drag MIME bindings.
  3. Reuse the pool for compulsory and dummy package checks.

Log: Avoid repeated AppStream metadata loading during launcher item creation
Influence: Reduces launcher display latency.

perf(appstream): 复用元数据池

  1. AppStream 元数据仅加载一次,并复用数据池执行应用查询。
  2. 监听元数据变化,并通知 QML 重新计算拖拽 MIME 绑定。
  3. 必备应用和占位应用检查复用同一个数据池。

Log: 避免创建启动器应用项时重复加载 AppStream 元数据
PMS: TASK-393753
Influence: 降低启动器显示延迟。

Summary by Sourcery

Reuse a single monitored AppStream metadata pool across desktop integration logic and surface changes to QML for drag MIME recalculation.

New Features:

  • Expose a dummyPackagesRevision property from DesktopIntegration to QML to signal AppStream metadata-driven changes.
  • Allow QML drag MIME data generation to depend on AppStream metadata updates via the dummyPackagesRevision binding.

Enhancements:

  • Initialize and maintain a shared AppStream::Pool instance in DesktopIntegration for all application metadata queries instead of creating per-call pools.
  • Enable AppStream metadata monitoring and update internal revision tracking when the pool content changes.

Documentation:

  • Update SPDX copyright years in DesktopIntegration and Helper.qml headers.

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry @mhduiy, you have reached your weekly rate limit of 500000 diff characters.

Please try again later or upgrade to continue using Sourcery

@sourcery-ai

sourcery-ai Bot commented Aug 6, 2026

Copy link
Copy Markdown

Reviewer's Guide

Reuse a single AppStream::Pool instance within DesktopIntegration, expose a revision counter to QML so drag MIME bindings react to AppStream metadata changes, and adjust related methods/properties accordingly.

Sequence diagram for QML drag MIME reacting to AppStream metadata changes

sequenceDiagram
    participant Pool as AppStream_Pool
    participant DesktopIntegration
    participant HelperQml as Helper_qml

    Pool->>DesktopIntegration: changed()
    DesktopIntegration->>DesktopIntegration: ++m_dummyPackagesRevision
    DesktopIntegration-->>HelperQml: dummyPackagesChanged
    HelperQml->>HelperQml: generateDragMimeData(desktopId, dockOnly)
    HelperQml->>DesktopIntegration: dummyPackagesRevision
    DesktopIntegration-->>HelperQml: current revision
    Note over HelperQml: Binding re-evaluates drag MIME data based on updated metadata
Loading

File-Level Changes

Change Details Files
Introduce a long-lived AppStream metadata pool in DesktopIntegration and use it for compulsory and dummy package checks.
  • Add an AppStream::Pool member to DesktopIntegration and initialize it in the constructor.
  • Configure the pool with monitoring flags and load metadata once at startup, logging on failure.
  • Replace per-call AppStream::Pool construction in compulsory and dummy package checks with the shared pool instance.
desktopintegration.cpp
desktopintegration.h
Expose a dummy-packages revision property to QML and update it when AppStream metadata changes so QML bindings can re-evaluate drag MIME data.
  • Add a dummyPackagesRevision property with getter and notify signal on DesktopIntegration.
  • Increment the revision and emit the change signal when the AppStream pool reports metadata changes.
  • Reference the revision property in Helper.qml’s generateDragMimeData function to create a dependency on metadata state.
desktopintegration.cpp
desktopintegration.h
qml/Helper.qml
Update SPDX copyright years to cover 2026 in modified files.
  • Adjust the SPDX-FileCopyrightText ranges in DesktopIntegration and Helper.qml headers to extend through 2026.
desktopintegration.h
qml/Helper.qml

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

1. Load AppStream metadata once and reuse the pool for application queries.
2. Monitor metadata changes and notify QML drag MIME bindings.
3. Reuse the pool for compulsory and dummy package checks.

Log: Avoid repeated AppStream metadata loading during launcher item creation
Influence: Reduces launcher display latency.

perf(appstream): 复用元数据池

1. AppStream 元数据仅加载一次,并复用数据池执行应用查询。
2. 监听元数据变化,并通知 QML 重新计算拖拽 MIME 绑定。
3. 必备应用和占位应用检查复用同一个数据池。

Log: 避免创建启动器应用项时重复加载 AppStream 元数据
PMS: TASK-393753
Influence: 降低启动器显示延迟。
@deepin-ci-robot

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: BLumia, mhduiy

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@deepin-ci-robot

Copy link
Copy Markdown

deepin pr auto review

★ 总体评分:89分

■ 【总体评价】

代码成功将AppStream池从局部变量重构为成员变量以提升性能,但存在Qt对象值语义使用的规范性问题
逻辑正确但因QObject直接作为值成员违反Qt惯例扣11分

■ 【详细分析】

  • 1.语法逻辑(完全正确)✓

重构后的代码在构造函数中完成AppStream池的初始化与加载,在appIsCompulsoryForDesktop和appIsDummyPackage中直接复用成员变量m_appStreamPool,逻辑连贯且符合C++对象生命周期管理。QML中通过读取dummyPackagesRevision属性建立绑定依赖以触发重新评估,语法无误。

  • 2.代码质量(一般)✕

在desktopintegration.h中,将继承自QObject的AppStream::Pool类直接声明为值类型成员变量。在Qt框架中,QObject及其子类禁用了拷贝构造函数和赋值运算符,标准做法是使用指针在堆上分配。将其作为值成员虽然在此单例场景下不会触发拷贝导致的编译错误,但会隐式删除DesktopIntegration类的默认移动和拷贝语义,属于不规范的Qt代码实践。
潜在问题:破坏了宿主类的默认拷贝与移动语义;增加了头文件依赖,导致所有包含desktopintegration.h的文件均需解析AppStreamQt/pool.h,降低编译速度。
建议:将m_appStreamPool改为指针类型,在desktopintegration.h中使用前置声明,在cpp中通过new进行初始化。

  • 3.代码性能(高效)✓

彻底消除了原代码在每次调用appIsCompulsoryForDesktop和appIsDummyPackage时重复实例化Pool并执行load()带来的严重I/O与解析开销。通过FlagMonitor实现了元数据的增量监控与按需刷新,性能提升显著。

  • 4.代码安全(存在0个安全漏洞)✓

漏洞对比统计:新增漏洞 0 个,减少漏洞 0 个,持平 0 个
代码未引入外部输入执行、命令注入或内存越界等安全风险,AppStream库接口调用安全。

■ 【改进建议代码示例】

diff --git a/desktopintegration.h b/desktopintegration.h
--- a/desktopintegration.h
+++ b/desktopintegration.h
@@ -8,7 +8,7 @@
 #include <QRect>
 #include <QStandardPaths>
 #include <QtQml/qqml.h>
-#include <AppStreamQt/pool.h>
+class AppStream::Pool;
 
 class AppWiz;
 class DdeDock;
@@ -87,7 +87,7 @@ private:
     explicit DesktopIntegration(QObject * parent = nullptr);
 
     QStringList m_compulsoryAppIdList;
-    AppStream::Pool m_appStreamPool;
+    AppStream::Pool *m_appStreamPool = nullptr;
     uint m_dummyPackagesRevision = 0;
     AppWiz * m_appWizIntegration;
     DdeDock * m_dockIntegration;
diff --git a/desktopintegration.cpp b/desktopintegration.cpp
--- a/desktopintegration.cpp
+++ b/desktopintegration.cpp
@@ -17,6 +17,7 @@
 
 #include <xdgactivation.h>
 
+#include <AppStreamQt/pool.h>
 #include "appwiz.h"
 #include "ddedock.h"
 #include "appearance.h"
@@ -92,7 +93,8 @@ bool DesktopIntegration::appIsCompulsoryForDesktop(const QString &desktopId)
 
     const QString currentDE(DesktopIntegration::currentDE());
 
-    const AppStream::ComponentBox components = m_appStreamPool.componentsByLaunchable(AppStream::Launchable::KindDesktopId, desktopId);
+    const AppStream::ComponentBox components = m_appStreamPool ? m_appStreamPool->componentsByLaunchable(AppStream::Launchable::KindDesktopId, desktopId) 
+                                                               : AppStream::ComponentBox();
     for (const AppStream::Component & component : components) {
         return component.compulsoryForDesktops().contains(currentDE);
     }
@@ -104,7 +106,8 @@ bool DesktopIntegration::appIsCompulsoryForDesktop(const QString &desktopId)
 
 bool DesktopIntegration::appIsDummyPackage(const QString &desktopId)
 {
-    const AppStream::ComponentBox components = m_appStreamPool.componentsByLaunchable(AppStream::Launchable::KindDesktopId, desktopId);
+    const AppStream::ComponentBox components = m_appStreamPool ? m_appStreamPool->componentsByLaunchable(AppStream::Launchable::KindDesktopId, desktopId) 
+                                                               : AppStream::ComponentBox();
     for (const AppStream::Component & component : components) {
         return component.customValue("DDE::is_dummy_package") == "true";
     }
@@ -214,7 +217,7 @@ void DesktopIntegration::uninstallApp(const QString &desktopId)
 
 DesktopIntegration::DesktopIntegration(QObject *parent)
     : QObject(parent)
-    , m_appStreamPool(this)
+    , m_appStreamPool(new AppStream::Pool(this))
     , m_appWizIntegration(new AppWiz(this))
     , m_dockIntegration(new DdeDock(this))
     , m_appearanceIntegration(new Appearance(this))
@@ -222,10 +225,12 @@ DesktopIntegration::DesktopIntegration(QObject *parent)
 {
     qCDebug(logDesktopIntegration) << "Initializing DesktopIntegration";
-    m_appStreamPool.addFlags(AppStream::Pool::FlagMonitor);
-    if (!m_appStreamPool.load()) {
-        qCWarning(logDesktopIntegration) << "Failed to load AppStream metadata:" << m_appStreamPool.lastError();
+    if (m_appStreamPool) {
+        m_appStreamPool->addFlags(AppStream::Pool::FlagMonitor);
+        if (!m_appStreamPool->load()) {
+            qCWarning(logDesktopIntegration) << "Failed to load AppStream metadata:" << m_appStreamPool->lastError();
+        }
     }
-    connect(&m_appStreamPool, &AppStream::Pool::changed, this, [this] {
+    connect(m_appStreamPool, &AppStream::Pool::changed, this, [this] {
         ++m_dummyPackagesRevision;
         Q_EMIT dummyPackagesChanged();
     });

@mhduiy

mhduiy commented Aug 6, 2026

Copy link
Copy Markdown
Contributor Author

/forcemerge

@deepin-bot

deepin-bot Bot commented Aug 6, 2026

Copy link
Copy Markdown

This pr force merged! (status: blocked)

@deepin-bot
deepin-bot Bot merged commit 29736cf into linuxdeepin:master Aug 6, 2026
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants