270 lines
8.7 KiB
C++
270 lines
8.7 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.
|
|
*/
|
|
|
|
#ifndef OB_TABLE_STORE_STAT_MGR_H_
|
|
#define OB_TABLE_STORE_STAT_MGR_H_
|
|
#include <stdint.h>
|
|
#include "lib/oblog/ob_log_module.h"
|
|
#include "lib/utility/ob_print_utils.h"
|
|
#include "lib/lock/ob_spin_rwlock.h"
|
|
#include "lib/allocator/page_arena.h"
|
|
#include "lib/hash_func/murmur_hash.h"
|
|
#include "lib/hash/ob_hashmap.h"
|
|
#include "lib/task/ob_timer.h"
|
|
#include "common/ob_tablet_id.h"
|
|
#include "share/ob_ls_id.h"
|
|
|
|
namespace oceanbase
|
|
{
|
|
namespace storage
|
|
{
|
|
struct ObMergeIterStat
|
|
{
|
|
public:
|
|
ObMergeIterStat() { reset(); };
|
|
~ObMergeIterStat() = default;
|
|
OB_INLINE void reset() { MEMSET(this, 0, sizeof(ObMergeIterStat)); }
|
|
bool is_valid() const;
|
|
int add(const ObMergeIterStat& other);
|
|
ObMergeIterStat & operator=(const ObMergeIterStat &other);
|
|
TO_STRING_KV(K_(call_cnt), K_(output_row_cnt));
|
|
|
|
int64_t call_cnt_;
|
|
int64_t output_row_cnt_;
|
|
};
|
|
|
|
struct ObBlockAccessStat
|
|
{
|
|
public:
|
|
ObBlockAccessStat() { reset(); };
|
|
~ObBlockAccessStat() = default;
|
|
OB_INLINE void reset() { MEMSET(this, 0, sizeof(ObBlockAccessStat)); }
|
|
bool is_valid() const;
|
|
int add(const ObBlockAccessStat& other);
|
|
ObBlockAccessStat & operator=(const ObBlockAccessStat &other);
|
|
TO_STRING_KV(K_(effect_read_cnt), K_(empty_read_cnt));
|
|
|
|
int64_t effect_read_cnt_;
|
|
int64_t empty_read_cnt_;
|
|
};
|
|
|
|
struct ObTableStoreStat
|
|
{
|
|
public:
|
|
ObTableStoreStat();
|
|
~ObTableStoreStat() = default;
|
|
|
|
void reset();
|
|
void reuse();
|
|
bool is_valid() const;
|
|
int add(const ObTableStoreStat& other);
|
|
ObTableStoreStat &operator=(const ObTableStoreStat& other);
|
|
OB_INLINE bool enable_get_row_cache() const
|
|
{
|
|
return row_cache_miss_cnt_ < common::MAX_MULTI_GET_CACHE_AWARE_ROW_NUM
|
|
|| row_cache_hit_cnt_ > row_cache_miss_cnt_ / 2;
|
|
}
|
|
OB_INLINE bool enable_put_row_cache() const
|
|
{
|
|
return row_cache_put_cnt_ < common::MAX_MULTI_GET_CACHE_AWARE_ROW_NUM;
|
|
}
|
|
OB_INLINE bool enable_put_fuse_row_cache(const int64_t threshold) const
|
|
{
|
|
return fuse_row_cache_put_cnt_ < threshold;
|
|
}
|
|
OB_INLINE bool enable_get_fuse_row_cache(const int64_t threshold) const
|
|
{
|
|
return fuse_row_cache_miss_cnt_ < threshold
|
|
|| fuse_row_cache_hit_cnt_ > fuse_row_cache_miss_cnt_ / 4;
|
|
}
|
|
OB_INLINE bool enable_bf_cache() const
|
|
{
|
|
return (bf_access_cnt_ < common::MAX_MULTI_GET_CACHE_AWARE_ROW_NUM
|
|
|| bf_filter_cnt_ > (bf_access_cnt_ / 8));
|
|
}
|
|
OB_INLINE bool enable_sstable_bf_cache() const
|
|
{
|
|
return (sstable_bf_access_cnt_ < common::MAX_MULTI_GET_CACHE_AWARE_ROW_NUM / 5
|
|
|| sstable_bf_filter_cnt_ > sstable_bf_access_cnt_ / 4);
|
|
}
|
|
OB_INLINE int64_t get_empty_read_cnt() const
|
|
{
|
|
return exist_row_.empty_read_cnt_ + get_row_.empty_read_cnt_ + scan_row_.empty_read_cnt_;
|
|
}
|
|
TO_STRING_KV(K_(ls_id), K_(tablet_id), K_(table_id),
|
|
K_(row_cache_hit_cnt), K_(row_cache_miss_cnt), K_(row_cache_put_cnt),
|
|
K_(bf_filter_cnt), K_(bf_empty_read_cnt), K_(bf_access_cnt),
|
|
K_(block_cache_hit_cnt), K_(block_cache_miss_cnt),
|
|
K_(access_row_cnt), K_(output_row_cnt), K_(fuse_row_cache_hit_cnt),
|
|
K_(fuse_row_cache_miss_cnt), K_(fuse_row_cache_put_cnt),
|
|
K_(macro_access_cnt), K_(micro_access_cnt), K_(pushdown_micro_access_cnt),
|
|
K_(pushdown_row_access_cnt), K_(pushdown_row_select_cnt),
|
|
K_(single_get_stat), K_(multi_get_stat), K_(index_back_stat),
|
|
K_(single_scan_stat), K_(multi_scan_stat),
|
|
K_(exist_row), K_(get_row), K_(scan_row),
|
|
K_(sstable_bf_filter_cnt), K_(sstable_bf_empty_read_cnt),
|
|
K_(sstable_bf_access_cnt), K_(rowkey_prefix),
|
|
K_(logical_read_cnt), K_(physical_read_cnt));
|
|
|
|
share::ObLSID ls_id_;
|
|
common::ObTabletID tablet_id_;
|
|
common::ObTableID table_id_;
|
|
int64_t row_cache_hit_cnt_;
|
|
int64_t row_cache_miss_cnt_;
|
|
int64_t row_cache_put_cnt_;
|
|
int64_t bf_filter_cnt_;
|
|
int64_t bf_empty_read_cnt_;
|
|
int64_t bf_access_cnt_;
|
|
int64_t block_cache_hit_cnt_;
|
|
int64_t block_cache_miss_cnt_;
|
|
int64_t index_block_cache_hit_cnt_;
|
|
int64_t index_block_cache_miss_cnt_;
|
|
int64_t access_row_cnt_;
|
|
int64_t output_row_cnt_;
|
|
int64_t fuse_row_cache_hit_cnt_;
|
|
int64_t fuse_row_cache_miss_cnt_;
|
|
int64_t fuse_row_cache_put_cnt_;
|
|
int64_t macro_access_cnt_;
|
|
int64_t micro_access_cnt_;
|
|
int64_t pushdown_micro_access_cnt_;
|
|
int64_t pushdown_row_access_cnt_;
|
|
int64_t pushdown_row_select_cnt_;
|
|
ObMergeIterStat single_get_stat_;
|
|
ObMergeIterStat multi_get_stat_;
|
|
ObMergeIterStat index_back_stat_; // index back only works in multi_get mode
|
|
ObMergeIterStat single_scan_stat_;
|
|
ObMergeIterStat multi_scan_stat_;
|
|
ObBlockAccessStat exist_row_;
|
|
ObBlockAccessStat get_row_;
|
|
ObBlockAccessStat scan_row_;
|
|
int64_t sstable_bf_filter_cnt_;
|
|
int64_t sstable_bf_empty_read_cnt_;
|
|
int64_t sstable_bf_access_cnt_;
|
|
int64_t rowkey_prefix_;
|
|
int64_t logical_read_cnt_;
|
|
int64_t physical_read_cnt_;
|
|
};
|
|
|
|
struct ObTableStoreStatKey
|
|
{
|
|
public:
|
|
ObTableStoreStatKey() : table_id_(common::OB_INVALID_ID), tablet_id_(common::OB_INVALID_ID) {}
|
|
ObTableStoreStatKey(const ObTableID table_id, const ObTabletID tablet_id) : table_id_(table_id), tablet_id_(tablet_id) {}
|
|
~ObTableStoreStatKey() {}
|
|
OB_INLINE uint64_t hash() const
|
|
{
|
|
uint64_t hash_ret = 0;
|
|
hash_ret = common::murmurhash(&table_id_, sizeof(ObTableID), 0);
|
|
hash_ret = common::murmurhash(&tablet_id_, sizeof(ObTabletID), hash_ret);
|
|
return hash_ret;
|
|
}
|
|
int hash(uint64_t &hash_val) const
|
|
{
|
|
hash_val = hash();
|
|
return OB_SUCCESS;
|
|
}
|
|
OB_INLINE bool operator ==(const ObTableStoreStatKey &other) const
|
|
{
|
|
return (table_id_ == other.table_id_) && (tablet_id_ == other.tablet_id_);
|
|
}
|
|
OB_INLINE bool operator !=(const ObTableStoreStatKey &other) const
|
|
{
|
|
return (*this == other);
|
|
}
|
|
TO_STRING_KV(K_(table_id), K_(tablet_id));
|
|
common::ObTableID table_id_;
|
|
common::ObTabletID tablet_id_;
|
|
};
|
|
|
|
struct ObTableStoreStatNode
|
|
{
|
|
public:
|
|
ObTableStoreStatNode() : pre_(NULL), next_(NULL), stat_(NULL) {}
|
|
~ObTableStoreStatNode() { reset(); }
|
|
OB_INLINE void reset() { pre_ = next_ = NULL; stat_ = NULL; }
|
|
ObTableStoreStatNode *pre_;
|
|
ObTableStoreStatNode *next_;
|
|
ObTableStoreStat *stat_;
|
|
};
|
|
|
|
class ObTableStoreStatIterator
|
|
{
|
|
public:
|
|
ObTableStoreStatIterator();
|
|
virtual ~ObTableStoreStatIterator();
|
|
int open();
|
|
int get_next_stat(ObTableStoreStat &stat);
|
|
void reset();
|
|
private:
|
|
int64_t cur_idx_;
|
|
bool is_opened_;
|
|
};
|
|
|
|
// TODO(@DanLing) remove ObTableStoreStatMgr
|
|
class ObTableStoreStatMgr
|
|
{
|
|
public:
|
|
int init(const int64_t limit_cnt = DEFAULT_MAX_CNT);
|
|
void stop();
|
|
void wait();
|
|
void reset();
|
|
void destroy();
|
|
static ObTableStoreStatMgr &get_instance();
|
|
int report_stat(const ObTableStoreStat &stat);
|
|
private:
|
|
ObTableStoreStatMgr();
|
|
virtual ~ObTableStoreStatMgr();
|
|
void move_node_to_head(ObTableStoreStatNode *node);
|
|
int get_table_store_stat(const int64_t idx, ObTableStoreStat &stat);
|
|
void run_report_task();
|
|
int add_stat(const ObTableStoreStat &stat);
|
|
|
|
friend class ObTableStoreStatIterator;
|
|
typedef common::hash::ObHashMap<ObTableStoreStatKey, ObTableStoreStatNode*, common::hash::NoPthreadDefendMode> TableStoreMap;
|
|
static const int64_t DEFAULT_MAX_CNT = 40000; // 40000 * (sizeof(key)(16) + sizeof(node*)(8) + sizeof(node)(24) + sizeof(stat)(96)) = 6.25MB
|
|
static const int64_t MAX_PENDDING_CNT = 100000; // 100000 * sizeof(stat)(96) = 9.2MB
|
|
static const int64_t REPORT_TASK_INTERVAL_US = 1000 * 1000; // 1 seconds
|
|
|
|
class ReportTask : public common::ObTimerTask
|
|
{
|
|
public:
|
|
ReportTask() : stat_mgr_(NULL) {}
|
|
virtual ~ReportTask() { destroy(); }
|
|
int init(ObTableStoreStatMgr *stat_mgr);
|
|
void destroy() { stat_mgr_ = NULL; }
|
|
virtual void runTimerTask();
|
|
private:
|
|
ObTableStoreStatMgr *stat_mgr_;
|
|
DISALLOW_COPY_AND_ASSIGN(ReportTask);
|
|
};
|
|
|
|
bool is_inited_;
|
|
common::SpinRWLock lock_;
|
|
TableStoreMap quick_map_;
|
|
int64_t cur_cnt_;
|
|
int64_t limit_cnt_;
|
|
ObTableStoreStatNode *lru_head_;
|
|
ObTableStoreStatNode *lru_tail_;
|
|
ObTableStoreStat stat_array_[DEFAULT_MAX_CNT];
|
|
ObTableStoreStatNode node_pool_[DEFAULT_MAX_CNT];
|
|
|
|
// stat buffer area
|
|
ObTableStoreStat stat_queue_[MAX_PENDDING_CNT];
|
|
uint64_t report_cursor_ CACHE_ALIGNED;
|
|
uint64_t pending_cursor_ CACHE_ALIGNED;
|
|
ReportTask report_task_;
|
|
};
|
|
|
|
} //namespace storage
|
|
} //namespace oceanbase
|
|
#endif /* OB_TABLE_STORE_STAT_MGR_H_ */
|