Skip to content

compression level in clipzipplugin for improved performance#343

Merged
deepin-bot[bot] merged 3 commits intolinuxdeepin:develop/snipefrom
dengzhongyuan365-dev:pzip-cpp
Jan 15, 2026
Merged

compression level in clipzipplugin for improved performance#343
deepin-bot[bot] merged 3 commits intolinuxdeepin:develop/snipefrom
dengzhongyuan365-dev:pzip-cpp

Conversation

@dengzhongyuan365-dev
Copy link
Copy Markdown
Contributor

@dengzhongyuan365-dev dengzhongyuan365-dev commented Jan 15, 2026

feat: Enhance ZIP plugin handling in UiTools

  • Added logic to skip the pzip plugin when reading ZIP files, as it is write-only.
  • Introduced debug messages to indicate when the pzip plugin is being removed from the plugin selection process.

Log: Improve handling of pzip plugin for ZIP file reading

Summary by Sourcery

Optimize pzip-based ZIP compression and limit its usage to supported environments while ensuring it is not used for reading ZIP archives.

New Features:

  • Use a fixed fast compression level for the pzip-based clipzip plugin, independent of GUI compression settings.

Bug Fixes:

  • Treat non-normal pzip process exits as errors and make the process-finished handling compatible with both Qt5 and Qt6.
  • Avoid selecting the pzip plugin when reading ZIP files, since it is write-only.

Enhancements:

  • Restrict building and installation of the pzip/clipzip plugins to ARM + Qt6 environments via CMake configuration.
  • Improve logging for pzip execution and plugin selection with clearer informational and debug messages.

Build:

  • Gate inclusion of the pzip and clipzipplugin subdirectories on ARM + Qt6, and conditionally install the clipzip plugin only in that configuration.

- Updated CMake configuration to conditionally enable pzip and clipzipplugin for ARM architecture with Qt6.
- Improved signal-slot connections in clipzipplugin for compatibility with different Qt versions.
- Added compression level options and refined process completion handling.

Log: Enhance ARM + Qt6 support for clipzipplugin
- Added logic to skip the pzip plugin when reading ZIP files, as it is write-only.
- Introduced debug messages to indicate when the pzip plugin is being removed from the plugin selection process.

Log: Improve handling of pzip plugin for ZIP file reading
@sourcery-ai
Copy link
Copy Markdown

sourcery-ai Bot commented Jan 15, 2026

Reviewer's Guide

Updates the CliPzip (pzip) integration to favor fast compression settings, modernizes QProcess signal handling for Qt5/Qt6, limits the pzip-based plugin to ARM + Qt6 builds, and ensures the pzip plugin is only used for writing ZIPs (not reading) with clearer runtime logging.

Sequence diagram for skipping pzip plugin when reading ZIP

sequenceDiagram
    actor User
    participant UiTools
    participant PluginManager
    participant PzipPlugin
    participant LibzipPlugin

    User->>UiTools: createInterface(fileName, bWrite=false)
    UiTools->>UiTools: detect mimeType = application/zip
    UiTools->>UiTools: set removePzipFlag = true

    UiTools->>PluginManager: query offers for fileName
    PluginManager-->>UiTools: offers [PzipPlugin, LibzipPlugin, ...]

    loop iterate offers
        UiTools->>PzipPlugin: check metaData().name()
        UiTools->>UiTools: removePzipFlag && name contains pzip
        UiTools-->>PzipPlugin: skip plugin

        UiTools->>LibzipPlugin: check metaData().name()
        UiTools->>UiTools: removePzipFlag && name does not contain pzip
        UiTools-->>LibzipPlugin: select plugin
    end

    UiTools-->>User: ReadOnlyArchiveInterface using LibzipPlugin
Loading

Class diagram for updated CliPzipPlugin integration

classDiagram
    class ReadWriteArchiveInterface
    class KPtyProcess
    class QTimer

    class CliPzipPluginFactory {
        +CliPzipPluginFactory()
        +~CliPzipPluginFactory()
        +create()
    }

    class CliPzipPlugin {
        +CliPzipPlugin()
        +~CliPzipPlugin()
        +PluginFinishType extractFiles(files, options)
        +PluginFinishType addFiles(files, options)
        -void readStdout(bool handleAll)
        -void processFinished(int exitCode, QProcess::ExitStatus exitStatus)
        -void processFinished(int exitCode)
        -void deleteProcess()
        -KPtyProcess* m_process
        -QTimer* m_timer
    }

    CliPzipPluginFactory --> CliPzipPlugin
    CliPzipPlugin --|> ReadWriteArchiveInterface
    CliPzipPlugin o-- KPtyProcess : manages
    CliPzipPlugin o-- QTimer : manages

    class QProcess {
        +void start()
        +ExitStatus exitStatus()
        +signal finished(int exitCode, ExitStatus exitStatus)
        +signal finished(int exitCode)
    }

    CliPzipPlugin ..> QProcess : uses for pzip
Loading

File-Level Changes

Change Details Files
Modernize QProcess::finished signal/slot wiring and processFinished handling for Qt5/Qt6 compatibility.
  • Replace old SIGNAL/SLOT syntax with QOverload-based connect for Qt5 and function-pointer connect for Qt6 when wiring QProcess::finished to CliPzipPlugin::processFinished.
  • Split processFinished slot signature using preprocessor: Qt5 keeps (int,QProcess::ExitStatus) while Qt6 uses (int) and derives ExitStatus from QProcess.
  • Tighten completion logic so success requires exitCode == 0 and exitStatus == QProcess::NormalExit instead of only checking the exit code.
3rdparty/clipzipplugin/clipzipplugin.cpp
3rdparty/clipzipplugin/clipzipplugin.h
Tune pzip invocation for better performance and clearer logging when adding files.
  • Force pzip compression level to 1 for maximum speed and explicitly ignore GUI-provided compression level in options.
  • Adjust thread argument handling to only pass an explicit core count when iCPUTheadNum > 1, allowing pzip to use all cores by default otherwise and switching from -j to -c option.
  • Promote the startup log for pzip execution from qDebug() to qInfo() to ensure it appears in higher-level logs.
  • Add comments documenting the rationale for compression level and thread behavior choices.
3rdparty/clipzipplugin/clipzipplugin.cpp
Restrict pzip/clipzipplugin build and installation to ARM + Qt6 environments.
  • Wrap add_subdirectory(pzip) and add_subdirectory(clipzipplugin) in a CMake condition that only enables them when building for ARM/aarch64 and Qt6, with status messages for both enabled and disabled paths.
  • Guard installation of the clipzipplugin target similarly so it is only installed on ARM + Qt6 builds.
3rdparty/CMakeLists.txt
CMakeLists.txt
Ensure the pzip-based plugin is not used for reading ZIP files and improve related diagnostics.
  • When creating an archive interface, set a flag for non-write operations on ZIP mimetypes to indicate pzip should be excluded from plugin selection.
  • Skip plugins whose metaData().name() contains "pzip" when that flag is set, logging debug messages when the flag is activated and when pzip is skipped during iteration.
src/source/common/uitools.cpp
Add missing QtGlobal include to support version checks for slot overloading.
  • Include in clipzipplugin.h to use QT_VERSION_CHECK in preprocessor conditions around the processFinished slot declaration.
3rdparty/clipzipplugin/clipzipplugin.h

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

- Updated clipzipplugin to enforce a compression level of 1, prioritizing speed over user-defined settings.
- Removed the option to specify compression levels from the GUI, simplifying the configuration for optimal performance.

Log: Enhance performance by standardizing compression level in clipzipplugin

bug: https://pms.uniontech.com/bug-view-346679.html
Copy link
Copy Markdown

@sourcery-ai sourcery-ai Bot left a comment

Choose a reason for hiding this comment

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

Hey - I've found 2 issues, and left some high level feedback:

  • The plugin skipping logic relies on plugin->metaData().name().contains("pzip", Qt::CaseInsensitive), which is a bit fragile; consider matching on a more stable identifier (e.g., plugin id or exact name) to avoid accidentally skipping unrelated plugins with similar names.
  • The ARM + Qt6 condition is duplicated in both the top-level and 3rdparty CMakeLists; it may be worth centralizing this into a single option/variable or helper macro to keep the enablement logic consistent and easier to maintain.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The plugin skipping logic relies on `plugin->metaData().name().contains("pzip", Qt::CaseInsensitive)`, which is a bit fragile; consider matching on a more stable identifier (e.g., plugin id or exact name) to avoid accidentally skipping unrelated plugins with similar names.
- The `ARM + Qt6` condition is duplicated in both the top-level and `3rdparty` CMakeLists; it may be worth centralizing this into a single option/variable or helper macro to keep the enablement logic consistent and easier to maintain.

## Individual Comments

### Comment 1
<location> `3rdparty/clipzipplugin/clipzipplugin.cpp:198-202` </location>
<code_context>
+    arguments << "-l" << "1";
+    Q_UNUSED(options.iCompressionLevel);  // 忽略 GUI 传递的压缩级别
+
+    // 线程数:只有大于1时才指定,否则让 pzip 自动使用全部 CPU 核心
+    if (options.iCPUTheadNum > 1) {
+        arguments << "-c" << QString::number(options.iCPUTheadNum);
     }
</code_context>

<issue_to_address>
**suggestion (bug_risk):** The new thread-count logic changes behavior for `iCPUTheadNum == 1` and might not match the comment or user expectations.

Previously, any `iCPUTheadNum > 0` produced a `-c` option. Now, `iCPUTheadNum == 1` sends no `-c`, which (per the comment) makes pzip use all cores. So a user choosing “1 thread” in the GUI effectively gets “all cores,” not a single-threaded run. If this is intentional, consider removing the “1 thread” option from the GUI or mapping `1` to pzip’s single-thread syntax (if available). Otherwise, keep the old behavior for `== 1`.

```suggestion
    // 线程数:GUI 中设置的大于 0 的线程数都传递给 pzip
    // iCPUTheadNum <= 0 时不传 -c 参数,pzip 默认使用全部核心
    if (options.iCPUTheadNum > 0) {
        arguments << "-c" << QString::number(options.iCPUTheadNum);
    }
```
</issue_to_address>

### Comment 2
<location> `src/source/common/uitools.cpp:289-296` </location>
<code_context>
     }

+    // pzip 插件只用于压缩,不用于读取/解压
+    bool removePzipFlag = (!bWrite) && (mimeType.name() == QString("application/zip"));
+    if (removePzipFlag) {
+        qDebug() << "Setting flag to remove pzip plugin for reading zip (pzip is write-only)";
</code_context>

<issue_to_address>
**suggestion (bug_risk):** Skipping the plugin based on `mimeType` string equality and plugin name substring is somewhat brittle.

This relies on two brittle conditions: `mimeType.name() == "application/zip"` and `plugin->metaData().name().contains("pzip", Qt::CaseInsensitive)`. It may fail if other ZIP MIME types are introduced (e.g. `application/x-zip`) or if the plugin name changes or is localized. Prefer a more stable identifier (e.g. plugin ID or a dedicated metadata flag for write-only pzip), and consider broadening the ZIP MIME check if other ZIP types are supported elsewhere.

Suggested implementation:

```cpp
    // pzip 插件只用于压缩,不用于读取/解压
    //
    // 使用更稳健的 MIME 类型检测方式:通过 inherits() 支持多种 ZIP MIME 类型,
    // 避免仅依赖于单一字符串 "application/zip"。
    const bool isZipMimeType =
            mimeType.inherits(QStringLiteral("application/zip")) ||
            mimeType.inherits(QStringLiteral("application/x-zip")) ||
            mimeType.inherits(QStringLiteral("application/x-zip-compressed"));

    bool removePzipFlag = (!bWrite) && isZipMimeType;
    if (removePzipFlag) {
        qDebug() << "Setting flag to remove pzip plugin for reading zip (pzip is write-only)"
                 << "for MIME type:" << mimeType.name();
    }

```

```cpp
        // 读取 ZIP 时跳过 pzip 插件(pzip 只用于压缩)
        //
        // 优先使用稳定的插件标识符(pluginId),避免依赖名字的子串匹配。
        const auto metaData = plugin->metaData();
        const QString pluginId = metaData.pluginId();
        const QString pluginName = metaData.name();

        const bool isPzipPlugin =
                (!pluginId.isEmpty() &&
                 (pluginId.compare(QStringLiteral("pzip"), Qt::CaseInsensitive) == 0 ||
                  pluginId.compare(QStringLiteral("org.example.pzip"), Qt::CaseInsensitive) == 0)) ||
                (pluginId.isEmpty() &&
                 pluginName.compare(QStringLiteral("pzip"), Qt::CaseInsensitive) == 0);

        if (removePzipFlag && isPzipPlugin) {

```

Depending on how plugin metadata is defined in your project:

1. Ensure that the pzip plugin has a stable `pluginId` set in its metadata (e.g. `"pzip"` or `"org.example.pzip"`), and adjust the string(s) in the `pluginId.compare(...)` calls above to match the actual ID used in your plugin JSON/metadata.
2. If your plugin system does not expose `pluginId()` on `metaData`, replace `metaData.pluginId()` with the appropriate API used in your codebase for a stable identifier (for example `metaData.pluginId()` vs `metaData.id()` vs a custom property).
3. If other ZIP MIME types are supported elsewhere in the codebase, extend the `isZipMimeType` expression with those types so behavior is consistent.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

@deepin-ci-robot
Copy link
Copy Markdown

deepin pr auto review

这段代码主要进行了以下几方面的修改:

  1. pzipclipzipplugin 的编译条件限制为仅在 ARM 架构且使用 Qt6 的环境下。
  2. 修改了 clipzipplugin 的实现,以兼容 Qt5 和 Qt6 的信号槽语法。
  3. 调整了 pzip 的调用参数,增加了压缩级别和线程数的控制。
  4. 更新了插件的元数据配置文件。
  5. 修改了插件加载逻辑,使得 pzip 插件仅在写入(压缩)时使用。

以下是对这些修改的详细审查和改进建议:

1. CMakeLists.txt (3rdparty 和 根目录)

审查意见:

  • 逻辑与语法:逻辑正确。使用 CMAKE_SYSTEM_PROCESSORQT_VERSION_MAJOR 进行条件判断是标准做法。
  • 代码质量:添加了 message(STATUS ...) 是很好的实践,有助于开发者了解构建配置。
  • 代码性能:不适用。
  • 代码安全:不适用。

改进建议:

  • 考虑到 pzip 是一个可选依赖,建议在根 CMakeLists.txt 中增加一个选项(如 BUILD_PZIP_PLUGIN),允许用户手动强制开启或关闭该功能,而不仅仅依赖架构自动判断。
    option(BUILD_PZIP_PLUGIN "Build pzip plugin (default: ON on ARM+Qt6, OFF otherwise)" ON)
    
    # 逻辑调整
    if((CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64|arm") AND (QT_VERSION_MAJOR EQUAL 6) AND BUILD_PZIP_PLUGIN)
        # ...
    endif()

2. clipzipplugin.cpp 和 clipzipplugin.h

审查意见:

  • 逻辑与语法
    • Qt5/Qt6 的兼容性处理(QOverload vs 直接取地址)是正确的。
    • processFinished 在 Qt6 中的签名变化处理正确(Qt6 中 finished(int) 信号不再携带 ExitStatus,需要通过成员函数获取)。
  • 代码质量
    • 使用 Q_UNUSED 标记未使用的变量很好。
    • qDebug 改为 qInfo 对于关键流程日志是更好的选择。
  • 代码性能
    • arguments << "-l" << "1"; 强制压缩级别为 1(最快速度)。虽然符合高性能定位,但应确认这是否符合所有场景的需求(用户是否可能需要更高压缩比)。
  • 代码安全
    • processFinished 中对 m_process 的空指针检查(m_process ? ...)是很好的防御性编程。

改进建议:

  • Qt 兼容性宏:目前的 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) 写法略显冗长。建议在头文件中定义一个宏,或者使用 Qt 提供的兼容性宏(如果有)。
  • processFinished 的逻辑:在 Qt6 分支中,exitStatus 的获取依赖于 m_process。如果在 processFinished 被调用时 m_process 已经被置空(例如在析构函数中),QProcess::NormalExit 的默认值可能掩盖某些错误。虽然目前代码中 deleteProcess() 在获取状态之后调用,逻辑是安全的,但需保持警惕。
  • 压缩参数
    • 代码中 arguments << "-l" << "1"; 硬编码了压缩级别。建议检查 options 中是否包含压缩级别设置,并尝试使用它,而不是直接 Q_UNUSED。如果确实为了性能强制为 1,建议添加注释说明原因。
    • 线程数判断 if (options.iCPUTheadNum > 1) 是合理的,但建议确认 pzip 命令行工具在未指定 -c 参数时的默认行为是否真的是"使用全部 CPU 核心"。

3. kerfuffle_clipzip.json

审查意见:

  • 逻辑与语法:JSON 格式正确。添加了详细的压缩能力描述。
  • 代码质量:添加了多语言描述,支持良好。
  • 代码性能:不适用。
  • 代码安全:不适用。

改进建议:

  • CompressionLevelDefault:设置为 1。这与 C++ 代码中的硬编码一致。如果未来打算支持可调节压缩级别,这里需要动态更新或者设置一个更通用的默认值(如 6)。

4. uitools.cpp

审查意见:

  • 逻辑与语法:逻辑清晰。通过插件名称过滤来防止 pzip 用于解压,这与其作为"高性能压缩工具"的定位一致。
  • 代码质量:日志输出详细,便于调试。
  • 代码性能:字符串匹配 contains("pzip", ...) 在插件数量较少时性能影响可忽略。
  • 代码安全:不适用。

改进建议:

  • 插件识别方式:使用 plugin->metaData().name().contains("pzip") 来识别插件虽然简单,但如果未来有其他插件名称包含 "pzip" 可能会误判。
    • 建议:使用插件的 PluginId(在 JSON 中定义为 "Id": "kerfuffle_clipzip")进行判断,更加精确:
      if (removePzipFlag && plugin->metaData().pluginId() == QLatin1String("kerfuffle_clipzip")) {
          // ...
      }
    • 或者检查 JSON 中的特定字段。

总结

这段代码的修改整体上是高质量且安全的,主要目的是针对特定硬件(ARM)优化压缩性能,并适配 Qt6。主要的改进空间在于:

  1. 增强构建系统的灵活性(CMake option)。
  2. 提高插件识别的鲁棒性(使用 PluginId 而非名称模糊匹配)。
  3. 确认压缩参数的硬编码是否满足所有需求,或者未来是否需要开放配置。

@deepin-ci-robot
Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: dengzhongyuan365-dev, lzwind

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

@dengzhongyuan365-dev
Copy link
Copy Markdown
Contributor Author

/forcemerge

@deepin-bot deepin-bot Bot merged commit 91664e2 into linuxdeepin:develop/snipe Jan 15, 2026
15 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