diff options
author | Louis du Verdier <louis.du.verdier@free.fr> | 2022-03-24 13:35:07 +0100 |
---|---|---|
committer | Louis du Verdier <louis.du.verdier@free.fr> | 2022-06-15 18:23:12 +0200 |
commit | edd983071e0a90ee8665d2f45916fb575fc25857 (patch) | |
tree | cef433e610177c4d679c1b16926591d7fded7787 /src/plugins/platforms/android | |
parent | f53f7095044275767e389d16aabad5ff7144ec9f (diff) |
Android: Improve loading speed of individual assets
This change improves the loading speed of files stored in Android assets
folder by caching the information about files already opened.
Prior to the change, when creating a QFile or QFileInfo to an asset
file, the engine would first scan all the file's directory and parent
directories in order to cache all this in FolderIterator::m_assetsCache.
Due to the nature of Android assets, it might be very slow, depending on
the number of images in this tree.
In this patch, individual file accesses will stop using FolderIterator
and will simply open what is asked, caching the information about the
resource in order to avoid to have to call the expensive
AAssetManager_open if the file is accessed again (e.g. by QFileInfo).
Fixes: QTBUG-101161
Change-Id: Iaedf4cdf83d5116053b51895a6795d43bc60f942
Pick-to: 6.4 6.3 6.2 5.15
Reviewed-by: Rami Potinkara <rami.potinkara@qt.io>
Reviewed-by: Ville Voutilainen <ville.voutilainen@qt.io>
Diffstat (limited to 'src/plugins/platforms/android')
-rw-r--r-- | src/plugins/platforms/android/qandroidassetsfileenginehandler.cpp | 64 |
1 files changed, 46 insertions, 18 deletions
diff --git a/src/plugins/platforms/android/qandroidassetsfileenginehandler.cpp b/src/plugins/platforms/android/qandroidassetsfileenginehandler.cpp index a25aa673d3..165f953357 100644 --- a/src/plugins/platforms/android/qandroidassetsfileenginehandler.cpp +++ b/src/plugins/platforms/android/qandroidassetsfileenginehandler.cpp @@ -231,9 +231,10 @@ public: { Q_UNUSED(permissions); - if (m_isFolder || (openMode & QIODevice::WriteOnly)) + if (!m_assetInfo || m_assetInfo->type != AssetItem::Type::File || (openMode & QIODevice::WriteOnly)) return false; - close(); + if (m_assetFile) + return true; m_assetFile = AAssetManager_open(m_assetManager, m_fileName.toUtf8(), AASSET_MODE_BUFFER); return m_assetFile; } @@ -245,7 +246,6 @@ public: m_assetFile = 0; return true; } - m_isFolder = false; return false; } @@ -286,10 +286,12 @@ public: { FileFlags commonFlags(ReadOwnerPerm|ReadUserPerm|ReadGroupPerm|ReadOtherPerm|ExistsFlag); FileFlags flags; - if (m_assetFile) - flags = FileType | commonFlags; - else if (m_isFolder) - flags = DirectoryType | commonFlags; + if (m_assetInfo) { + if (m_assetInfo->type == AssetItem::Type::File) + flags = FileType | commonFlags; + else if (m_assetInfo->type == AssetItem::Type::Folder) + flags = DirectoryType | commonFlags; + } return type & flags; } @@ -324,21 +326,42 @@ public: return; close(); m_fileName = cleanedAssetPath(file); - switch (FolderIterator::fileType(m_fileName)) { - case AssetItem::Type::File: - open(QIODevice::ReadOnly, std::nullopt); - break; - case AssetItem::Type::Folder: - m_isFolder = true; - break; - case AssetItem::Type::Invalid: - break; + + { + QMutexLocker lock(&m_assetsInfoCacheMutex); + QSharedPointer<AssetItem> *assetInfoPtr = m_assetsInfoCache.object(m_fileName); + if (assetInfoPtr) { + m_assetInfo = *assetInfoPtr; + return; + } } + + QSharedPointer<AssetItem> *newAssetInfoPtr = new QSharedPointer<AssetItem>(new AssetItem); + + m_assetInfo = *newAssetInfoPtr; + m_assetInfo->name = m_fileName; + m_assetInfo->type = AssetItem::Type::Invalid; + + m_assetFile = AAssetManager_open(m_assetManager, m_fileName.toUtf8(), AASSET_MODE_BUFFER); + + if (m_assetFile) { + m_assetInfo->type = AssetItem::Type::File; + } else { + auto *assetDir = AAssetManager_openDir(m_assetManager, m_fileName.toUtf8()); + if (assetDir) { + if (AAssetDir_getNextFileName(assetDir)) + m_assetInfo->type = AssetItem::Type::Folder; + AAssetDir_close(assetDir); + } + } + + QMutexLocker lock(&m_assetsInfoCacheMutex); + m_assetsInfoCache.insert(m_fileName, newAssetInfoPtr); } Iterator *beginEntryList(QDir::Filters filters, const QStringList &filterNames) override { - if (m_isFolder) + if (m_assetInfo && m_assetInfo->type == AssetItem::Type::Folder) return new AndroidAbstractFileEngineIterator(filters, filterNames, m_fileName); return nullptr; } @@ -348,9 +371,14 @@ private: AAssetManager *m_assetManager = nullptr; // initialize with a name that can't be used as a file name QString m_fileName = "."_L1; - bool m_isFolder = false; + QSharedPointer<AssetItem> m_assetInfo; + + static QCache<QString, QSharedPointer<AssetItem>> m_assetsInfoCache; + static QMutex m_assetsInfoCacheMutex; }; +QCache<QString, QSharedPointer<AssetItem>> AndroidAbstractFileEngine::m_assetsInfoCache(std::max(200, qEnvironmentVariableIntValue("QT_ANDROID_MAX_FILEINFO_ASSETS_CACHE_SIZE"))); +QMutex AndroidAbstractFileEngine::m_assetsInfoCacheMutex; AndroidAssetsFileEngineHandler::AndroidAssetsFileEngineHandler() { |