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();
 | 
						|
}
 |