!5961 优化GSC的淘汰内存回收和内存统计

Merge pull request !5961 from 杨皓/master
This commit is contained in:
opengauss_bot
2024-08-06 09:13:01 +00:00
committed by Gitee
14 changed files with 119 additions and 97 deletions

View File

@ -51,22 +51,6 @@ static uint64 GetPartEstimateSize(GlobalPartitionEntry *entry)
return part_size;
}
template <bool is_relation>
void GlobalBaseDefCache::RemoveElemFromBucket(GlobalBaseEntry *base)
{
if (is_relation) {
GlobalRelationEntry *entry = (GlobalRelationEntry *)base;
uint64 rel_size = GetRelEstimateSize(entry);
pg_atomic_fetch_sub_u64(&m_base_space, AllocSetContextUsedSpace(((AllocSet)entry->rel_mem_manager)));
m_db_entry->MemoryEstimateSub(rel_size);
} else {
GlobalPartitionEntry *entry = (GlobalPartitionEntry *)base;
uint64 part_size = GetPartEstimateSize(entry);
pg_atomic_fetch_sub_u64(&m_base_space, part_size);
m_db_entry->MemoryEstimateSub(part_size);
}
m_bucket_list.RemoveElemFromBucket(&base->cache_elem);
}
template <bool is_relation>
void GlobalBaseDefCache::AddHeadToBucket(Index hash_index, GlobalBaseEntry *base)
{
@ -86,16 +70,11 @@ void GlobalBaseDefCache::AddHeadToBucket(Index hash_index, GlobalBaseEntry *base
template void GlobalBaseDefCache::AddHeadToBucket<true>(Index hash_index, GlobalBaseEntry *base);
template void GlobalBaseDefCache::AddHeadToBucket<false>(Index hash_index, GlobalBaseEntry *base);
template void GlobalBaseDefCache::RemoveElemFromBucket<true>(GlobalBaseEntry *base);
template void GlobalBaseDefCache::RemoveElemFromBucket<false>(GlobalBaseEntry *base);
template <bool is_relation>
void GlobalBaseEntry::Free(GlobalBaseEntry *entry)
{
Assert(entry->refcount == 0);
if (is_relation) {
Assert(entry->type == GLOBAL_RELATION_ENTRY);
if (entry->type == GLOBAL_RELATION_ENTRY) {
if (((GlobalRelationEntry *)entry)->rel_mem_manager != NULL) {
MemoryContextDelete(((GlobalRelationEntry *)entry)->rel_mem_manager);
}
@ -107,8 +86,30 @@ void GlobalBaseEntry::Free(GlobalBaseEntry *entry)
}
pfree(entry);
}
template void GlobalBaseEntry::Free<true>(GlobalBaseEntry *entry);
template void GlobalBaseEntry::Free<false>(GlobalBaseEntry *entry);
static void free_dead_defentry_internal(GlobalBaseEntry *entry, volatile uint64 *base_space,
GlobalSysDBCacheEntry *db_entry)
{
Assert(entry->refcount == 0);
if (entry->type == GLOBAL_RELATION_ENTRY) {
if (((GlobalRelationEntry *)entry)->rel_mem_manager != NULL) {
GlobalRelationEntry *rel_entry = (GlobalRelationEntry *)entry;
uint64 rel_size = GetRelEstimateSize(rel_entry);
pg_atomic_fetch_sub_u64(
base_space, AllocSetContextUsedSpace(((AllocSet)rel_entry->rel_mem_manager)));
db_entry->MemoryEstimateSub(rel_size);
}
} else {
Assert(entry->type == GLOBAL_PARTITION_ENTRY);
if (((GlobalPartitionEntry *)entry)->part != NULL) {
GlobalPartitionEntry *part_entry = (GlobalPartitionEntry *)entry;
uint64 part_size = GetPartEstimateSize(part_entry);
pg_atomic_fetch_sub_u64(base_space, part_size);
db_entry->MemoryEstimateSub(part_size);
}
}
GlobalBaseEntry::Free(entry);
}
void GlobalBaseEntry::Release()
{
@ -166,8 +167,18 @@ GlobalBaseEntry *GlobalBaseDefCache::SearchReadOnly(Oid obj_oid, uint32 hash_val
}
template <bool is_relation>
void GlobalBaseDefCache::FreeDeadEntrys()
void GlobalBaseDefCache::FreeDeadElements()
{
if (m_dead_entries.GetLength() == 0) {
return;
}
/* only one clean is enough */
ResourceOwnerEnlargeGlobalIsExclusive(t_thrd.utils_cxt.CurrentResourceOwner);
if (!atomic_compare_exchange_u32(&m_recovery_basedef_flag, 0, 1)) {
return;
}
ResourceOwnerRememberGlobalIsExclusive(t_thrd.utils_cxt.CurrentResourceOwner, &m_recovery_basedef_flag);
while (m_dead_entries.GetLength() > 0) {
Dlelem *elt = m_dead_entries.RemoveHead();
if (elt == NULL) {
@ -179,12 +190,15 @@ void GlobalBaseDefCache::FreeDeadEntrys()
m_dead_entries.AddTail(&entry->cache_elem);
break;
} else {
entry->Free<is_relation>(entry);
free_dead_defentry_internal(entry, &m_base_space, m_db_entry);
}
}
Assert(m_recovery_basedef_flag == 1);
ResourceOwnerForgetGlobalIsExclusive(t_thrd.utils_cxt.CurrentResourceOwner, &m_recovery_basedef_flag);
atomic_compare_exchange_u32(&m_recovery_basedef_flag, 1, 0);
}
template void GlobalBaseDefCache::FreeDeadEntrys<false>();
template void GlobalBaseDefCache::FreeDeadEntrys<true>();
template void GlobalBaseDefCache::FreeDeadElements<false>();
template void GlobalBaseDefCache::FreeDeadElements<true>();
template <bool is_relation>
void GlobalBaseDefCache::Invalidate(Oid dbid, Oid obj_oid)
@ -268,9 +282,9 @@ template void GlobalBaseDefCache::ResetCaches<true, true>();
template <bool is_relation>
void GlobalBaseDefCache::HandleDeadEntry(GlobalBaseEntry *entry)
{
RemoveElemFromBucket<is_relation>(entry);
m_bucket_list.RemoveElemFromBucket(&entry->cache_elem);
if (entry->refcount == 0) {
m_dead_entries.AddHead(&entry->cache_elem);
free_dead_defentry_internal(entry, &m_base_space, m_db_entry);
} else {
m_dead_entries.AddTail(&entry->cache_elem);
}
@ -396,4 +410,5 @@ GlobalBaseDefCache::GlobalBaseDefCache(Oid db_oid, bool is_shared, GlobalSysDBCa
m_base_space = 0;
m_obj_locks = NULL;
m_db_entry = entry;
m_recovery_basedef_flag = 0;
}

View File

@ -39,7 +39,9 @@ template <bool force>
void GlobalSysDBCacheEntry::ResetDBCache()
{
m_systabCache->ResetCatCaches<force>();
m_systabCache->FreeDeadElements();
m_tabdefCache->ResetRelCaches<force>();
m_tabdefCache->FreeDeadElements<true>();
if (m_dbOid != InvalidOid) {
m_partdefCache->ResetPartCaches<force>();
}
@ -48,9 +50,12 @@ void GlobalSysDBCacheEntry::ResetDBCache()
void GlobalSysDBCacheEntry::RemoveTailElements()
{
m_systabCache->RemoveAllTailElements();
m_systabCache->FreeDeadElements();
m_tabdefCache->RemoveAllTailElements<true>();
m_tabdefCache->FreeDeadElements<true>();
if (m_dbOid != InvalidOid) {
m_partdefCache->RemoveAllTailElements<false>();
m_partdefCache->FreeDeadElements<false>();
}
}

View File

@ -77,7 +77,7 @@ void GlobalPartDefCache::Insert(Partition part, uint32 hash_value)
bool found = GlobalBaseDefCache::EntryExist(part->pd_id, hash_index);
if (found) {
PthreadRWlockUnlock(LOCAL_SYSDB_RESOWNER, obj_lock);
entry->Free<false>(entry);
GlobalBaseEntry::Free(entry);
return;
}
GlobalBaseDefCache::AddHeadToBucket<false>(hash_index, entry);

View File

@ -86,14 +86,6 @@ void GlobalSysDBCache::ReleaseGSCEntry(GlobalSysDBCacheEntry *entry)
pg_atomic_fetch_sub_u64(&entry->m_refcount, 1);
}
void GlobalSysDBCache::RemoveElemFromBucket(GlobalSysDBCacheEntry *entry)
{
/* shared db never remove */
Assert(entry->m_dbOid != InvalidOid);
m_bucket_list.RemoveElemFromBucket(&entry->m_cache_elem);
m_dbstat_manager.RecordSwapOutDBEntry(entry);
}
void GlobalSysDBCache::AddHeadToBucket(Index hash_index, GlobalSysDBCacheEntry *entry)
{
m_bucket_list.AddHeadToBucket(hash_index, &entry->m_cache_elem);
@ -103,11 +95,22 @@ void GlobalSysDBCache::AddHeadToBucket(Index hash_index, GlobalSysDBCacheEntry *
m_dbstat_manager.ThreadHoldDB(entry);
}
static void free_dead_dbs_internal(GlobalSysDBCacheEntry *entry)
{
/* sub all to delete, make sure no one use the entry */
entry->MemoryEstimateSub(entry->m_rough_used_space);
Assert(entry->m_rough_used_space == 0);
GlobalSysDBCacheEntry::Free(entry);
}
void GlobalSysDBCache::HandleDeadDB(GlobalSysDBCacheEntry *entry)
{
RemoveElemFromBucket(entry);
/* shared db never remove */
Assert(entry->m_dbOid != InvalidOid);
m_bucket_list.RemoveElemFromBucket(&entry->m_cache_elem);
m_dbstat_manager.RecordSwapOutDBEntry(entry);
if (entry->m_refcount == 0) {
m_dead_dbs.AddHead(&entry->m_cache_elem);
free_dead_dbs_internal(entry);
} else {
m_dead_dbs.AddTail(&entry->m_cache_elem);
}
@ -131,10 +134,7 @@ void GlobalSysDBCache::FreeDeadDBs()
m_dead_dbs.AddTail(&dbEntry->m_cache_elem);
break;
} else {
/* sub all to delete, make sure no one use the entry */
dbEntry->MemoryEstimateSub(dbEntry->m_rough_used_space);
Assert(dbEntry->m_rough_used_space == 0);
dbEntry->Free(dbEntry);
free_dead_dbs_internal(dbEntry);
}
}
}
@ -179,7 +179,7 @@ GlobalSysDBCacheEntry *GlobalSysDBCache::SearchGSCEntry(Oid db_id, Index hash_in
if (existDbEntry != NULL) {
m_dbstat_manager.ThreadHoldDB(existDbEntry);
PthreadRWlockUnlock(LOCAL_SYSDB_RESOWNER, &m_db_locks[hash_index]);
newDbEntry->Free(newDbEntry);
GlobalSysDBCacheEntry::Free(newDbEntry);
return existDbEntry;
}

View File

@ -149,7 +149,7 @@ void GlobalCatCList::Release()
void GlobalSysTupCache::ReleaseGlobalCatCTup(GlobalCatCTup *ct)
{
if (unlikely(!ct->canInsertGSC)) {
pfree(ct);
GlobalCatCTup::Free(ct);
return;
}
(void)pg_atomic_fetch_sub_u64(&ct->refcount, 1);
@ -158,7 +158,7 @@ void GlobalSysTupCache::ReleaseGlobalCatCTup(GlobalCatCTup *ct)
void GlobalSysTupCache::ReleaseGlobalCatCList(GlobalCatCList *cl)
{
if (unlikely(!cl->canInsertGSC)) {
FreeGlobalCatCList(cl);
GlobalCatCList::Free(cl);
return;
}
(void)pg_atomic_fetch_sub_u64(&cl->refcount, 1);
@ -185,12 +185,13 @@ void GlobalSysTupCache::AddHeadToCCList(GlobalCatCList *cl)
pg_atomic_fetch_add_u64(m_tup_space, cl_size);
DLAddHead(&cc_lists, &cl->cache_elem);
}
void GlobalSysTupCache::RemoveElemFromCCList(GlobalCatCList *cl)
static void free_dead_cl_internal(GlobalCatCList *cl, volatile uint64 *tup_space, GlobalSysDBCacheEntry *entry)
{
uint64 cl_size = GetClEstimateSize(cl);
m_dbEntry->MemoryEstimateSub(cl_size);
pg_atomic_fetch_sub_u64(m_tup_space, cl_size);
DLRemove(&cl->cache_elem);
entry->MemoryEstimateSub(cl_size);
pg_atomic_fetch_sub_u64(tup_space, cl_size);
GlobalCatCList::Free(cl);
}
void GlobalSysTupCache::AddHeadToBucket(Index hash_index, GlobalCatCTup *ct)
@ -203,23 +204,23 @@ void GlobalSysTupCache::AddHeadToBucket(Index hash_index, GlobalCatCTup *ct)
DLAddHead(&cc_buckets[hash_index], &ct->cache_elem);
}
void GlobalSysTupCache::RemoveElemFromBucket(GlobalCatCTup *ct)
static void free_dead_ct_internal(GlobalCatCTup *ct, volatile uint64 *tup_space, GlobalSysDBCacheEntry *entry)
{
uint64 ct_size = GetCtEstimateSize(ct);
pg_atomic_fetch_sub_u64(m_tup_space, ct_size);
pg_atomic_fetch_sub_u64(tup_space, ct_size);
/* free space of tup */
m_dbEntry->MemoryEstimateSub(ct_size);
pg_atomic_fetch_sub_u64(m_tup_count, 1);
DLRemove(&ct->cache_elem);
entry->MemoryEstimateSub(ct_size);
GlobalCatCTup::Free(ct);
}
void GlobalSysTupCache::HandleDeadGlobalCatCTup(GlobalCatCTup *ct)
{
/* this func run in wr lock, so dont call free directly */
RemoveElemFromBucket(ct);
pg_atomic_fetch_sub_u64(m_tup_count, 1);
DLRemove(&ct->cache_elem);
ct->dead = true;
if (ct->refcount == 0) {
m_dead_cts.AddHead(&ct->cache_elem);
free_dead_ct_internal(ct, m_tup_space, m_dbEntry);
} else {
m_dead_cts.AddTail(&ct->cache_elem);
}
@ -238,7 +239,7 @@ void GlobalSysTupCache::FreeDeadCts()
m_dead_cts.AddTail(&ct->cache_elem);
break;
} else {
pfree(ct);
free_dead_ct_internal(ct, m_tup_space, m_dbEntry);
}
}
}
@ -283,22 +284,22 @@ void GlobalSysTupCache::RemoveTailTupleElements(Index hash_index)
ResourceOwnerForgetGlobalIsExclusive(LOCAL_SYSDB_RESOWNER, &m_is_tup_swappingouts[hash_index]);
}
void GlobalSysTupCache::FreeGlobalCatCList(GlobalCatCList *cl)
void GlobalCatCList::Free(GlobalCatCList *cl)
{
Assert(cl->refcount == 0 || !cl->canInsertGSC);
for (int i = 0; i < cl->n_members; i++) {
cl->members[i]->Release();
}
CatCacheFreeKeys(m_relinfo.cc_tupdesc, cl->nkeys, m_relinfo.cc_keyno, cl->keys);
pfree(cl);
CatCacheFreeKeys(cl->my_cache->GetCCTupleDesc(), cl->nkeys, cl->my_cache->GetCCKeyno(), cl->keys);
pfree_ext(cl);
}
void GlobalSysTupCache::HandleDeadGlobalCatCList(GlobalCatCList *cl)
{
/* this func run in wr lock, so dont call free directly */
RemoveElemFromCCList(cl);
DLRemove(&cl->cache_elem);
if (cl->refcount == 0) {
m_dead_cls.AddHead(&cl->cache_elem);
free_dead_cl_internal(cl, m_tup_space, m_dbEntry);
} else {
m_dead_cls.AddTail(&cl->cache_elem);
}
@ -317,7 +318,7 @@ void GlobalSysTupCache::FreeDeadCls()
m_dead_cls.AddTail(&cl->cache_elem);
break;
} else {
FreeGlobalCatCList(cl);
free_dead_cl_internal(cl, m_tup_space, m_dbEntry);
}
}
FreeDeadCts();
@ -581,7 +582,7 @@ GlobalCatCTup *GlobalSysTupCache::InsertHeapTupleIntoGlobalCatCache(InsertCatTup
if (unlikely(ct != NULL)) {
/* other thread has inserted one */
PthreadRWlockUnlock(LOCAL_SYSDB_RESOWNER, bucket_lock);
pfree_ext(new_ct);
GlobalCatCTup::Free(new_ct);
return ct;
}
@ -1047,7 +1048,7 @@ GlobalCatCList *GlobalSysTupCache::InsertListIntoCatCacheList(InsertCatListInfo
ResourceOwnerRememberGlobalCatCList(LOCAL_SYSDB_RESOWNER, exist_cl);
/* we need mark clist's refcont to 0 then do real free up. */
cl->refcount = 0;
FreeGlobalCatCList(cl);
GlobalCatCList::Free(cl);
cl = exist_cl;
} else {
AddHeadToCCList(cl);

View File

@ -515,7 +515,7 @@ void GlobalTabDefCache::Insert(Relation rel, uint32 hash_value)
bool found = GlobalBaseDefCache::EntryExist(rel->rd_id, hash_index);
if (found) {
PthreadRWlockUnlock(LOCAL_SYSDB_RESOWNER, &m_obj_locks[hash_index]);
entry->Free<true>(entry);
GlobalBaseEntry::Free(entry);
return;
}

View File

@ -2349,7 +2349,7 @@ void ResourceOwnerReleaseGlobalBaseEntry(ResourceOwner owner, bool isCommit)
}
if (unlikely(entry->refcount == 0)) {
/* palloc fail */
entry->FreeError();
GlobalBaseEntry::Free(entry);
} else {
entry->Release();
}

View File

@ -72,6 +72,7 @@ public:
}
template <bool is_relation>
void RemoveAllTailElements();
template <bool is_relation> void FreeDeadElements(); /* free elem */
protected:
/* base class initialization funciton */
@ -101,14 +102,12 @@ protected:
/* fucntions to remove/free elem from GSC hashtable */
template <bool is_relation> void HandleDeadEntry(GlobalBaseEntry *entry); /* remove from hashtable */
template <bool is_relation> void FreeDeadEntrys(); /* free elem */
/* function to handle GSC memory swapout */
template <bool is_relation, bool force> void ResetCaches();
template <bool is_relation> void RemoveTailElements(Index hash_index);
/* function to add/remove elem to GSC hashtable */
template <bool is_relation> void RemoveElemFromBucket(GlobalBaseEntry *base);
template <bool is_relation> void AddHeadToBucket(Index hash_index, GlobalBaseEntry *base);
/* GSC Identifier fields */
@ -120,6 +119,7 @@ protected:
char m_relkind; /* dev-debug only, no real process so far */
volatile uint32 *m_is_swappingouts;
volatile uint32 m_recovery_basedef_flag;
/* GSC statistic information, assigned from GlobalSysCacheStat class */
volatile uint64 *m_searches;

View File

@ -48,7 +48,7 @@ public:
*/
GlobalPartitionEntry *SearchReadOnly(Oid partRelOid, uint32 hash_value)
{
GlobalBaseDefCache::FreeDeadEntrys<false>();
GlobalBaseDefCache::FreeDeadElements<false>();
GlobalPartitionEntry *entry =
(GlobalPartitionEntry *)GlobalBaseDefCache::SearchReadOnly(partRelOid, hash_value);
return entry;
@ -60,7 +60,7 @@ public:
return;
}
GlobalBaseDefCache::ResetCaches<false, force>();
GlobalBaseDefCache::FreeDeadEntrys<false>();
GlobalBaseDefCache::FreeDeadElements<false>();
}
inline void Invalidate(Oid dbOid, Oid partRelOid)

View File

@ -76,18 +76,7 @@ struct GlobalBaseEntry {
volatile uint64 refcount;
Dlelem cache_elem;
void Release();
template <bool is_relation>
static void Free(GlobalBaseEntry *entry);
void FreeError()
{
if (type == GLOBAL_RELATION_ENTRY) {
Free<true>(this);
} else {
Assert(type == GLOBAL_PARTITION_ENTRY);
Free<false>(this);
}
}
};
struct GlobalRelationEntry : public GlobalBaseEntry {
Relation rel;

View File

@ -186,8 +186,6 @@ private:
void InitRelForInitSysCacheFlag();
void InitSysCacheRelIds();
void RemoveElemFromBucket(GlobalSysDBCacheEntry *entry);
void AddHeadToBucket(Index hash_index, GlobalSysDBCacheEntry *entry);
/* Flag to indicate if inited */

View File

@ -65,6 +65,17 @@ public:
template <bool force>
void ResetCatCaches();
void FreeDeadElements()
{
for (int i = 0; i < SysCacheSize; i++) {
if (m_global_systupcaches[i] == NULL) {
continue;
}
m_global_systupcaches[i]->FreeDeadCls();
m_global_systupcaches[i]->FreeDeadCts();
}
}
void RemoveAllTailElements();
/*

View File

@ -103,6 +103,10 @@ struct GlobalCatCTup {
HeapTupleData tuple; /* tuple management header */
void Release();
static void Free(GlobalCatCTup *ct)
{
pfree_ext(ct);
}
};
/*
@ -133,6 +137,7 @@ struct GlobalCatCList {
GlobalCatCTup *members[FLEXIBLE_ARRAY_MEMBER];
void Release();
static void Free(GlobalCatCList *cl);
};
/*
@ -305,7 +310,10 @@ public:
{
return m_relinfo.cc_reloid;
}
inline int *GetCCKeyno()
{
return m_relinfo.cc_keyno;
}
void Init();
inline bool Inited()
{
@ -323,7 +331,8 @@ public:
uint32 hash_value, Datum *arguments, oidvector* argModes, bool is_disposable);
GlobalCatCTup *SearchTupleMissWithArgModes(InsertCatTupInfo *tup_info, oidvector* argModes);
#endif
void FreeDeadCts();
void FreeDeadCls();
bool enable_rls;
private:
/*
@ -375,16 +384,12 @@ private:
void SearchBuiltinProcCacheList(InsertCatListInfo *list_info);
GlobalCatCList *FindListInternal(uint32 hash_value, int nkeys, Datum *arguments, int *location);
void FreeDeadCts();
void HandleDeadGlobalCatCTup(GlobalCatCTup *ct);
void RemoveTailTupleElements(Index hash_index);
void FreeDeadCls();
void HandleDeadGlobalCatCList(GlobalCatCList *cl);
void RemoveTailListElements();
void FreeGlobalCatCList(GlobalCatCList *cl);
/* when initdb, this func call first */
void InitCacheInfo(Oid reloid, Oid indexoid, int nkeys, const int *key, int nbuckets);
void InitHashTable();
@ -403,10 +408,8 @@ private:
}
void AddHeadToCCList(GlobalCatCList *cl);
void RemoveElemFromCCList(GlobalCatCList *cl);
void AddHeadToBucket(Index hash_index, GlobalCatCTup *ct);
void RemoveElemFromBucket(GlobalCatCTup *ct);
/* Global cache identifier */
Oid m_dbOid;

View File

@ -42,7 +42,7 @@ public:
GlobalRelationEntry *SearchReadOnly(Oid relOid, uint32 hash_value)
{
GlobalBaseDefCache::FreeDeadEntrys<true>();
GlobalBaseDefCache::FreeDeadElements<true>();
GlobalRelationEntry *entry =
(GlobalRelationEntry *)GlobalBaseDefCache::SearchReadOnly(relOid, hash_value);
return entry;
@ -55,7 +55,7 @@ public:
return;
}
GlobalBaseDefCache::ResetCaches<true, force>();
GlobalBaseDefCache::FreeDeadEntrys<true>();
GlobalBaseDefCache::FreeDeadElements<true>();
}
inline uint64 GetSysCacheSpaceNum()