448 lines
8.3 KiB
C++
448 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;
|
|
|
|
#if 0
|
|
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 << 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_);
|
|
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);
|
|
}
|
|
#endif
|
|
|
|
int main(int argc, char *argv[])
|
|
{
|
|
signal(49, SIG_IGN);
|
|
::testing::InitGoogleTest(&argc, argv);
|
|
return RUN_ALL_TESTS();
|
|
}
|