patch 4.0

This commit is contained in:
wangzelin.wzl
2022-10-24 10:34:53 +08:00
parent 4ad6e00ec3
commit 93a1074b0c
10533 changed files with 2588271 additions and 2299373 deletions

View File

@ -19,58 +19,49 @@
#include "lib/allocator/ob_qsync.h"
#include "lib/utility/ob_print_utils.h"
namespace oceanbase {
namespace common {
namespace oceanbase
{
namespace common
{
extern ObBlockAllocMgr default_blk_alloc;
class ObSimpleSync {
class ObSimpleSync
{
public:
ObSimpleSync() : ref_(0)
{}
int32_t ref(int32_t x)
{
return ATOMIC_AAF(&ref_, x);
}
void sync()
{
while (ATOMIC_LOAD(&ref_) > 0) {
ObSimpleSync(): ref_(0) {}
int32_t ref(int32_t x) { return ATOMIC_AAF(&ref_, x); }
void sync() {
while(ATOMIC_LOAD(&ref_) > 0) {
PAUSE();
}
}
private:
int32_t ref_;
};
class ObDListWithLock {
class ObDListWithLock
{
public:
typedef ObDLink DLink;
ObDListWithLock() : lock_()
{
ObDListWithLock(): lock_() {
head_.next_ = &head_;
head_.prev_ = &head_;
}
~ObDListWithLock()
{}
void add(DLink* p)
{
~ObDListWithLock() {}
void add(DLink* p) {
lib::ObLockGuard<common::ObSpinLock> guard(lock_);
add_(p);
}
void del(DLink* p)
{
void del(DLink* p) {
lib::ObLockGuard<common::ObSpinLock> guard(lock_);
del_(p);
}
DLink* top()
{
DLink* top() {
DLink* p = (DLink*)ATOMIC_LOAD(&head_.next_);
return &head_ == p ? NULL : p;
return &head_ == p? NULL: p;
}
private:
void add_(DLink* p)
{
void add_(DLink* p) {
DLink* prev = head_.prev_;
DLink* next = &head_;
p->prev_ = prev;
@ -78,44 +69,42 @@ private:
prev->next_ = p;
next->prev_ = p;
}
void del_(DLink* p)
{
void del_(DLink* p) {
DLink* prev = p->prev_;
DLink* next = (DLink*)p->next_;
prev->next_ = next;
next->prev_ = prev;
}
private:
mutable common::ObSpinLock lock_;
DLink head_ CACHE_ALIGNED;
};
class ObEmbedFixedQueue {
class ObEmbedFixedQueue
{
public:
ObEmbedFixedQueue(): push_(0), pop_(0), capacity_(0) {}
ObEmbedFixedQueue(): push_(0), pop_(0), capacity_(0) {
init(0);
}
~ObEmbedFixedQueue() {}
void init(uint64_t capacity) {
capacity_ = capacity;
memset(data_, 0, sizeof(void*) * capacity);
}
void push(void* p)
{
void push(void* p) {
void** addr = data_ + ATOMIC_FAA(&push_, 1) % capacity_;
while (!ATOMIC_BCAS(addr, NULL, p)) {
while(!ATOMIC_BCAS(addr, NULL, p)) {
PAUSE();
}
}
void* pop()
{
void* pop() {
void* p = NULL;
void** addr = data_ + ATOMIC_FAA(&pop_, 1) % capacity_;
while (NULL == (p = ATOMIC_TAS(addr, NULL))) {
while(NULL == (p = ATOMIC_TAS(addr, NULL))) {
PAUSE();
}
return p;
}
private:
uint64_t push_ CACHE_ALIGNED;
uint64_t pop_ CACHE_ALIGNED;
@ -128,133 +117,104 @@ private:
acquire release recycle
1. shared block must be linked in list
2. private block can be used for alloc, or can be destroyed.
3. flying block is a transient, difference with private state is that private block has no chance to trigger link to
list.
3. flying block is a transient, difference with private state is that private block has no chance to trigger link to list.
*/
class ObStockCtrl {
class ObStockCtrl
{
public:
enum { K = INT32_MAX / 2 };
ObStockCtrl() : total_(0), stock_(0)
{}
~ObStockCtrl()
{}
void init_stock(int32_t n)
{
enum { K = INT32_MAX/2 };
ObStockCtrl(): total_(0), stock_(0) {}
~ObStockCtrl() {}
void init_stock(int32_t n) {
total_ = n;
stock_ = n;
}
public:
uint32_t total()
{
return total_;
}
bool acquire()
{
return dec_if_gt(K, K) > K;
}
bool release()
{
return faa(-K) > 0;
}
bool recyle()
{
uint32_t total() { return total_; }
bool acquire() { return dec_if_gt(K, K) > K; }
bool release() { return faa(-K) > 0; }
bool recyle() {
int32_t total = total_;
return inc_if_lt(2 * K, -K + total) == -K + total;
return inc_if_lt(2 * K, -K + total) == -K + total;
}
bool alloc_stock()
{
return dec_if_gt(1, 0) > 0;
}
bool free_stock(bool& first_free)
{
bool alloc_stock() { return dec_if_gt(1, 0) > 0; }
bool free_stock(bool& first_free) {
int32_t total = total_;
int32_t ov = cas_or_inc(K + total - 1, -K + total, 1);
first_free = (ov == -K);
return ov == K + total - 1;
}
private:
int32_t faa(int32_t x)
{
return ATOMIC_FAA(&stock_, x);
}
int32_t aaf(int32_t x)
{
return ATOMIC_AAF(&stock_, x);
}
int32_t dec_if_gt(int32_t x, int32_t b)
{
int32_t faa(int32_t x) { return ATOMIC_FAA(&stock_, x); }
int32_t aaf(int32_t x) { return ATOMIC_AAF(&stock_, x); }
int32_t dec_if_gt(int32_t x, int32_t b) {
int32_t ov = ATOMIC_LOAD(&stock_);
int32_t nv = 0;
while (ov > b && ov != (nv = ATOMIC_VCAS(&stock_, ov, ov - x))) {
while(ov > b && ov != (nv = ATOMIC_VCAS(&stock_, ov, ov - x))) {
ov = nv;
}
return ov;
}
int32_t inc_if_lt(int32_t x, int32_t b)
{
int32_t inc_if_lt(int32_t x, int32_t b) {
int32_t ov = ATOMIC_LOAD(&stock_);
int32_t nv = 0;
while (ov < b && ov != (nv = ATOMIC_VCAS(&stock_, ov, ov + x))) {
while(ov < b && ov != (nv = ATOMIC_VCAS(&stock_, ov, ov + x))) {
ov = nv;
}
return ov;
}
int32_t cas_or_inc(int32_t cmp, int32_t val, int32_t x)
{
int32_t cas_or_inc(int32_t cmp, int32_t val, int32_t x) {
int32_t ov = ATOMIC_LOAD(&stock_);
int32_t nv = 0;
while (
(cmp == ov) ? (ov != (nv = ATOMIC_VCAS(&stock_, cmp, val))) : (ov != (nv = ATOMIC_VCAS(&stock_, ov, ov + x)))) {
while((cmp == ov)
? (ov != (nv = ATOMIC_VCAS(&stock_, cmp, val)))
: (ov != (nv = ATOMIC_VCAS(&stock_, ov, ov + x)))) {
ov = nv;
}
return ov;
}
private:
int32_t total_ CACHE_ALIGNED;
int32_t stock_ CACHE_ALIGNED;
};
class ObBlockSlicer : public ObStockCtrl {
class ObSliceAlloc;
class ObBlockSlicer: public ObStockCtrl
{
public:
static const uint32_t ITEM_MAGIC_CODE = 0XCCEEDDF1;
static const uint32_t ITEM_MAGIC_CODE_MASK = 0XFFFFFFF0;
typedef ObEmbedFixedQueue FList;
typedef ObBlockSlicer Host;
struct Item {
struct Item
{
public:
Item(Host* host) : host_(host)
{}
~Item()
{}
Item(Host* host): MAGIC_CODE_(ITEM_MAGIC_CODE), host_(host) {}
~Item(){}
uint32_t MAGIC_CODE_;
ObBlockSlicer* host_;
} __attribute__((aligned(16)));
;
} __attribute__((aligned (16)));;
public:
ObDLink dlink_ CACHE_ALIGNED;
public:
ObBlockSlicer(int32_t limit, int32_t slice_size, void* tmallocator = NULL) : tmallocator_(tmallocator)
{
ObBlockSlicer(int32_t limit, int32_t slice_size, ObSliceAlloc* slice_alloc, void* tmallocator = NULL)
: slice_alloc_(slice_alloc), tmallocator_(tmallocator) {
int64_t isize = lib::align_up2((int32_t)sizeof(Item) + slice_size, 16);
int64_t total = (limit - (int32_t)sizeof(*this)) / (isize + (int32_t)sizeof(void*));
int64_t total = (limit - (int32_t)sizeof(*this))/(isize + (int32_t)sizeof(void*));
char* istart = (char*)lib::align_up2((uint64_t)((char*)(this + 1) + sizeof(void*) * total), 16);
if (istart + isize * total > ((char*)this) + limit) {
total--;
}
flist_.init((int32_t)total);
for (int32_t i = 0; i < total; i++) {
flist_.push((void*)new (istart + i * isize) Item(this));
for(int32_t i = 0; i < total; i++) {
flist_.push((void*)new(istart + i * isize)Item(this));
}
init_stock((int32_t)total);
hash_ = cal_hash_((uint64_t)this);
}
~ObBlockSlicer()
{
~ObBlockSlicer() {
tmallocator_ = NULL;
}
uint64_t cal_hash_(uint64_t h)
static uint64_t hash(uint64_t h)
{
h ^= h >> 33;
h *= 0xff51afd7ed558ccd;
@ -263,102 +223,81 @@ public:
h ^= h >> 33;
return h;
}
Item* alloc_item()
{
return alloc_stock() ? (Item*)flist_.pop() : NULL;
Item* alloc_item() {
Item* ret = NULL;
ret = alloc_stock()? (Item*)flist_.pop(): NULL;
if (NULL != ret) {
ret->MAGIC_CODE_ = ITEM_MAGIC_CODE;
}
return ret;
}
bool free_item(Item* p, bool& first_free)
{
bool free_item(Item* p, bool& first_free) {
flist_.push(p);
return free_stock(first_free);
}
uint64_t hash() const
{
return hash_;
}
void* get_tmallocator()
{
return tmallocator_;
}
void* get_tmallocator() { return tmallocator_; }
void* get_slice_alloc() { return slice_alloc_; }
private:
uint64_t hash_;
ObSliceAlloc* slice_alloc_;
void* tmallocator_;
FList flist_ CACHE_ALIGNED;
};
class ObSliceAlloc {
class ObSliceAlloc
{
public:
enum { MAX_ARENA_NUM = 32, MAX_REF_NUM = 4096, DEFAULT_BLOCK_SIZE = OB_MALLOC_NORMAL_BLOCK_SIZE };
typedef ObSimpleSync Sync;
typedef ObBlockSlicer Block;
typedef ObBlockAllocMgr BlockAlloc;
typedef ObDListWithLock BlockList;
class Arena {
class Arena
{
public:
Arena() : blk_(NULL)
{}
Block* blk()
{
return ATOMIC_LOAD(&blk_);
}
bool cas(Block* ov, Block* nv)
{
return ATOMIC_BCAS(&blk_, ov, nv);
}
Block* clear()
{
return ATOMIC_TAS(&blk_, NULL);
}
Arena(): blk_(NULL) {}
Block* blk() { return ATOMIC_LOAD(&blk_); }
bool cas(Block* ov, Block* nv) { return ATOMIC_BCAS(&blk_, ov, nv); }
Block* clear() { return ATOMIC_TAS(&blk_, NULL); }
private:
Block* blk_;
} CACHE_ALIGNED;
ObSliceAlloc() : nway_(0), bsize_(0), isize_(0), slice_limit_(0), blk_alloc_(default_blk_alloc), tmallocator_(NULL)
{}
ObSliceAlloc(const int size, const ObMemAttr& attr, int block_size = DEFAULT_BLOCK_SIZE,
BlockAlloc& blk_alloc = default_blk_alloc, void* tmallocator = NULL)
: nway_(1), bsize_(block_size), isize_(size), attr_(attr), blk_alloc_(blk_alloc), tmallocator_(tmallocator)
{
slice_limit_ = block_size - (int32_t)sizeof(Block) - (int32_t)sizeof(Block::Item);
LIB_LOG(INFO, "ObSliceAlloc init finished", K(bsize_), K(isize_), K(slice_limit_), KP(tmallocator_));
}
~ObSliceAlloc()
{
ObSliceAlloc(): nway_(0), bsize_(0), isize_(0),
slice_limit_(0), blk_alloc_(default_blk_alloc), tmallocator_(NULL) {}
ObSliceAlloc(const int size, const ObMemAttr &attr, int block_size=DEFAULT_BLOCK_SIZE,
BlockAlloc &blk_alloc = default_blk_alloc, void* tmallocator = NULL)
: nway_(1), bsize_(block_size), isize_(size), attr_(attr),
blk_alloc_(blk_alloc), tmallocator_(tmallocator) {
slice_limit_ = block_size - (int32_t)sizeof(Block) - (int32_t)sizeof(Block::Item);
LIB_LOG(INFO, "ObSliceAlloc init finished", K(bsize_), K(isize_), K(slice_limit_), KP(tmallocator_));
}
~ObSliceAlloc() {
tmallocator_ = NULL;
}
int init(const int size, const int block_size, BlockAlloc& block_alloc, const ObMemAttr& attr)
{
int init(const int size, const int block_size, BlockAlloc& block_alloc, const ObMemAttr& attr) {
int ret = common::OB_SUCCESS;
new (this) ObSliceAlloc(size, attr, block_size, block_alloc, NULL);
new(this)ObSliceAlloc(size, attr, block_size, block_alloc, NULL);
return ret;
}
void set_nway(int nway)
{
void set_nway(int nway) {
if (nway <= 0) {
nway = 1;
} else if (nway > MAX_ARENA_NUM) {
nway = MAX_ARENA_NUM;
}
ATOMIC_STORE(&nway_, nway);
ATOMIC_STORE(&nway_, nway);
purge_extra_cached_block(nway);
}
void try_purge()
{
void try_purge() {
if (NULL == blk_list_.top()) {
purge_extra_cached_block(0);
}
}
int64_t limit()
{
return blk_alloc_.limit();
}
int64_t hold()
{
return blk_alloc_.hold();
}
void* alloc()
{
int64_t limit() { return blk_alloc_.limit(); }
int64_t hold() { return blk_alloc_.hold(); }
void* alloc() {
#ifdef OB_USE_ASAN
return ::malloc(isize_);
#else
Block::Item* ret = NULL;
int tmp_ret = OB_SUCCESS;
if (isize_ > slice_limit_) {
@ -368,7 +307,7 @@ public:
LIB_LOG(ERROR, "slice size is larger than block size, unexpected !", K(tmp_ret), K(isize_), K(slice_limit_));
}
}
while (NULL == ret && OB_SUCCESS == tmp_ret) {
while(NULL == ret && OB_SUCCESS == tmp_ret) {
Arena& arena = arena_[get_itid() % nway_];
Block* blk = arena.blk();
if (NULL == blk) {
@ -383,7 +322,7 @@ public:
}
} else {
Block* blk2release = NULL;
int64_t slot_idx = blk->hash() % MAX_REF_NUM;
int64_t slot_idx = ObBlockSlicer::hash((uint64_t)blk) % MAX_REF_NUM;
blk_ref_[slot_idx].ref(1);
if (blk == arena.blk()) {
if (NULL == (ret = blk->alloc_item())) {
@ -394,18 +333,31 @@ public:
}
blk_ref_[slot_idx].ref(-1);
if (NULL != blk2release) {
blk_ref_[blk2release->hash() % MAX_REF_NUM].sync();
blk_ref_[ObBlockSlicer::hash((uint64_t)blk2release) % MAX_REF_NUM].sync();
release_block(blk2release);
}
}
}
return NULL == ret ? NULL : (void*)(ret + 1);
return NULL == ret? NULL: (void*)(ret + 1);
#endif
}
void free(void* p)
{
void free(void* p) {
#ifdef OB_USE_ASAN
::free(p);
#else
if (NULL != p) {
Block::Item* item = (Block::Item*)p - 1;
abort_unless(Block::ITEM_MAGIC_CODE == item->MAGIC_CODE_);
Block* blk = item->host_;
#ifndef NDEBUG
abort_unless(blk->get_slice_alloc() == this);
#else
if (this != blk->get_slice_alloc()) {
LIB_LOG(ERROR, "blk is freed or alloced by different slice_alloc", K(this), K(blk->get_slice_alloc()));
return;
}
#endif
item->MAGIC_CODE_ = item->MAGIC_CODE_ & Block::ITEM_MAGIC_CODE_MASK;
bool first_free = false;
bool need_destroy = blk->free_item(item, first_free);
if (need_destroy) {
@ -414,46 +366,36 @@ public:
add_to_blist(blk);
}
}
#endif
}
void purge_extra_cached_block(int keep)
{
for (int i = MAX_ARENA_NUM - 1; i >= keep; i--) {
void purge_extra_cached_block(int keep) {
for(int i = MAX_ARENA_NUM - 1; i >= keep; i--) {
Arena& arena = arena_[i];
Block* old_blk = arena.clear();
if (NULL != old_blk) {
blk_ref_[old_blk->hash() % MAX_REF_NUM].sync();
blk_ref_[ObBlockSlicer::hash((uint64_t)old_blk) % MAX_REF_NUM].sync();
release_block(old_blk);
}
}
}
int64_t to_string(char* buf, const int64_t limit) const
int64_t to_string(char *buf, const int64_t limit) const
{
return snprintf(buf,
limit,
"SliceAlloc: nway=%d bsize/isize=%d/%d limit=%d attr=%s",
nway_,
bsize_,
isize_,
slice_limit_,
to_cstring(attr_));
return snprintf(buf, limit, "SliceAlloc: nway=%d bsize/isize=%d/%d limit=%d attr=%s",
nway_, bsize_, isize_, slice_limit_, to_cstring(attr_));
}
private:
void release_block(Block* blk)
{
void release_block(Block* blk) {
if (blk->release()) {
add_to_blist(blk);
}
}
void add_to_blist(Block* blk)
{
void add_to_blist(Block* blk) {
blk_list_.add(&blk->dlink_);
if (blk->recyle()) {
destroy_block(blk);
}
}
Block* get_from_blist()
{
Block* get_from_blist() {
Block* ret = NULL;
ObDLink* dlink = NULL;
do {
@ -465,29 +407,27 @@ private:
}
}
reclaim_sync_.ref(-1);
} while (NULL == ret && dlink != NULL);
} while(NULL == ret && dlink != NULL);
if (NULL != ret) {
blk_list_.del(&ret->dlink_);
}
return ret;
}
Block* prepare_block()
{
Block* ret_blk = get_from_blist();
Block* prepare_block() {
Block *ret_blk = get_from_blist();
if (NULL == ret_blk) {
void* ptr = NULL;
void *ptr = NULL;
if (NULL != (ptr = blk_alloc_.alloc_block(bsize_, attr_))) {
ret_blk = new (ptr) Block(bsize_, isize_, tmallocator_);
ret_blk = new(ptr)Block(bsize_, isize_, this, tmallocator_);
}
}
return ret_blk;
}
void destroy_block(Block* blk)
{
void destroy_block(Block* blk) {
blk_list_.del(&blk->dlink_);
reclaim_sync_.sync();
blk_alloc_.free_block(blk, bsize_);
// try_purge();
//try_purge();
}
protected:
@ -500,9 +440,9 @@ protected:
BlockList blk_list_ CACHE_ALIGNED;
Arena arena_[MAX_ARENA_NUM];
Sync blk_ref_[MAX_REF_NUM];
BlockAlloc& blk_alloc_;
BlockAlloc &blk_alloc_;
void* tmallocator_;
};
}; // end namespace common
}; // end namespace oceanbase
}; // end namespace common
}; // end namespace oceanbase
#endif /* OCEANBASE_ALLOCATOR_OB_SLICE_ALLOC_H_ */