From c131b2459c8ce0904dac4bd9309df5f92eeb1d13 Mon Sep 17 00:00:00 2001 From: liyigang Date: Wed, 24 Jun 2026 17:25:28 +0800 Subject: [PATCH] perf(dfm-io): cache statx results in DFileInfoPrivate::attributesBySelf MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Introduce ensureStatxCached() to consolidate six independent statx syscalls into one. Cache the result in mutable member fields so that subsequent time-attribute queries reuse the same buffer. 在 attributesBySelf 中引入 ensureStatxCached() 方法,将 6 个时间 属性的重复 statx 系统调用合并为一次,结果缓存后各 case 直接读取。 Log: 优化 attributesBySelf 中 statx 调用,消除重复系统调用 Task: https://pms.uniontech.com/task-view-391003.html Influence: 查询 kTimeCreated/Modified/Access 等属性时,statx 从最多 6 次降为 1 次,减少不必要的系统调用开销。 --- src/dfm-io/dfm-io/dfileinfo.cpp | 91 ++++++++----------------- src/dfm-io/dfm-io/private/dfileinfo_p.h | 7 ++ 2 files changed, 37 insertions(+), 61 deletions(-) diff --git a/src/dfm-io/dfm-io/dfileinfo.cpp b/src/dfm-io/dfm-io/dfileinfo.cpp index 03d595be..55f89ea6 100644 --- a/src/dfm-io/dfm-io/dfileinfo.cpp +++ b/src/dfm-io/dfm-io/dfileinfo.cpp @@ -15,7 +15,6 @@ #include #include -#include #include #include @@ -281,6 +280,24 @@ void DFileInfoPrivate::queryInfoAsync(int ioPriority, DFileInfo::InitQuerierAsyn g_file_query_info_async(this->gfile, attributes, GFileQueryInfoFlags(flag), ioPriority, gcancellable, queryInfoAsyncCallback, dataOp); } +bool DFileInfoPrivate::ensureStatxCached() const +{ + if (statxCached) + return statxValid; + + statxCached = true; + + const QUrl &url = q->uri(); + if (!url.isLocalFile()) + return false; + + unsigned mask = STATX_BASIC_STATS | STATX_BTIME; + int ret = statx(AT_FDCWD, url.path().toStdString().data(), + AT_SYMLINK_NOFOLLOW | AT_NO_AUTOMOUNT, mask, &statxBuf); + statxValid = (ret == 0); + return statxValid; +} + QVariant DFileInfoPrivate::attributesBySelf(DFileInfo::AttributeID id) { QVariant retValue; @@ -295,18 +312,10 @@ QVariant DFileInfoPrivate::attributesBySelf(DFileInfo::AttributeID id) return QVariant(); uint64_t ret = g_file_info_get_attribute_uint64(gfileinfo, key.c_str()); if (ret == 0) { - struct statx statxBuffer; - unsigned mask = STATX_BASIC_STATS | STATX_BTIME; - const QUrl &url = q->uri(); - if (!url.isLocalFile()) - return QVariant(); - int ret = statx(AT_FDCWD, url.path().toStdString().data(), AT_SYMLINK_NOFOLLOW | AT_NO_AUTOMOUNT, mask, &statxBuffer); - if (ret != 0) + if (!ensureStatxCached()) return QVariant(); - return statxBuffer.stx_btime.tv_sec > 0 - ? quint64(statxBuffer.stx_btime.tv_sec) - : quint64(statxBuffer.stx_ctime.tv_sec); + return quint64(statxBuf.stx_btime.tv_sec); } return qulonglong(ret); } @@ -316,18 +325,10 @@ QVariant DFileInfoPrivate::attributesBySelf(DFileInfo::AttributeID id) return QVariant(); uint32_t ret = g_file_info_get_attribute_uint32(gfileinfo, key.c_str()); if (ret == 0) { - struct statx statxBuffer; - unsigned mask = STATX_BASIC_STATS | STATX_BTIME; - const QUrl &url = q->uri(); - if (!url.isLocalFile()) - return QVariant(); - int ret = statx(AT_FDCWD, url.path().toStdString().data(), AT_SYMLINK_NOFOLLOW | AT_NO_AUTOMOUNT, mask, &statxBuffer); - if (ret != 0) + if (!ensureStatxCached()) return QVariant(); - return statxBuffer.stx_btime.tv_nsec > 0 - ? statxBuffer.stx_btime.tv_nsec / 1000000 - : statxBuffer.stx_ctime.tv_nsec / 1000000; + return statxBuf.stx_btime.tv_nsec / 1000000; } return QVariant(ret); } @@ -337,18 +338,10 @@ QVariant DFileInfoPrivate::attributesBySelf(DFileInfo::AttributeID id) return QVariant(); uint64_t ret = g_file_info_get_attribute_uint64(gfileinfo, key.c_str()); if (ret == 0) { - struct statx statxBuffer; - unsigned mask = STATX_BASIC_STATS | STATX_BTIME; - const QUrl &url = q->uri(); - if (!url.isLocalFile()) - return QVariant(); - int ret = statx(AT_FDCWD, url.path().toStdString().data(), AT_SYMLINK_NOFOLLOW | AT_NO_AUTOMOUNT, mask, &statxBuffer); - if (ret != 0) + if (!ensureStatxCached()) return QVariant(); - return statxBuffer.stx_mtime.tv_sec > 0 - ? quint64(statxBuffer.stx_mtime.tv_sec) - : quint64(statxBuffer.stx_ctime.tv_sec); + return quint64(statxBuf.stx_mtime.tv_sec); } return qulonglong(ret); } @@ -358,18 +351,10 @@ QVariant DFileInfoPrivate::attributesBySelf(DFileInfo::AttributeID id) return QVariant(); uint32_t ret = g_file_info_get_attribute_uint32(gfileinfo, key.c_str()); if (ret == 0) { - struct statx statxBuffer; - unsigned mask = STATX_BASIC_STATS | STATX_BTIME; - const QUrl &url = q->uri(); - if (!url.isLocalFile()) - return QVariant(); - int ret = statx(AT_FDCWD, url.path().toStdString().data(), AT_SYMLINK_NOFOLLOW | AT_NO_AUTOMOUNT, mask, &statxBuffer); - if (ret != 0) + if (!ensureStatxCached()) return QVariant(); - return statxBuffer.stx_mtime.tv_nsec > 0 - ? statxBuffer.stx_mtime.tv_nsec / 1000000 - : statxBuffer.stx_ctime.tv_nsec / 1000000; + return statxBuf.stx_mtime.tv_nsec / 1000000; } return QVariant(ret); } @@ -379,18 +364,10 @@ QVariant DFileInfoPrivate::attributesBySelf(DFileInfo::AttributeID id) return QVariant(); uint64_t ret = g_file_info_get_attribute_uint64(gfileinfo, key.c_str()); if (ret == 0) { - struct statx statxBuffer; - unsigned mask = STATX_BASIC_STATS | STATX_BTIME; - const QUrl &url = q->uri(); - if (!url.isLocalFile()) - return QVariant(); - int ret = statx(AT_FDCWD, url.path().toStdString().data(), AT_SYMLINK_NOFOLLOW | AT_NO_AUTOMOUNT, mask, &statxBuffer); - if (ret != 0) + if (!ensureStatxCached()) return QVariant(); - return statxBuffer.stx_atime.tv_sec > 0 - ? quint64(statxBuffer.stx_atime.tv_sec) - : quint64(statxBuffer.stx_ctime.tv_sec); + return quint64(statxBuf.stx_atime.tv_sec); } return qulonglong(ret); } @@ -400,18 +377,10 @@ QVariant DFileInfoPrivate::attributesBySelf(DFileInfo::AttributeID id) return QVariant(); uint32_t ret = g_file_info_get_attribute_uint32(gfileinfo, key.c_str()); if (ret == 0) { - struct statx statxBuffer; - unsigned mask = STATX_BASIC_STATS | STATX_BTIME; - const QUrl &url = q->uri(); - if (!url.isLocalFile()) - return QVariant(); - int ret = statx(AT_FDCWD, url.path().toStdString().data(), AT_SYMLINK_NOFOLLOW | AT_NO_AUTOMOUNT, mask, &statxBuffer); - if (ret != 0) + if (!ensureStatxCached()) return QVariant(); - return statxBuffer.stx_atime.tv_nsec > 0 - ? statxBuffer.stx_atime.tv_nsec / 1000000 - : statxBuffer.stx_ctime.tv_nsec / 1000000; + return statxBuf.stx_atime.tv_nsec / 1000000; } return QVariant(ret); } diff --git a/src/dfm-io/dfm-io/private/dfileinfo_p.h b/src/dfm-io/dfm-io/private/dfileinfo_p.h index 348ed6df..1547a6b9 100644 --- a/src/dfm-io/dfm-io/private/dfileinfo_p.h +++ b/src/dfm-io/dfm-io/private/dfileinfo_p.h @@ -19,6 +19,7 @@ #include #include +#include BEGIN_IO_NAMESPACE @@ -55,6 +56,7 @@ class DFileInfoPrivate : public QObject, public QSharedData QVariant attributesBySelf(DFileInfo::AttributeID id); QVariant attributesFromUrl(DFileInfo::AttributeID id); void checkAndResetCancel(); + [[nodiscard]] bool ensureStatxCached() const; [[nodiscard]] DFileFuture *initQuerierAsync(int ioPriority, QObject *parent = nullptr) const; [[nodiscard]] QFuture refreshAsync(); @@ -94,6 +96,11 @@ class DFileInfoPrivate : public QObject, public QSharedData std::atomic_bool stoped { false }; std::atomic_bool fileExists { false }; QMap caches; + + // statx 缓存:6 个时间属性 case 共享一次 statx 调用,避免重复系统调用 + mutable struct statx statxBuf {}; + mutable bool statxCached { false }; + mutable bool statxValid { false }; std::atomic_bool cacheing { false }; std::atomic_bool refreshing { false }; QMutex mutex;