mirror of
https://gitee.com/openharmony/arkcompiler_ets_runtime
synced 2024-10-07 16:13:49 +00:00
Fix for freelist pool memory fragment
issue:https://gitee.com/openharmony/arkcompiler_ets_runtime/issues/I62K33?from=project-issue Signed-off-by: maojunwei <maojunwei1@huawei.com> Change-Id: Ib64a16eb988c7c222952f3ca52d14bffb24a60ed
This commit is contained in:
parent
0875afa157
commit
09d2070b16
@ -18,6 +18,7 @@
|
||||
|
||||
#include <deque>
|
||||
#include <map>
|
||||
#include <set>
|
||||
|
||||
#include "ecmascript/platform/map.h"
|
||||
#include "ecmascript/mem/mem.h"
|
||||
@ -107,11 +108,37 @@ public:
|
||||
{
|
||||
PageUnmap(memMap_);
|
||||
freeList_.clear();
|
||||
freeSet_.clear();
|
||||
}
|
||||
|
||||
NO_COPY_SEMANTIC(MemMapFreeList);
|
||||
NO_MOVE_SEMANTIC(MemMapFreeList);
|
||||
|
||||
void MergeList()
|
||||
{
|
||||
auto it = freeList_.begin();
|
||||
while (it != freeList_.end()) {
|
||||
bool isEqual = false;
|
||||
void *startMem = (*it).second.GetMem();
|
||||
size_t newSize = (*it).second.GetSize();
|
||||
auto startIt = it++;
|
||||
if (it == freeList_.end()) {
|
||||
break;
|
||||
}
|
||||
auto next = reinterpret_cast<void *>(reinterpret_cast<uintptr_t>(startMem) + newSize);
|
||||
while (it != freeList_.end() && next == (*it).second.GetMem()) {
|
||||
newSize += (*it).second.GetSize();
|
||||
freeList_.erase(it++);
|
||||
next = reinterpret_cast<void *>(reinterpret_cast<uintptr_t>(startMem) + newSize);
|
||||
isEqual = true;
|
||||
}
|
||||
if (isEqual) {
|
||||
freeList_.erase(startIt);
|
||||
freeList_.emplace(newSize, MemMap(startMem, newSize));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MemMap GetMemFromList(size_t size)
|
||||
{
|
||||
if (freeListPoolSize_ + size > capacity_) {
|
||||
@ -121,8 +148,19 @@ public:
|
||||
os::memory::LockHolder lock(lock_);
|
||||
auto iterate = freeList_.lower_bound(size);
|
||||
if (iterate == freeList_.end()) {
|
||||
LOG_GC(ERROR) << "Freelist pool oom: memory fragment(" << freeListPoolSize_ << ")";
|
||||
return MemMap();
|
||||
MergeList();
|
||||
iterate = freeList_.lower_bound(size);
|
||||
// Unable to get memory from freeList, use PageMap
|
||||
if (iterate == freeList_.end()) {
|
||||
if (freeListPoolSize_ + freeSetPoolSize_ + size > capacity_) {
|
||||
LOG_GC(ERROR) << "Freeset pool oom: overflow(" << freeSetPoolSize_ << ")";
|
||||
return MemMap();
|
||||
}
|
||||
MemMap smemMap = PageMap(size, PAGE_PROT_NONE, DEFAULT_REGION_SIZE);
|
||||
freeSet_.emplace(reinterpret_cast<uintptr_t>(smemMap.GetMem()));
|
||||
freeSetPoolSize_ += size;
|
||||
return smemMap;
|
||||
}
|
||||
}
|
||||
MemMap memMap = iterate->second;
|
||||
size_t remainderSize = memMap.GetSize() - size;
|
||||
@ -138,15 +176,24 @@ public:
|
||||
void AddMemToList(MemMap memMap)
|
||||
{
|
||||
os::memory::LockHolder lock(lock_);
|
||||
freeListPoolSize_ -= memMap.GetSize();
|
||||
freeList_.emplace(memMap.GetSize(), memMap);
|
||||
auto search = freeSet_.find(reinterpret_cast<uintptr_t>(memMap.GetMem()));
|
||||
if (UNLIKELY(search != freeSet_.end())) {
|
||||
freeSetPoolSize_ -= memMap.GetSize();
|
||||
freeSet_.erase(search);
|
||||
PageUnmap(memMap);
|
||||
} else {
|
||||
freeListPoolSize_ -= memMap.GetSize();
|
||||
freeList_.emplace(memMap.GetSize(), memMap);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
os::memory::Mutex lock_;
|
||||
MemMap memMap_;
|
||||
std::multimap<size_t, MemMap> freeList_;
|
||||
std::set<uintptr_t> freeSet_;
|
||||
std::atomic_size_t freeListPoolSize_ {0};
|
||||
std::atomic_size_t freeSetPoolSize_ {0};
|
||||
size_t capacity_ {0};
|
||||
};
|
||||
|
||||
|
@ -156,6 +156,7 @@ host_unittest_action("EcmaVm_003_Test") {
|
||||
"linked_hash_table_test.cpp",
|
||||
"linked_node_test.cpp",
|
||||
"mem_controller_test.cpp",
|
||||
"mem_map_allocator_test.cpp",
|
||||
"native_pointer_test.cpp",
|
||||
"object_factory_test.cpp",
|
||||
"object_operator_test.cpp",
|
||||
|
83
ecmascript/tests/mem_map_allocator_test.cpp
Normal file
83
ecmascript/tests/mem_map_allocator_test.cpp
Normal file
@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Copyright (c) 2021 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 "ecmascript/ecma_vm.h"
|
||||
|
||||
#include "ecmascript/mem/mem_map_allocator.h"
|
||||
#include "ecmascript/mem/mem_common.h"
|
||||
#include "ecmascript/tests/test_helper.h"
|
||||
|
||||
using namespace panda::ecmascript;
|
||||
using namespace panda::ecmascript::base;
|
||||
|
||||
namespace panda::test {
|
||||
|
||||
constexpr size_t HUGE_OBJECT_CAPACITY = 512_KB;
|
||||
|
||||
class MemMapAllocatorTest : public testing::Test {
|
||||
public:
|
||||
static void SetUpTestCase()
|
||||
{
|
||||
GTEST_LOG_(INFO) << "SetUpTestCase";
|
||||
}
|
||||
|
||||
static void TearDownTestCase()
|
||||
{
|
||||
GTEST_LOG_(INFO) << "TearDownCase";
|
||||
}
|
||||
|
||||
void SetUp() override
|
||||
{
|
||||
TestHelper::CreateEcmaVMWithScope(instance, thread, scope);
|
||||
}
|
||||
|
||||
void TearDown() override
|
||||
{
|
||||
TestHelper::DestroyEcmaVMWithScope(instance, scope);
|
||||
}
|
||||
|
||||
EcmaVM *instance {nullptr};
|
||||
EcmaHandleScope *scope {nullptr};
|
||||
JSThread *thread {nullptr};
|
||||
};
|
||||
|
||||
HWTEST_F_L0(MemMapAllocatorTest, GetMemFromList)
|
||||
{
|
||||
MemMap memMap = PageMap(HUGE_OBJECT_CAPACITY, PAGE_PROT_NONE, DEFAULT_REGION_SIZE);
|
||||
PageRelease(memMap.GetMem(), memMap.GetSize());
|
||||
MemMapFreeList memMapFreeList_;
|
||||
memMapFreeList_.Initialize(memMap);
|
||||
|
||||
// From FreeList
|
||||
size_t size1 = 256 * 1024;
|
||||
auto mem1 = memMapFreeList_.GetMemFromList(size1);
|
||||
EXPECT_EQ(mem1.GetSize(), size1);
|
||||
|
||||
// From FreeList
|
||||
size_t size2 = 128 * 1024;
|
||||
auto mem2 = memMapFreeList_.GetMemFromList(size2);
|
||||
EXPECT_EQ(mem2.GetSize(), size2);
|
||||
|
||||
// From PageMap
|
||||
size_t size3 = 128 * 1024;
|
||||
auto mem3 = memMapFreeList_.GetMemFromList(size3);
|
||||
EXPECT_EQ(mem3.GetSize(), size3);
|
||||
|
||||
memMapFreeList_.AddMemToList(mem3);
|
||||
memMapFreeList_.Finalize();
|
||||
}
|
||||
|
||||
} // namespace panda::test
|
Loading…
Reference in New Issue
Block a user