Files
oceanbase/deps/oblib/unittest/lib/alloc/test_object_set.cpp
gm 4a92b6d7df reformat source code
according to code styles, 'AccessModifierOffset' should be -2.
2021-06-17 10:40:36 +08:00

440 lines
8.3 KiB
C++

/**
* Copyright (c) 2021 OceanBase
* OceanBase CE is licensed under Mulan PubL v2.
* You can use this software according to the terms and conditions of the Mulan PubL v2.
* You may obtain a copy of Mulan PubL v2 at:
* http://license.coscl.org.cn/MulanPubL-2.0
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PubL v2 for more details.
*/
#include "lib/alloc/object_set.h"
#include "lib/alloc/block_set.h"
#include <gtest/gtest.h>
#include "lib/allocator/page_arena.h"
#include "lib/resource/ob_resource_mgr.h"
#include "lib/ob_errno.h"
using namespace oceanbase::lib;
using namespace std;
using namespace oceanbase::common;
ObMemAttr attr;
class TestObjectSet : public ::testing::Test {
class ObjecSetLocker : public ISetLocker {
public:
ObjecSetLocker()
{}
void lock() override
{}
void unlock() override
{}
bool trylock() override
{
return true;
}
};
public:
TestObjectSet() : tallocator_(500), os_locker_(), bs_(), os_()
{}
virtual void SetUp()
{
cout << BLOCKS_PER_CHUNK << endl;
cout << NORMAL_AOBJECT_SIZE << endl;
cout << AOBJECT_META_SIZE << " " << ABLOCK_HEADER_SIZE << endl;
tallocator_.set_tenant_memory_mgr();
tallocator_.set_limit(1000L << 20);
bs_.reset();
bs_.set_tenant_ctx_allocator(tallocator_, attr);
os_.set_block_mgr(&bs_);
os_.set_locker(&os_locker_);
os_.reset();
}
virtual void TearDown()
{}
void* Malloc(uint64_t size)
{
void* p = NULL;
AObject* obj = os_.alloc_object(size, attr);
if (obj != NULL) {
p = obj->data_;
// memset(p, 0, size);
}
return p;
}
void Free(void* ptr)
{
AObject* obj = reinterpret_cast<AObject*>((char*)ptr - AOBJECT_HEADER_SIZE);
os_.free_object(obj);
}
void* Realloc(void* ptr, uint64_t size)
{
AObject* obj = NULL;
if (ptr != NULL) {
obj = reinterpret_cast<AObject*>((char*)ptr - AOBJECT_HEADER_SIZE);
}
obj = os_.realloc_object(obj, size, attr);
return obj->data_;
}
void Reset()
{
os_.reset();
}
void check_ptr(void* ptr)
{
EXPECT_TRUE(ptr != NULL);
UNUSED(ptr);
}
protected:
ObTenantCtxAllocator tallocator_;
ObjecSetLocker os_locker_;
BlockSet bs_;
ObjectSet os_;
};
TEST_F(TestObjectSet, Basic)
{
void* p = NULL;
int64_t cnt = 1L << 20;
uint64_t sz = 32;
while (cnt--) {
p = Malloc(sz);
check_ptr(p);
Free(p);
p = Malloc(sz);
check_ptr(p);
Free(p);
p = Malloc(sz);
check_ptr(p);
Free(p);
p = Malloc(sz);
check_ptr(p);
Free(p);
p = Malloc(sz);
check_ptr(p);
Free(p);
p = Malloc(sz);
check_ptr(p);
Free(p);
p = Malloc(sz);
check_ptr(p);
Free(p);
p = Malloc(sz);
check_ptr(p);
Free(p);
p = Malloc(sz);
check_ptr(p);
Free(p);
p = Malloc(sz);
check_ptr(p);
Free(p);
p = Malloc(sz);
check_ptr(p);
Free(p);
p = Malloc(sz);
check_ptr(p);
Free(p);
p = Malloc(sz);
check_ptr(p);
Free(p);
p = Malloc(sz);
check_ptr(p);
Free(p);
p = Malloc(sz);
check_ptr(p);
Free(p);
p = Malloc(sz);
check_ptr(p);
Free(p);
sz = ((sz | reinterpret_cast<size_t>(p)) & ((1 << 13) - 1));
}
}
TEST_F(TestObjectSet, Basic2)
{
void* p[128] = {};
int64_t cnt = 1L << (28 - 10);
uint64_t sz = 1024;
while (cnt--) {
int i = 0;
p[i++] = Malloc(sz);
p[i++] = Malloc(sz);
p[i++] = Malloc(sz);
p[i++] = Malloc(sz);
p[i++] = Malloc(sz);
p[i++] = Malloc(sz);
p[i++] = Malloc(sz);
p[i++] = Malloc(sz);
p[i++] = Malloc(sz);
p[i++] = Malloc(sz);
p[i++] = Malloc(sz);
p[i++] = Malloc(sz);
p[i++] = Malloc(sz);
p[i++] = Malloc(sz);
p[i++] = Malloc(sz);
p[i++] = Malloc(sz);
while (i--) {
Free(p[i]);
}
sz = ((sz | reinterpret_cast<size_t>(p[0])) & ((1 << 13) - 1));
}
}
TEST_F(TestObjectSet, SplitBug)
{
void* p[128] = {};
{
// build free list
for (int i = 0; i < 8; i++) {
p[i] = Malloc(8192);
}
for (int i = 0; i < 8; i++) {
Free(p[i]);
}
}
for (int i = 0; i < 8; i++) {
p[i] = Malloc(1008);
}
for (int i = 0; i < 7; i++) {
Free(p[i]);
}
for (int i = 0; i < 6; i++) {
p[i] = Malloc(1008);
memset(p[i], 0, 1008);
}
Free(p[0]);
Free(p[7]);
// The last remainder will indicate a invalid address if splitting
// obj doesn't work well.
Malloc(1);
}
TEST_F(TestObjectSet, Reset)
{
void* p = NULL;
int64_t cnt = 1L << (28 - 10);
uint64_t sz = 32;
while (cnt--) {
p = Malloc(sz);
check_ptr(p);
p = Malloc(sz);
check_ptr(p);
p = Malloc(sz);
check_ptr(p);
p = Malloc(sz);
check_ptr(p);
p = Malloc(sz);
check_ptr(p);
p = Malloc(sz);
check_ptr(p);
p = Malloc(sz);
check_ptr(p);
p = Malloc(sz);
check_ptr(p);
p = Malloc(sz);
check_ptr(p);
p = Malloc(sz);
check_ptr(p);
p = Malloc(sz);
check_ptr(p);
p = Malloc(sz);
check_ptr(p);
p = Malloc(sz);
check_ptr(p);
p = Malloc(sz);
check_ptr(p);
p = Malloc(sz);
check_ptr(p);
p = Malloc(sz);
check_ptr(p);
Reset();
sz = ((sz | reinterpret_cast<size_t>(p)) & ((1 << 13) - 1));
}
}
TEST_F(TestObjectSet, NormalObject)
{
void* p = NULL;
int64_t cnt = 1L << (28 - 6);
uint64_t sz = 1 < 13;
while (cnt--) {
p = Malloc(sz);
check_ptr(p);
Free(p);
}
}
TEST_F(TestObjectSet, NormalObject_plus_1)
{
void* p = NULL;
int64_t cnt = 1L << (28 - 6);
uint64_t sz = (1 << 13) + 1;
p = Malloc(sz);
while (cnt--) {
p = Malloc(sz);
check_ptr(p);
Free(p);
}
}
TEST_F(TestObjectSet, MallocReset)
{
int64_t cnt = 1L << 22;
const int sz = 1 << 13;
while (cnt--) {
Malloc(sz);
Reset();
}
}
TEST_F(TestObjectSet, PageArena)
{
int64_t cnt = 1L << 22;
const int sz = 32;
while (cnt--) {
Malloc(sz);
Malloc(sz);
Malloc(sz);
Malloc(sz);
Malloc(sz);
Malloc(sz);
Malloc(sz);
Malloc(sz);
Malloc(sz);
Malloc(sz);
Malloc(sz);
Malloc(sz);
Malloc(sz);
Malloc(sz);
Malloc(sz);
Malloc(sz);
Reset();
}
}
TEST_F(TestObjectSet, PageArenaOrigin)
{
// int64_t cnt = 1L << 22;
int64_t cnt = 1L << 20L;
const int sz = 32;
oceanbase::common::PageArena<> pa;
while (cnt--) {
pa.alloc(sz);
pa.alloc(sz);
pa.alloc(sz);
pa.alloc(sz);
pa.alloc(sz);
pa.alloc(sz);
pa.alloc(sz);
pa.alloc(sz);
pa.alloc(sz);
pa.alloc(sz);
pa.alloc(sz);
pa.alloc(sz);
pa.alloc(sz);
pa.alloc(sz);
pa.alloc(sz);
pa.alloc(sz);
pa.free();
}
}
TEST_F(TestObjectSet, ReallocInc1M)
{
void* p = NULL;
int64_t cnt = 1L << 10;
uint64_t sz = 1;
p = Realloc(p, 0);
EXPECT_TRUE(p != NULL);
while (cnt-- && sz < (1 << 20)) {
p = Realloc(p, sz);
memset(p, 0, sz);
p = Realloc(p, sz);
memset(p, 0, sz);
p = Realloc(p, sz);
memset(p, 0, sz);
p = Realloc(p, sz);
memset(p, 0, sz);
p = Realloc(p, sz);
memset(p, 0, sz);
p = Realloc(p, sz);
memset(p, 0, sz);
p = Realloc(p, sz);
memset(p, 0, sz);
sz += (reinterpret_cast<int64_t>(p) & ((1 << 6) - 1));
}
Free(p);
}
TEST_F(TestObjectSet, ReallocDec1M)
{
void* p = NULL;
int64_t cnt = 1L << 10;
int64_t sz = 1 << 20;
while (cnt-- && sz > 0) {
p = Realloc(p, sz);
memset(p, 0, sz);
p = Realloc(p, sz);
memset(p, 0, sz);
p = Realloc(p, sz);
memset(p, 0, sz);
p = Realloc(p, sz);
memset(p, 0, sz);
p = Realloc(p, sz);
memset(p, 0, sz);
p = Realloc(p, sz);
memset(p, 0, sz);
p = Realloc(p, sz);
memset(p, 0, sz);
sz -= (reinterpret_cast<int64_t>(p) & ((1 << 6) - 1));
}
Free(p);
}
TEST_F(TestObjectSet, BlockCacheSize)
{
static const int64_t SZ = 8192;
static const int64_t COUNT = 10000;
void* objs[COUNT] = {};
for (int i = 0; i < COUNT; ++i) {
objs[i] = Malloc(SZ);
}
for (int i = 0; i < COUNT / 10; ++i) {
Free(objs[i]);
}
EXPECT_EQ(os_.get_normal_hold() - os_.get_normal_used(), SZ + AOBJECT_META_SIZE);
}
int main(int argc, char* argv[])
{
signal(49, SIG_IGN);
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}