From b4ff5495e772abafce63a5d8074dccd741d71028 Mon Sep 17 00:00:00 2001 From: surencong Date: Fri, 2 Jun 2023 11:42:26 +0800 Subject: [PATCH] add PurgeableResourceManager category:feature issue:https://gitee.com/openharmony/commonlibrary_memory_utils/issues/I7ABWA Signed-off-by: surencong --- bundle.json | 10 +- libpurgeablemem/BUILD.gn | 4 + .../cpp/include/purgeable_resource_manager.h | 111 +++++++ .../cpp/src/purgeable_resource_manager.cpp | 280 ++++++++++++++++++ purgeable_mem_config.gni | 16 + 5 files changed, 419 insertions(+), 2 deletions(-) create mode 100644 libpurgeablemem/cpp/include/purgeable_resource_manager.h create mode 100644 libpurgeablemem/cpp/src/purgeable_resource_manager.cpp create mode 100644 purgeable_mem_config.gni diff --git a/bundle.json b/bundle.json index 7b5b930..cbd905e 100644 --- a/bundle.json +++ b/bundle.json @@ -43,9 +43,15 @@ "name": "//commonlibrary/memory_utils/libpurgeablemem:libpurgeablemem", "header": { "header_files": [ - "purgeable_mem_c.h" + "pm_log.h", + "pm_smartptr_util.h", + "purgeable_ashmem.h", + "purgeable_mem.h", + "purgeable_mem_base.h", + "purgeable_mem_builder.h", + "ux_page_table.h" ], - "header_base": "//commonlibrary/memory_utils/libpurgeablemem/c/include" + "header_base": "//commonlibrary/memory_utils/libpurgeablemem/cpp/include" } } ], diff --git a/libpurgeablemem/BUILD.gn b/libpurgeablemem/BUILD.gn index eea8e54..c26f6ba 100644 --- a/libpurgeablemem/BUILD.gn +++ b/libpurgeablemem/BUILD.gn @@ -35,12 +35,16 @@ ohos_shared_library("libpurgeablemem") { "cpp/src/purgeable_mem.cpp", "cpp/src/purgeable_mem_base.cpp", "cpp/src/purgeable_mem_builder.cpp", + "cpp/src/purgeable_resource_manager.cpp", "cpp/src/ux_page_table.cpp", ] include_dirs = [ "include" ] external_deps = [ "c_utils:utils", + "hitrace_native:hitrace_meter", "hiviewdfx_hilog_native:libhilog", + "init:libbegetutil", + "ipc:ipc_core", ] public_configs = [ ":libpurgeable_config" ] subsystem_name = "commonlibrary" diff --git a/libpurgeablemem/cpp/include/purgeable_resource_manager.h b/libpurgeablemem/cpp/include/purgeable_resource_manager.h new file mode 100644 index 0000000..3fb3b9b --- /dev/null +++ b/libpurgeablemem/cpp/include/purgeable_resource_manager.h @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_UTILS_MEMORY_LIBPURGEABLEMEM_CPP_INCLUDE_PURGEABLE_RESOURCE_MANAGER_H +#define OHOS_UTILS_MEMORY_LIBPURGEABLEMEM_CPP_INCLUDE_PURGEABLE_RESOURCE_MANAGER_H + +#include +#include +#include +#include + +#include "purgeable_mem_base.h" +#include "thread_pool.h" + +namespace OHOS { +namespace PurgeableMem { +/* System parameter name */ +const std::string THREAD_POOL_TASK_NUMBER_SYS_NAME = "persist.commonlibrary.purgeable.threadpooltasknum"; +const std::string LRU_CACHE_CAPACITY_SYS_NAME = "persist.commonlibrary.purgeable.lrucachecapacity"; +/* Threadpool task number and lrucache capacity */ +constexpr int32_t THREAD_POOL_TASK_NUMBER = 8; +constexpr int32_t MIN_THREAD_POOL_TASK_NUMBER = 1; +constexpr int32_t MAX_THREAD_POOL_TASK_NUMBER = 20; +constexpr int32_t LRU_CACHE_CAPACITY = 100; +constexpr int32_t MIN_LRU_CACHE_CAPACITY = 1; +constexpr int32_t MAX_LRU_CACHE_CAPACITY = 200; + +class LruCache { +public: + /* + * Visited: visit the cache entry with the given key. + * If the entry is found, it will be move to the most-recent position in the cache. + */ + void Visited(std::shared_ptr key); + + /* + * Insert: insert the PurgeableMemBase key in the lrucache. + * Input: @key: ptr of PurgeableMemBase. + */ + void Insert(std::shared_ptr key); + + /* + * Erase: erase the PurgeableMemBase key in the lrucache. + * Input: @key: ptr of PurgeableMemBase. + */ + void Erase(std::shared_ptr key); + + /* + * SetCapacity: set the capacity of the lrucache. + * Input: the capacity of lrucache. + */ + void SetCapacity(int32_t capacity); + + /* + * Clear: clear the resourcePtrList and positionMap of the lrucache. + */ + void Clear(); + + using ListSharedPtrIterator = std::list>::iterator; + std::list> GetResourcePtrList() const; + std::shared_ptr GetLastResourcePtr() const; + size_t Size() const; + +private: + int32_t lruCacheCapacity_; + std::list> resourcePtrList_; + std::unordered_map, ListSharedPtrIterator> positionMap_; +}; + +class PurgeableResourceManager { +public: + PurgeableResourceManager(const PurgeableResourceManager&) = delete; + PurgeableResourceManager& operator=(const PurgeableResourceManager&) = delete; + ~PurgeableResourceManager(); + + static PurgeableResourceManager &GetInstance(); + void BeginAccessPurgeableMem(); + void EndAccessPurgeableMem(); + void AddResource(std::shared_ptr resourcePtr); + void RemoveResource(std::shared_ptr resourcePtr); + void SetRecentUsedResource(std::shared_ptr resourcePtr); + void SetLruCacheCapacity(int32_t capacity); + void Clear(); + void RemoveLastResource(); + void ShowLruCache() const; + +private: + PurgeableResourceManager(); + int32_t GetThreadPoolTaskNumFromSysPara(); + int32_t GetLruCacheCapacityFromSysPara(); + void GetParaFromConfiguration(); + + mutable std::mutex mutex_; + LruCache lruCache_; + ThreadPool threadPool_; +}; +} /* namespace PurgeableMem */ +} /* namespace OHOS */ +#endif /* OHOS_UTILS_MEMORY_LIBPURGEABLEMEM_CPP_INCLUDE_PURGEABLE_RESOURCE_MANAGER_H */ \ No newline at end of file diff --git a/libpurgeablemem/cpp/src/purgeable_resource_manager.cpp b/libpurgeablemem/cpp/src/purgeable_resource_manager.cpp new file mode 100644 index 0000000..7783ef0 --- /dev/null +++ b/libpurgeablemem/cpp/src/purgeable_resource_manager.cpp @@ -0,0 +1,280 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "hitrace_meter.h" +#include "parameters.h" +#include "pm_log.h" +#include "purgeable_resource_manager.h" + +namespace OHOS { +namespace PurgeableMem { +void LruCache::Visited(std::shared_ptr key) +{ + if (key == nullptr) { + return; + } + + auto resourcePtrIter = positionMap_.find(key); + if (resourcePtrIter != positionMap_.end()) { + resourcePtrList_.splice(resourcePtrList_.begin(), resourcePtrList_, resourcePtrIter->second); + resourcePtrIter->second = resourcePtrList_.begin(); + } +} + +void LruCache::Insert(std::shared_ptr key) +{ + if (key == nullptr) { + return; + } + + auto resourcePtrIter = positionMap_.find(key); + if (resourcePtrIter != positionMap_.end()) { + resourcePtrList_.splice(resourcePtrList_.begin(), resourcePtrList_, resourcePtrIter->second); + resourcePtrIter->second = resourcePtrList_.begin(); + return; + } + + resourcePtrList_.emplace_front(key); + positionMap_.emplace(key, resourcePtrList_.begin()); + if (static_cast(resourcePtrList_.size()) > lruCacheCapacity_) { + positionMap_.erase(resourcePtrList_.back()); + resourcePtrList_.pop_back(); + } +} + +void LruCache::Erase(std::shared_ptr key) +{ + if (key == nullptr) { + return; + } + + auto resourcePtrIter = positionMap_.find(key); + if (resourcePtrIter == positionMap_.end()) { + return; + } + + resourcePtrList_.erase(resourcePtrIter->second); + positionMap_.erase(key); +} + +void LruCache::SetCapacity(int32_t capacity) +{ + if (capacity < 0 || capacity > MAX_LRU_CACHE_CAPACITY) { + PM_HILOG_DEBUG(LOG_CORE, "[PurgeableResourceManager] SetCapacity FAILED: capacity value is invalid!"); + return; + } + + lruCacheCapacity_ = capacity; + while (lruCacheCapacity_ < static_cast(Size())) { + Erase(resourcePtrList_.back()); + } +} + +void LruCache::Clear() +{ + positionMap_.clear(); + resourcePtrList_.clear(); +} + +std::list> LruCache::GetResourcePtrList() const +{ + return resourcePtrList_; +} + +std::shared_ptr LruCache::GetLastResourcePtr() const +{ + return resourcePtrList_.back(); +} + +size_t LruCache::Size() const +{ + return positionMap_.size(); +} + +PurgeableResourceManager::PurgeableResourceManager() +{ + GetParaFromConfiguration(); +} + +PurgeableResourceManager::~PurgeableResourceManager() +{ + std::lock_guard lock(mutex_); + threadPool_.Stop(); + lruCache_.Clear(); +} + +PurgeableResourceManager &PurgeableResourceManager::GetInstance() +{ + static PurgeableResourceManager instance; + return instance; +} + +void PurgeableResourceManager::BeginAccessPurgeableMem() +{ + std::lock_guard lock(mutex_); + StartTrace(HITRACE_TAG_COMMONLIBRARY, "OHOS::PurgeableMem::PurgeableResourceManager::BeginAccessPurgeableMem"); + std::list> resourcePtrList = lruCache_.GetResourcePtrList(); + for (auto &resourcePtr : resourcePtrList) { + if (resourcePtr == nullptr) { + continue; + } + + auto task = std::bind(&PurgeableMemBase::BeginRead, resourcePtr); + threadPool_.AddTask(task); + } + + FinishTrace(HITRACE_TAG_COMMONLIBRARY); + PM_HILOG_DEBUG(LOG_CORE, "[PurgeableResourceManager] BeginAccessPurgeableMem list size: %{public}zu", + lruCache_.Size()); +} + +void PurgeableResourceManager::EndAccessPurgeableMem() +{ + std::lock_guard lock(mutex_); + StartTrace(HITRACE_TAG_COMMONLIBRARY, "OHOS::PurgeableMem::PurgeableResourceManager::EndAccessPurgeableMem"); + std::list> resourcePtrList = lruCache_.GetResourcePtrList(); + for (auto &resourcePtr : resourcePtrList) { + if (resourcePtr == nullptr) { + continue; + } + + auto task = std::bind(&PurgeableMemBase::EndRead, resourcePtr); + threadPool_.AddTask(task); + } + + FinishTrace(HITRACE_TAG_COMMONLIBRARY); + PM_HILOG_DEBUG(LOG_CORE, "[PurgeableResourceManager] EndAccessPurgeableMem list size: %{public}zu", + lruCache_.Size()); +} + +void PurgeableResourceManager::AddResource(std::shared_ptr resourcePtr) +{ + std::lock_guard lock(mutex_); + StartTrace(HITRACE_TAG_COMMONLIBRARY, "OHOS::PurgeableMem::PurgeableResourceManager::AddResource"); + if (resourcePtr == nullptr) { + FinishTrace(HITRACE_TAG_COMMONLIBRARY); + return; + } + + lruCache_.Insert(resourcePtr); + FinishTrace(HITRACE_TAG_COMMONLIBRARY); + PM_HILOG_DEBUG(LOG_CORE, "[PurgeableResourceManager] AddResource resourcePtr: 0x%{public}lx, " + "list size: %{public}zu", (long)resourcePtr.get(), lruCache_.Size()); +} + +void PurgeableResourceManager::RemoveResource(std::shared_ptr resourcePtr) +{ + std::lock_guard lock(mutex_); + StartTrace(HITRACE_TAG_COMMONLIBRARY, "OHOS::PurgeableMem::PurgeableResourceManager::RemoveResource"); + if (resourcePtr == nullptr) { + FinishTrace(HITRACE_TAG_COMMONLIBRARY); + return; + } + + lruCache_.Erase(resourcePtr); + FinishTrace(HITRACE_TAG_COMMONLIBRARY); + PM_HILOG_DEBUG(LOG_CORE, "[PurgeableResourceManager] RemoveResource resourcePtr: 0x%{public}lx, " + "list size: %{public}zu", (long)resourcePtr.get(), lruCache_.Size()); +} + +void PurgeableResourceManager::SetRecentUsedResource(std::shared_ptr resourcePtr) +{ + std::lock_guard lock(mutex_); + if (resourcePtr == nullptr) { + return; + } + + lruCache_.Visited(resourcePtr); +} + +void PurgeableResourceManager::SetLruCacheCapacity(int32_t capacity) +{ + std::lock_guard lock(mutex_); + lruCache_.SetCapacity(capacity); +} + +void PurgeableResourceManager::Clear() +{ + std::lock_guard lock(mutex_); + lruCache_.Clear(); +} + +void PurgeableResourceManager::RemoveLastResource() +{ + std::lock_guard lock(mutex_); + StartTrace(HITRACE_TAG_COMMONLIBRARY, "OHOS::PurgeableMem::PurgeableResourceManager::RemoveLastResource"); + if (lruCache_.Size() == 0) { + FinishTrace(HITRACE_TAG_COMMONLIBRARY); + return; + } + + std::shared_ptr resourcePtr = lruCache_.GetLastResourcePtr(); + if (resourcePtr == nullptr) { + FinishTrace(HITRACE_TAG_COMMONLIBRARY); + return; + } + + lruCache_.Erase(resourcePtr); + FinishTrace(HITRACE_TAG_COMMONLIBRARY); + PM_HILOG_DEBUG(LOG_CORE, "[PurgeableResourceManager] RemoveLastResource resourcePtr: 0x%{public}lx, " + "list size: %{public}zu", (long)resourcePtr.get(), lruCache_.Size()); +} + +void PurgeableResourceManager::ShowLruCache() const +{ + std::lock_guard lock(mutex_); + std::list> resourcePtrList = lruCache_.GetResourcePtrList(); + int cnt = 0; + for (auto &resourcePtr : resourcePtrList) { + cnt++; + PM_HILOG_DEBUG(LOG_CORE, "[PurgeableResourceManager] ShowLruCache (resourcePtr: 0x%{public}lx, " + "%{public}zu th, list size: %{public}zu)", (long)resourcePtr.get(), cnt, lruCache_.Size()); + } +} + +int32_t PurgeableResourceManager::GetThreadPoolTaskNumFromSysPara() +{ + return system::GetIntParameter(THREAD_POOL_TASK_NUMBER_SYS_NAME, THREAD_POOL_TASK_NUMBER); +} + +int32_t PurgeableResourceManager::GetLruCacheCapacityFromSysPara() +{ + return system::GetIntParameter(LRU_CACHE_CAPACITY_SYS_NAME, LRU_CACHE_CAPACITY); +} + +void PurgeableResourceManager::GetParaFromConfiguration() +{ + int32_t threadPoolTaskNum = GetThreadPoolTaskNumFromSysPara(); + int32_t lruCacheCapacity = GetLruCacheCapacityFromSysPara(); + if (threadPoolTaskNum < MIN_THREAD_POOL_TASK_NUMBER || threadPoolTaskNum > MAX_THREAD_POOL_TASK_NUMBER) { + PM_HILOG_ERROR(LOG_CORE, "[PurgeableResourceManager] Get error threadpool task number from system parameter."); + return; + } + + if (lruCacheCapacity < MIN_LRU_CACHE_CAPACITY || lruCacheCapacity > MAX_LRU_CACHE_CAPACITY) { + PM_HILOG_ERROR(LOG_CORE, "[PurgeableResourceManager] Get error lrucache capacity from system parameter."); + return; + } + + lruCache_.SetCapacity(lruCacheCapacity); + if (threadPool_.GetThreadsNum() == 0) { + threadPool_.Start(threadPoolTaskNum); + } + + PM_HILOG_DEBUG(LOG_CORE, "[PurgeableResourceManager] lruCacheCapacity is: %{public}d, " + "threadPool threadsNum is: %{public}zu", lruCacheCapacity, threadPool_.GetThreadsNum()); +} +} /* namespace PurgeableMem */ +} /* namespace OHOS */ \ No newline at end of file diff --git a/purgeable_mem_config.gni b/purgeable_mem_config.gni new file mode 100644 index 0000000..388025d --- /dev/null +++ b/purgeable_mem_config.gni @@ -0,0 +1,16 @@ +# Copyright (c) 2023 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +declare_args() { + purgeable_ashmem_enable = false +} -- Gitee