From 927146ebc4d4219e9259ee273f3665cf8bf9cb0a Mon Sep 17 00:00:00 2001 From: sovyyvos Date: Sat, 11 Jan 2025 17:35:06 +0800 Subject: [PATCH] =?UTF-8?q?HTAP=E5=86=85=E5=AD=98=E5=80=9F=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/bin/gs_guc/cluster_guc.conf | 2 + src/common/backend/utils/adt/pgstatfuncs.cpp | 4 +- .../backend/utils/misc/guc/guc_memory.cpp | 28 +++++ .../process/threadpool/knl_session.cpp | 1 + src/gausskernel/storage/cmgr/cache_mgr.cpp | 103 +++++++++++++++- src/gausskernel/storage/cstore/cu.cpp | 15 +++ src/gausskernel/storage/htap/Makefile | 2 +- .../storage/htap/borrow_mem_pool.cpp | 116 ++++++++++++++++++ src/gausskernel/storage/htap/imcs_ctlg.cpp | 8 ++ .../storage/htap/imcstore_vacuum.cpp | 3 + .../storage/htap/imcucache_mgr.cpp | 106 ++++++++++++++-- src/include/access/htap/borrow_mem_pool.h | 75 +++++++++++ src/include/access/htap/imcucache_mgr.h | 8 ++ .../knl/knl_guc/knl_instance_attr_memory.h | 2 + src/include/knl/knl_session.h | 5 + src/include/storage/cache_mgr.h | 17 +++ src/include/storage/cu.h | 4 + 17 files changed, 486 insertions(+), 13 deletions(-) create mode 100644 src/gausskernel/storage/htap/borrow_mem_pool.cpp create mode 100644 src/include/access/htap/borrow_mem_pool.h diff --git a/src/bin/gs_guc/cluster_guc.conf b/src/bin/gs_guc/cluster_guc.conf index 2029d70a27..330fa6ca22 100755 --- a/src/bin/gs_guc/cluster_guc.conf +++ b/src/bin/gs_guc/cluster_guc.conf @@ -25,6 +25,8 @@ max_imcs_cache|int|102400,2147483647|kB|NULL| enable_parallel_populate|bool|0,0|NULL|NULL| enable_imcsscan|bool|0,0|NULL|NULL| +enable_borrow_memory|bool|0,0|NULL|NULL| +htap_borrow_mem_percent|int|0,100|NULL|NULL| enable_custom_parser|bool|0,0|NULL|NULL| allocate_mem_cost|real|0,1.79769e+308|NULL|NULL| cpu_index_tuple_cost|real|0,1.79769e+308|NULL|NULL| diff --git a/src/common/backend/utils/adt/pgstatfuncs.cpp b/src/common/backend/utils/adt/pgstatfuncs.cpp index ea428b0ca0..0a3a035aea 100644 --- a/src/common/backend/utils/adt/pgstatfuncs.cpp +++ b/src/common/backend/utils/adt/pgstatfuncs.cpp @@ -10132,7 +10132,7 @@ Datum gs_total_nodegroup_memory_detail(PG_FUNCTION_ARGS) } #ifdef ENABLE_HTAP -#define MEMORY_TYPES_CNT 26 +#define MEMORY_TYPES_CNT 27 #else #define MEMORY_TYPES_CNT 24 #endif @@ -10163,6 +10163,7 @@ const char* MemoryTypeName[] = {"max_process_memory", #ifdef ENABLE_HTAP "imcstore_max_memory", "imcstore_used_memory", + "imcstore_borrowed_memory", #endif }; @@ -10297,6 +10298,7 @@ Datum pv_total_memory_detail(PG_FUNCTION_ARGS) #ifdef ENABLE_HTAP mem_size[24] = (int)(g_instance.attr.attr_memory.max_imcs_cache >> BITS_IN_KB); mem_size[25] = IMCU_CACHE->GetCurrentMemSize() >> BITS_IN_MB; + mem_size[26] = IMCU_CACHE->GetCurrBorrowMemSize() >> BITS_IN_MB; #endif } diff --git a/src/common/backend/utils/misc/guc/guc_memory.cpp b/src/common/backend/utils/misc/guc/guc_memory.cpp index bc3fa8bac4..3f3fa70b1d 100644 --- a/src/common/backend/utils/misc/guc/guc_memory.cpp +++ b/src/common/backend/utils/misc/guc/guc_memory.cpp @@ -303,6 +303,21 @@ static void InitMemoryConfigureNamesBool() NULL}, #endif +#ifdef ENABLE_HTAP + // variable to enable borrow memory for HTAP + {{"enable_borrow_memory", + PGC_POSTMASTER, + NODE_ALL, + RESOURCES_MEM, + gettext_noop("enable borrow memory for HTAP populate."), + NULL}, + &g_instance.attr.attr_memory.enable_borrow_memory, + false, + NULL, + NULL, + NULL}, +#endif + /* End-of-list marker */ {{NULL, (GucContext)0, @@ -429,6 +444,19 @@ static void InitMemoryConfigureNamesInt() NULL, NULL, NULL}, + {{"htap_borrow_mem_percent", + PGC_POSTMASTER, + NODE_ALL, + RESOURCES_MEM, + gettext_noop("Sets the maximum percentage of imcs memory occupied by borrow memory."), + NULL}, + &g_instance.attr.attr_memory.htap_borrow_mem_percent, + 50, + 0, + 100, + NULL, + NULL, + NULL}, #endif /* End-of-list marker */ {{NULL, diff --git a/src/gausskernel/process/threadpool/knl_session.cpp b/src/gausskernel/process/threadpool/knl_session.cpp index 9ba7af3a3e..c7c3bf7470 100755 --- a/src/gausskernel/process/threadpool/knl_session.cpp +++ b/src/gausskernel/process/threadpool/knl_session.cpp @@ -1498,6 +1498,7 @@ static void knl_u_datavec_init(knl_u_datavec_context* datavec_cxt) static void knl_u_imcstore_init(knl_u_imcstore_context* imcstore_context) { imcstore_context->pinnedRowGroups = NIL; + imcstore_context->pinnedBorrowMemPool = NULL; } #endif diff --git a/src/gausskernel/storage/cmgr/cache_mgr.cpp b/src/gausskernel/storage/cmgr/cache_mgr.cpp index 8349008d02..4ce187bf61 100644 --- a/src/gausskernel/storage/cmgr/cache_mgr.cpp +++ b/src/gausskernel/storage/cmgr/cache_mgr.cpp @@ -30,6 +30,7 @@ #include "storage/ipc.h" #include "miscadmin.h" #ifdef ENABLE_HTAP +#include "access/htap/borrow_mem_pool.h" #include "access/htap/imcucache_mgr.h" #include "access/htap/imcustorage.h" #include "storage/smgr/relfilenode.h" @@ -128,8 +129,19 @@ void CacheMgr::Init(int64 cache_size, uint32 each_block_size, MgrCacheType type, m_CaccheSlotMax = 1; m_cstoreCurrentSize = 0; +#ifdef ENABLE_HTAP + if (g_instance.attr.attr_memory.enable_borrow_memory) { + double p = (int)(g_instance.attr.attr_memory.htap_borrow_mem_percent) / 100.0; + m_borrowMaxSize = (int64)(cache_size * p); + m_cstoreMaxSize = cache_size - m_borrowMaxSize; + m_borrowCurrSize = 0; + SpinLockInit(&m_borrowSizeLock); + } else { + m_cstoreMaxSize = cache_size; + } +#else m_cstoreMaxSize = cache_size; - +#endif total_slots = isImcs ? (cache_size / each_block_size) * MaxHeapAttributeNumber : Min(cache_size / each_block_size, MAX_CACHE_SLOT_COUNT); @@ -223,6 +235,11 @@ void CacheMgr::Destroy(void) /* free spin lock resource */ SpinLockFree(&m_memsize_lock); SpinLockFree(&m_freeList_lock); +#ifdef ENABLE_HTAP + if (g_instance.attr.attr_memory.enable_borrow_memory) { + SpinLockFree(&m_borrowSizeLock); + } +#endif pfree_ext(m_CacheSlots); pfree_ext(m_CacheDesc); @@ -385,7 +402,16 @@ void CacheMgr::InvalidateCacheBlock(CacheTag *cacheTag) /* free this block cache and update its size before unpin this slot id */ FreeCacheBlockMem(slotId); +#ifdef ENABLE_HTAP + if (m_CacheDesc[slotId].m_isBorrow) { + ResetBorrowSlot(slotId); + ReleaseBorrowMem(blockSize); + } else { + ReleaseCacheMem(blockSize); + } +#else ReleaseCacheMem(blockSize); +#endif UnPinCacheBlock(slotId); /* put it into free list */ @@ -445,6 +471,15 @@ CacheSlotId_t CacheMgr::EvictCacheBlock(int size, int retryNum) if (m_csweep++ >= m_CaccheSlotMax) { m_csweep = 0; } +#ifdef ENABLE_HTAP + if (m_CacheDesc[slotId].m_isBorrow) { + m_csweep = slotId + 1; + if (m_csweep >= m_CaccheSlotMax) { + m_csweep = 0; + } + continue; + } +#endif ereport(DEBUG2, (errmodule(MOD_CACHE), errmsg("try evict cache block, solt(%d), flag(%hhu), refcount(%u), usage_count(%hu), ring_count(%hu)", @@ -559,6 +594,50 @@ void CacheMgr::EvictCacheCUIntoDisk(CacheSlotId_t slotId) pg_atomic_add_fetch_u64(&imcsDesc->cuSizeInDisk, (uint64)cuDesc->cu_size); pg_atomic_add_fetch_u64(&imcsDesc->cuNumsInDisk, 1); } + +bool CacheMgr::IsBorrowSlotId(CacheSlotId_t slotId) +{ + return m_CacheDesc[slotId].m_isBorrow; +} + +void CacheMgr::ResetBorrowSlot(CacheSlotId_t slotId) +{ + m_CacheDesc[slotId].m_isBorrow = false; +} + +bool CacheMgr::ReserveBorrowMem(int size) +{ + if (g_instance.attr.attr_memory.enable_borrow_memory && + u_sess->imcstore_ctx.pinnedBorrowMemPool != NULL && + u_sess->imcstore_ctx.pinnedBorrowMemPool->CanBorrow()) { + SpinLockAcquire(&m_borrowSizeLock); + if ((m_borrowCurrSize + size) <= m_borrowMaxSize) { + m_borrowCurrSize += size; + SpinLockRelease(&m_borrowSizeLock); + return true; + } + SpinLockRelease(&m_borrowSizeLock); + } + return false; +} + +void CacheMgr::ReleaseBorrowMem(int size) +{ + SpinLockAcquire(&m_borrowSizeLock); + Assert(m_borrowCurrSize >= size); + m_borrowCurrSize -= size; + SpinLockRelease(&m_borrowSizeLock); +} + +int64 CacheMgr::GetCurrBorrowMemSize() +{ + int64 borrowMemSize = 0; + SpinLockAcquire(&m_borrowSizeLock); + borrowMemSize = m_borrowCurrSize; + SpinLockRelease(&m_borrowSizeLock); + + return borrowMemSize; +} #endif /* @@ -577,7 +656,12 @@ RETRY_FIND_FREESPACE: retryNum++; /* If there is memory available, and slots on the free list, just return one from there */ +#ifdef ENABLE_HTAP + bool isBorrowMem = false; + if (ReserveCacheMem(size) || (isBorrowMem = ReserveBorrowMem(size))) { +#else if (ReserveCacheMem(size)) { +#endif if ((slotId = GetFreeListCache()) != CACHE_BLOCK_INVALID_IDX) { LockSweep(); if (slotId > m_CaccheSlotMax) { @@ -587,6 +671,9 @@ RETRY_FIND_FREESPACE: LockCacheDescHeader(slotId); m_CacheDesc[slotId].m_flag = CACHE_BLOCK_NEW; // is !Valid +#ifdef ENABLE_HTAP + m_CacheDesc[slotId].m_isBorrow = isBorrowMem; +#endif PinCacheBlock_Locked(slotId); // Released header lock @@ -594,6 +681,10 @@ RETRY_FIND_FREESPACE: * Returning from here means we have reserved the memory and * a new free slot */ return slotId; +#ifdef ENABLE_HTAP + } else if (isBorrowMem) { + ReleaseBorrowMem(size); +#endif } else { /* We release the memory now, and get it back again later once we evict a buffer */ ReleaseCacheMem(size); @@ -641,6 +732,16 @@ void CacheMgr::FreeCacheBlockMem(CacheSlotId_t slot) * be set to 0 after the slot is released. at least memory of * min(sizeof(CU), sizeof(OrcDataValue)) size must be cleanned up. */ CU *cu = (CU *)(&m_CacheSlots[slot * m_slot_length]); +#ifdef ENABLE_HTAP + if (cu->m_srcBuf != NULL && m_CacheDesc[slot].m_isBorrow) { + if (u_sess->imcstore_ctx.pinnedBorrowMemPool != NULL) { + u_sess->imcstore_ctx.pinnedBorrowMemPool->DeAllocate(cu->m_srcBuf); + } + cu->FreeOffset(); + cu->Reset(); + return; + } +#endif cu->FreeMem(); cu->Reset(); } else if (m_CacheDesc[slot].m_cache_tag.type == CACHE_OBS_DATA) { diff --git a/src/gausskernel/storage/cstore/cu.cpp b/src/gausskernel/storage/cstore/cu.cpp index 9e6cc48842..89a4f79a7e 100644 --- a/src/gausskernel/storage/cstore/cu.cpp +++ b/src/gausskernel/storage/cstore/cu.cpp @@ -1897,6 +1897,9 @@ void IMCSDesc::Init(Relation rel, int2vector* imcstoreAttsNum, int imcstoreNatts /* not primary node && not partitioned */ if (t_thrd.postmaster_cxt.HaShmData->current_mode != PRIMARY_MODE && !RelationIsPartitioned(rel)) { + if (g_instance.attr.attr_memory.enable_borrow_memory) { + borrowMemPool = New(CurrentMemoryContext) BorrowMemoryPool(relOid); + } uint32 totalBlks = RelationGetNumberOfBlocks(rel); uint32 rowGroupNums = ImcsCeil(totalBlks, MAX_IMCS_PAGES_ONE_CU); imcuDescContext = AllocSetContextCreate(CurrentMemoryContext, @@ -2032,6 +2035,7 @@ IMCSDesc::IMCSDesc() pg_atomic_init_u64(&cuNumsInMem, 0); pg_atomic_init_u64(&cuSizeInMem, 0); pg_atomic_init_u64(&cuNumsInDisk, 0); + borrowMemPool = NULL; } IMCSDesc::~IMCSDesc() @@ -2052,6 +2056,9 @@ IMCSDesc::~IMCSDesc() MemoryContextDelete(imcuDescContext); imcuDescContext = NULL; } + if (borrowMemPool != NULL) { + DELETE_EX(borrowMemPool); + } } RowGroup::RowGroup(uint32 rowGroupId, int imcsNatts) @@ -2233,4 +2240,12 @@ void CU::UnpackNumericCUFromDisk(int rowCount, uint32 magic, int cuSize) m_numericIntLike = true; } +void CU::FreeOffset() +{ + if (m_offset) { + CStoreMemAlloc::Pfree(m_offset, !m_inCUCache); + } + m_offset = NULL; + m_offsetSize = 0; +} #endif diff --git a/src/gausskernel/storage/htap/Makefile b/src/gausskernel/storage/htap/Makefile index 98ce2722e1..6c4d6b6ad3 100644 --- a/src/gausskernel/storage/htap/Makefile +++ b/src/gausskernel/storage/htap/Makefile @@ -35,6 +35,6 @@ endif override CPPFLAGS += -I${top_builddir}/contrib/ndpplugin -OBJS = imcucache_mgr.o imcstore_insert.o imcs_ctlg.o imcustorage.o imcstore_am.o imcstore_vacuum.o imcstore_delta.o +OBJS = imcucache_mgr.o imcstore_insert.o imcs_ctlg.o imcustorage.o imcstore_am.o imcstore_vacuum.o imcstore_delta.o borrow_mem_pool.o include $(top_srcdir)/src/gausskernel/common.mk diff --git a/src/gausskernel/storage/htap/borrow_mem_pool.cpp b/src/gausskernel/storage/htap/borrow_mem_pool.cpp new file mode 100644 index 0000000000..b3048c8dbe --- /dev/null +++ b/src/gausskernel/storage/htap/borrow_mem_pool.cpp @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2024 Huawei Technologies Co.,Ltd. + * + * openGauss is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * + * http://license.coscl.org.cn/MulanPSL2 + * + * 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 PSL v2 for more details. + * --------------------------------------------------------------------------------------- + * borrow_mem_pool.cpp + * routines to support IMColStore + * + * IDENTIFICATION + * src/gausskernel/storage/htap/borrow_mem_pool.cpp + * --------------------------------------------------------------------------------------- + */ + +#include "storage/rack_mem.h" +#include "access/htap/borrow_mem_pool.h" + +BorrowMemoryPool::BorrowMemoryPool(Oid relOid) +{ + m_headBlock = NULL; + m_currBlock = NULL; + m_relOid = relOid; + m_mutex = PTHREAD_RWLOCK_INITIALIZER; +} + +BorrowMemoryPool::~BorrowMemoryPool() +{} + +void* BorrowMemoryPool::Allocate(uint32 size) +{ + void *result = NULL; + uint32 chunkSize = BMP_CHUNK_HDSZ + size; + + pthread_rwlock_wrlock(&m_mutex); + if (m_currBlock == NULL || m_currPos + chunkSize > BLOCK_SIZE) { + BMPBlock *prevBlock = m_currBlock; + void *rackPtr = RackMemMalloc(BLOCK_SIZE, L0, 0); + if (rackPtr != NULL) { + m_currBlock = (BMPBlock*)palloc0(sizeof(BMPBlock)); + m_currBlock->ptr = rackPtr; + m_currPos = 0; + if (prevBlock != NULL) { + prevBlock->next = m_currBlock; + } else { + m_headBlock = m_currBlock; + } + ereport(LOG, (errmsg("HTAP BorrowMemPool Allocate: borrow a block, num(%u), size(%u), oid(%u)", + ++m_block_num, BLOCK_SIZE, m_relOid))); + } else { + m_lastBorrowFailed = true; + ereport(WARNING, (errmsg("HTAP BorrowMemPool Allocate: borrow memory failed, size(%u), oid(%u)", + BLOCK_SIZE, m_relOid))); + pthread_rwlock_unlock(&m_mutex); + return result; + } + } + + result = (char*)m_currBlock->ptr + m_currPos + BMP_CHUNK_HDSZ; + ((BMPChunkHeader*)((char*)m_currBlock->ptr + m_currPos))->bmpBlock = m_currBlock; + m_currBlock->refCnt++; + m_currPos += chunkSize; + + pthread_rwlock_unlock(&m_mutex); + return result; +} + +void BorrowMemoryPool::DeAllocate(void *ptr) +{ + pthread_rwlock_wrlock(&m_mutex); + BMPBlock *blk = ((BMPChunkHeader*)((char*)ptr - BMP_CHUNK_HDSZ))->bmpBlock; + Assert(blk != NULL); + if (--blk->refCnt <= 0 && blk->ptr != NULL) { + RackMemFree(blk->ptr); + blk->ptr = NULL; + ereport(LOG, (errmsg("HTAP BorrowMemPool DeAllocate: return a block, size(%u), oid(%u), %u block left", + BLOCK_SIZE, m_relOid, --m_block_num))); + } + pthread_rwlock_unlock(&m_mutex); +} + +bool BorrowMemoryPool::CanBorrow() +{ + bool canBorrow = true; + pthread_rwlock_rdlock(&m_mutex); + canBorrow = !m_lastBorrowFailed; + pthread_rwlock_unlock(&m_mutex); + return canBorrow; +} + +void BorrowMemoryPool::Destroy() +{ + pthread_rwlock_wrlock(&m_mutex); + BMPBlock *blk = m_headBlock; + + while (blk != NULL) { + if (blk->ptr != NULL) { + RackMemFree(blk->ptr); + blk->ptr = NULL; + ereport(LOG, (errmsg("HTAP BorrowMemPool Destroy: return a block, size(%u), oid(%u), %u block left", + BLOCK_SIZE, m_relOid, --m_block_num))); + } + + BMPBlock *nextBlk = blk->next; + pfree_ext(blk); + blk = nextBlk; + } + pthread_rwlock_unlock(&m_mutex); +} diff --git a/src/gausskernel/storage/htap/imcs_ctlg.cpp b/src/gausskernel/storage/htap/imcs_ctlg.cpp index f73cf4bbc8..c294e53d26 100644 --- a/src/gausskernel/storage/htap/imcs_ctlg.cpp +++ b/src/gausskernel/storage/htap/imcs_ctlg.cpp @@ -412,6 +412,10 @@ void PopulateImcs(Relation rel, int2vector* imcsAttsNum, int imcsNatts) PG_TRY(); { + IMCSDesc *imcsDesc = IMCU_CACHE->GetImcsDesc(RelationGetRelid(rel)); + if (g_instance.attr.attr_memory.enable_borrow_memory) { + u_sess->imcstore_ctx.pinnedBorrowMemPool = imcsDesc->borrowMemPool; + } while ((tuple = tableam_scan_getnexttuple(scan, ForwardScanDirection)) != NULL) { tableam_tops_deform_tuple(tuple, relTupleDesc, val, null); null[relTupleDesc->natts] = false; @@ -530,6 +534,10 @@ void ParallelPopulateImcsMain(const BgWorkerContext *bwc) IMCStoreInsert imcstoreInsert(rel, shared->imcsTupleDesc, shared->imcsAttsNum); PG_TRY(); { + IMCSDesc *imcsDesc = IMCU_CACHE->GetImcsDesc(RelationGetRelid(rel)); + if (g_instance.attr.attr_memory.enable_borrow_memory) { + u_sess->imcstore_ctx.pinnedBorrowMemPool = imcsDesc->borrowMemPool; + } while ((tuple = tableam_scan_getnexttuple(scan, ForwardScanDirection)) != NULL) { tableam_tops_deform_tuple(tuple, relTupleDesc, val, null); null[relTupleDesc->natts] = false; diff --git a/src/gausskernel/storage/htap/imcstore_vacuum.cpp b/src/gausskernel/storage/htap/imcstore_vacuum.cpp index 5e2339c646..144a16ffe2 100644 --- a/src/gausskernel/storage/htap/imcstore_vacuum.cpp +++ b/src/gausskernel/storage/htap/imcstore_vacuum.cpp @@ -505,6 +505,9 @@ void IMCStoreVacuumWorkerMain(void) MemoryContext oldcontext = MemoryContextSwitchTo(imcsDesc->imcuDescContext); PG_TRY(); { + if (g_instance.attr.attr_memory.enable_borrow_memory && imcsDesc->borrowMemPool != NULL) { + u_sess->imcstore_ctx.pinnedBorrowMemPool = imcsDesc->borrowMemPool; + } IMCStoreVacuum(rel, imcsDesc, target.rowGroupId); } PG_CATCH(); diff --git a/src/gausskernel/storage/htap/imcucache_mgr.cpp b/src/gausskernel/storage/htap/imcucache_mgr.cpp index 324e989a3b..f5ab9756d5 100644 --- a/src/gausskernel/storage/htap/imcucache_mgr.cpp +++ b/src/gausskernel/storage/htap/imcucache_mgr.cpp @@ -31,6 +31,7 @@ #include "utils/builtins.h" #include "storage/cu.h" #include "replication/syncrep.h" +#include "access/htap/borrow_mem_pool.h" #include "access/htap/imcs_ctlg.h" #include "access/htap/imcucache_mgr.h" @@ -227,15 +228,11 @@ void IMCUDataCacheMgr::NewSingletonInstance(void) MemoryContextSwitchTo(oldcontext); } -void IMCUDataCacheMgr::CacheCU(CU* srcCU, CU* slotCU) +void IMCUDataCacheMgr::BaseCacheCU(CU* srcCU, CU* slotCU) { - slotCU->m_srcBuf = srcCU->m_srcBuf; - slotCU->m_nulls = srcCU->m_nulls; - slotCU->m_srcData = srcCU->m_srcData; - srcCU->m_compressedBuf = srcCU->m_compressedBuf; - slotCU->m_offset = srcCU->m_offset; - slotCU->m_tmpinfo = srcCU->m_tmpinfo; - slotCU->m_compressedLoadBuf = srcCU->m_compressedLoadBuf; + slotCU->m_compressedBuf = NULL; + slotCU->m_tmpinfo = NULL; + slotCU->m_compressedLoadBuf = NULL; slotCU->m_head_padding_size = srcCU->m_head_padding_size; slotCU->m_offsetSize = srcCU->m_offsetSize; slotCU->m_srcBufSize = srcCU->m_srcBufSize; @@ -256,6 +253,41 @@ void IMCUDataCacheMgr::CacheCU(CU* srcCU, CU* slotCU) slotCU->m_inCUCache = true; slotCU->m_numericIntLike = srcCU->m_numericIntLike; } + +void IMCUDataCacheMgr::CacheCU(CU* srcCU, CU* slotCU) +{ + slotCU->m_srcBuf = srcCU->m_srcBuf; + slotCU->m_nulls = srcCU->m_nulls; + slotCU->m_srcData = srcCU->m_srcData; + slotCU->m_offset = srcCU->m_offset; + BaseCacheCU(srcCU, slotCU); +} + +bool IMCUDataCacheMgr::CacheBorrowMemCU(CU* srcCU, CU* slotCU, CUDesc* cuDescPtr) +{ + errno_t rc = EOK; + BaseCacheCU(srcCU, slotCU); + + if (srcCU->m_srcBuf != NULL) { + char *buf = (char *)(u_sess->imcstore_ctx.pinnedBorrowMemPool->Allocate(srcCU->m_srcBufSize)); + if (buf == nullptr) { + return false; + } + rc = memcpy_s(buf, srcCU->m_srcBufSize, srcCU->m_srcBuf, srcCU->m_srcBufSize); + securec_check(rc, "\0", "\0"); + slotCU->m_srcBuf = buf; + slotCU->m_srcData = buf + srcCU->m_bpNullRawSize; + if (srcCU->m_bpNullRawSize != 0) { + slotCU->m_nulls = (unsigned char*)slotCU->m_srcBuf; + } + if (!slotCU->HasNullValue()) { + slotCU->FormValuesOffset(cuDescPtr->row_count); + } else { + slotCU->FormValuesOffset(cuDescPtr->row_count); + } + } + return true; +} void IMCUDataCacheMgr::SaveCU(IMCSDesc* imcsDesc, RelFileNodeOld* rnode, int colId, CU* cuPtr, CUDesc* cuDescPtr) { @@ -266,11 +298,25 @@ void IMCUDataCacheMgr::SaveCU(IMCSDesc* imcsDesc, RelFileNodeOld* rnode, int col cuPtr->FreeSrcBuf(); return; } - bool hasFound = false; DataSlotTag slotTag = InitCUSlotTag(rnode, colId, cuDescPtr->cu_id, cuDescPtr->cu_pointer); + +RETRY_RESERVE_DATABLOCK: + bool hasFound = false; CacheSlotId_t slotId = ReserveDataBlock(&slotTag, cuDescPtr->cu_size, hasFound); CU* slotCU = GetCUBuf(slotId); - CacheCU(cuPtr, slotCU); + if (IsBorrowSlotId(slotId)) { + if (CacheBorrowMemCU(cuPtr, slotCU, cuDescPtr)) { + cuPtr->Destroy(); + } else { + ReleaseBorrowMemSize(cuDescPtr->cu_size); + ResetBorrowSlot(slotId); + UnPinDataBlock(slotId); + goto RETRY_RESERVE_DATABLOCK; + } + } else { + CacheCU(cuPtr, slotCU); + } + slotCU->imcsDesc = imcsDesc; UnPinDataBlock(slotId); DataBlockCompleteIO(slotId); @@ -395,6 +441,9 @@ void IMCUDataCacheMgr::DeleteImcsDesc(Oid relOid, RelFileNode* relNode) /* drop rowgroup\cu\cudesc, no need to drop RowGroups for primary node */ LWLockAcquire(imcsDesc->imcsDescLock, LW_EXCLUSIVE); Assert(relNode); + if (g_instance.attr.attr_memory.enable_borrow_memory && imcsDesc->borrowMemPool != NULL) { + imcsDesc->borrowMemPool->Destroy(); + } imcsDesc->DropRowGroups(relNode); LWLockRelease(imcsDesc->imcsDescLock); MemoryContextDelete(imcsDesc->imcuDescContext); @@ -489,6 +538,10 @@ bool IMCUDataCacheMgr::HasInitialImcsTable() void IMCUDataCacheMgr::ResetInstance() { + if (g_instance.attr.attr_memory.enable_borrow_memory) { + m_data_cache->FreeAllBorrowMemPool(); + } + if (m_data_cache != NULL) { HeapMemResetHash(m_data_cache->m_imcs_hash, "IMCSDesc Lookup Table"); m_data_cache->m_cache_mgr->FreeImcstoreCache(); @@ -496,4 +549,37 @@ void IMCUDataCacheMgr::ResetInstance() CreateIMCUDirAndClearCUFiles(); ereport(WARNING, (errmsg("IMCStore data cache manager reset."))); +} + +bool IMCUDataCacheMgr::IsBorrowSlotId(CacheSlotId_t slotId) +{ + return m_cache_mgr->IsBorrowSlotId(slotId); +} + +void IMCUDataCacheMgr::ResetBorrowSlot(CacheSlotId_t slotId) +{ + m_cache_mgr->ResetBorrowSlot(slotId); +} + +void IMCUDataCacheMgr::ReleaseBorrowMemSize(int size) +{ + m_cache_mgr->ReleaseBorrowMem(size); +} + +int64 IMCUDataCacheMgr::GetCurrBorrowMemSize() +{ + return m_cache_mgr->GetCurrBorrowMemSize(); +} + +void IMCUDataCacheMgr::FreeAllBorrowMemPool() +{ + HASH_SEQ_STATUS hashSeq; + IMCSDesc *imcsDesc = NULL; + + hash_seq_init(&hashSeq, m_imcs_hash); + while ((imcsDesc = (IMCSDesc*)hash_seq_search(&hashSeq)) != NULL) { + if (imcsDesc->borrowMemPool != NULL) { + imcsDesc->borrowMemPool->Destroy(); + } + } } \ No newline at end of file diff --git a/src/include/access/htap/borrow_mem_pool.h b/src/include/access/htap/borrow_mem_pool.h new file mode 100644 index 0000000000..2630d62951 --- /dev/null +++ b/src/include/access/htap/borrow_mem_pool.h @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2024 Huawei Technologies Co.,Ltd. + * + * openGauss is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * + * http://license.coscl.org.cn/MulanPSL2 + * + * 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 PSL v2 for more details. + * --------------------------------------------------------------------------------------- + * + * borrow_mem_pool.h + * routines to support IMColStore + * + * + * IDENTIFICATION + * src/include/access/htap/borrow_mem_pool.h + * + * --------------------------------------------------------------------------------------- + */ + +#ifndef BORROW_MEM_POOL_H +#define BORROW_MEM_POOL_H + +#include "postgres.h" + +#define BMP_CHUNK_HDSZ (sizeof(BMPChunkHeader)) + +typedef struct BMPBlock { + void *ptr; + int refCnt; + BMPBlock *next; +} BMPBlock; + +typedef struct { + BMPBlock *bmpBlock; +} BMPChunkHeader; + +class BorrowMemoryPool : public BaseObject { +public: + BorrowMemoryPool(Oid relOid); + + ~BorrowMemoryPool(); + + void *Allocate(uint32 size); + + void DeAllocate(void *ptr); + + bool CanBorrow(); + + void Destroy(); + +private: + static const uint32 BLOCK_SIZE = 1 << 27; + + BMPBlock *m_headBlock; + + BMPBlock *m_currBlock; + + uint32 m_currPos{0}; + + uint32 m_block_num{0}; + + Oid m_relOid; + + bool m_lastBorrowFailed{false}; + + pthread_rwlock_t m_mutex; +}; + +#endif /* BORROW_MEM_POOL_H */ \ No newline at end of file diff --git a/src/include/access/htap/imcucache_mgr.h b/src/include/access/htap/imcucache_mgr.h index 6bfb4f8baa..bb1ccd6bb8 100644 --- a/src/include/access/htap/imcucache_mgr.h +++ b/src/include/access/htap/imcucache_mgr.h @@ -81,7 +81,9 @@ public: // static static IMCUDataCacheMgr* GetInstance(void); static void NewSingletonInstance(void); static void ResetInstance(); + static void BaseCacheCU(CU* srcCU, CU* slotCU); static void CacheCU(CU* srcCU, CU* slotCU); + static bool CacheBorrowMemCU(CU* srcCU, CU* slotCU, CUDesc* cuDescPtr); public: void SaveCU(IMCSDesc* imcsDesc, RelFileNodeOld* rnode, int colId, CU* cuPtr, CUDesc* cuDescPtr); @@ -99,6 +101,12 @@ public: void UpdatePrimaryImcsStatus(Oid relOid, int imcsStatus); bool HasInitialImcsTable(); + bool IsBorrowSlotId(CacheSlotId_t slotId); + void ResetBorrowSlot(CacheSlotId_t slotId); + void ReleaseBorrowMemSize(int size); + int64 GetCurrBorrowMemSize(); + void FreeAllBorrowMemPool(); + HTAB* m_imcs_hash; LWLock *m_imcs_lock; MemoryContext m_imcs_context; diff --git a/src/include/knl/knl_guc/knl_instance_attr_memory.h b/src/include/knl/knl_guc/knl_instance_attr_memory.h index 3a2dfa1a04..d3af86da69 100644 --- a/src/include/knl/knl_guc/knl_instance_attr_memory.h +++ b/src/include/knl/knl_guc/knl_instance_attr_memory.h @@ -47,6 +47,8 @@ typedef struct knl_instance_attr_memory { int max_process_memory; #ifdef ENABLE_HTAP int max_imcs_cache; + bool enable_borrow_memory; + int htap_borrow_mem_percent; #endif bool enable_memory_context_check_debug; int global_syscache_threshold; diff --git a/src/include/knl/knl_session.h b/src/include/knl/knl_session.h index 32f4964de7..e4ede7b689 100644 --- a/src/include/knl/knl_session.h +++ b/src/include/knl/knl_session.h @@ -45,6 +45,10 @@ #include +#include "postgres.h" +#ifdef ENABLE_HTAP +#include "access/htap/borrow_mem_pool.h" +#endif #include "access/ustore/undo/knl_uundotype.h" #include "access/skey.h" #include "c.h" @@ -3038,6 +3042,7 @@ typedef struct knl_u_datavec_context { #ifdef ENABLE_HTAP typedef struct knl_u_imcstore_context { List* pinnedRowGroups; + BorrowMemoryPool* pinnedBorrowMemPool; } knl_u_imcstore_context; #endif diff --git a/src/include/storage/cache_mgr.h b/src/include/storage/cache_mgr.h index 42c70acf25..64e211d47e 100644 --- a/src/include/storage/cache_mgr.h +++ b/src/include/storage/cache_mgr.h @@ -153,6 +153,10 @@ typedef struct CacheDesc { slock_t m_slot_hdr_lock; CacheFlags m_flag; + +#ifdef ENABLE_HTAP + bool m_isBorrow{false}; +#endif } CacheDesc; int CacheMgrNumLocks(int64 cache_size, uint32 each_block_size); @@ -227,6 +231,13 @@ public: } void CopyCacheBlockTag(CacheSlotId_t slotId, CacheTag* outTag); +#ifdef ENABLE_HTAP + bool IsBorrowSlotId(CacheSlotId_t slotId); + void ResetBorrowSlot(CacheSlotId_t slotId); + void ReleaseBorrowMem(int size); + int64 GetCurrBorrowMemSize(); +#endif + char* m_CacheSlots; /* only true when ImcuCacheMgr init */ bool isImcs = false; @@ -242,6 +253,7 @@ private: CacheSlotId_t GetFreeCacheBlock(int size); #ifdef ENABLE_HTAP void EvictCacheCUIntoDisk(CacheSlotId_t slotId); + bool ReserveBorrowMem(int size); #endif /* memory operate */ @@ -279,6 +291,11 @@ private: int64 m_cstoreMaxSize; int64 m_cstoreCurrentSize; +#ifdef ENABLE_HTAP + int64 m_borrowMaxSize; + int64 m_borrowCurrSize; + slock_t m_borrowSizeLock; +#endif int m_freeListHead; int m_freeListTail; diff --git a/src/include/storage/cu.h b/src/include/storage/cu.h index 96025ca722..137f242075 100644 --- a/src/include/storage/cu.h +++ b/src/include/storage/cu.h @@ -32,6 +32,7 @@ #include "utils/datum.h" #include "storage/lock/lwlock.h" #ifdef ENABLE_HTAP +#include "access/htap/borrow_mem_pool.h" #include "access/htap/imcstore_delta.h" #define ROW_GROUP_INIT_NUMS (1024) @@ -237,6 +238,8 @@ struct IMCSDesc { uint32 maxRowGroupCapacity; bool isPartition; Oid parentOid; + BorrowMemoryPool* borrowMemPool; + IMCSDesc(); ~IMCSDesc(); @@ -410,6 +413,7 @@ public: #ifdef ENABLE_HTAP void PackNumericCUForFlushToDisk(); void UnpackNumericCUFromDisk(int rowCount, uint32 magic, int cuSize); + void FreeOffset(); #endif // Compress data -- Gitee