【 OpenGauss源碼學習 —— 列存儲(CStoreMemAlloc)】

列存儲(CStoreMemAlloc)

  • 概述
  • CStoreMemAlloc 類
    • CStoreMemAlloc::Palloc 函數
    • CStoreMemAlloc::AllocPointerNode 函數
    • CStoreMemAlloc::FreePointerNode 函數
    • CStoreMemAlloc::Repalloc 函數
    • CStoreMemAlloc::Pfree
    • CStoreMemAlloc::Register 函數
    • CStoreMemAlloc::Unregister 函數
    • CStoreMemAlloc::Reset 函數
    • CStoreMemAlloc::Init 函數
  • 總結

聲明:本文的部分內容參考了他人的文章。在編寫過程中,我們尊重他人的知識產權和學術成果,力求遵循合理使用原則,并在適用的情況下注明引用來源。
本文主要參考了 OpenGauss1.1.0 的開源代碼和《OpenGauss數據庫源碼解析》一書以及OpenGauss社區學習文檔和一些參考資料

概述

??學習完了 CUCUStorage 類,我們最后來學習一下 CStoreMemAlloc 類。CStoreMemAlloc 類提供了內存管理的功能,而 CUCUStorage 類負責處理列存儲中的具體數據單元和物理存儲。在實際的列存儲系統中,這些類可能會協同工作以有效地管理內存和存儲數據。

CStoreMemAlloc 類

??CStoreMemAlloc 類在列存儲中扮演了一個內存管理的角色,幫助管理和釋放與列存儲操作相關的動態內存。這對于確保系統在處理大量數據時能夠高效使用內存防止內存泄漏以及正確處理事務回滾等方面非常重要。類的定義如下:(函數路徑:src/include/storage/cstore/cstore_mem_alloc.h

// 類定義:CStoreMemAlloc
// 用于管理從malloc中分配的內存指針
// 在事務出現錯誤時,可以在abortTransaction中重置malloc的內存
// 在事務提交時,可以重置malloc的內存
class CStoreMemAlloc {
public:static void* Palloc(Size size, bool toRegister = true);static void Pfree(void* pointer, bool registered = true);static void* Repalloc(void* pointer, Size size, Size old_size, bool registered = true);static void Register(void* pointer);static void Unregister(const void* pointer);static void Reset();static void Init();private:static void* AllocPointerNode();static void FreePointerNode(PointerNode* pointer);// 保存所有分配的內存指針數組static THR_LOCAL PointerList m_tab[MaxPointersArryLen];// 記錄分配的內存指針數量static THR_LOCAL uint64 m_count;// 保存已經分配的PointerNode的緩存static THR_LOCAL uint32 m_ptrNodeCacheCount;static THR_LOCAL PointerNode* m_ptrNodeCache[MaxPtrNodeCacheLen];
};

??下面我們分別來看看CStoreMemAlloc 類成員函數的作用是什么?

CStoreMemAlloc::Palloc 函數

??CStoreMemAlloc 類中的 Palloc 方法。該方法用于從系統中分配內存,并根據需要將內存指針注冊到管理中。具體作用和功能如下:

描述:該方法用于從系統中分配內存,支持動態內存的分配操作。
參數:size:需要分配的內存大小。toRegister:表示是否需要將該內存指針在事務管理范圍內進行注冊。如果為 true,則注冊;如果為 false,則不注冊。
功能:確保要分配的內存大小大于0。調用內部的 InnerMalloc 方法進行實際的內存分配。如果內存分配失敗,拋出內存不足的錯誤。如果需要在事務管理范圍內注冊該內存指針,則進行注冊。返回分配的內存指針。

??函數源碼如下所示:(路徑:src/gausskernel/storage/cstore/cstore_mem_alloc.cpp

/** @Description: 從系統中分配內存* @Param[IN] size: 需要的內存大小* @Param[IN] toRegister: 如果這塊內存在線程管理的范圍內,則設置為 true;*                        如果這塊內存在進程管理的范圍內,則設置為 false。* @See also: 無*/
void* CStoreMemAlloc::Palloc(Size size, bool toRegister)
{// 確保分配的內存大小大于0Assert(size > 0);// 調用內部的分配方法分配內存void* ptr = InnerMalloc(size);// 如果分配失敗,拋出內存不足的錯誤if (ptr == NULL) {ereport(ERROR, (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("malloc fails, out of memory: size %lu", size)));}// 如果需要注冊(在事務管理范圍內),則進行注冊if (toRegister) {/* 步驟2:注冊指針 */Register(ptr);}// 返回分配的內存指針return ptr;
}

CStoreMemAlloc::AllocPointerNode 函數

??這段代碼是 CStoreMemAlloc 類中的 AllocPointerNode 方法。該方法用于分配一個指針節點,具體作用和功能如下:

描述:該方法用于分配一個指針節點,該節點可能被用于管理 CStoreMemAlloc 類中的內存指針。
返回:返回分配得到的指針節點。
功能:如果指針節點緩存中有可用節點,從緩存中取出一個節點。如果指針節點緩存中沒有可用節點,直接使用 malloc 分配一個新的節點。如果分配失敗,拋出內存不足的錯誤。返回分配得到的指針節點。

??函數源碼如下所示:(路徑:src/gausskernel/storage/cstore/cstore_mem_alloc.cpp

/** @Description: 分配一個指針節點* @Return: 分配得到的指針節點* @See also: 無*/
void* CStoreMemAlloc::AllocPointerNode()
{PointerNode* ptr = NULL;// 如果緩存中有可用節點,從緩存中取出if (m_ptrNodeCacheCount > 0) {ptr = m_ptrNodeCache[--m_ptrNodeCacheCount];} else {// 如果緩存中沒有可用節點,直接使用malloc分配新節點ptr = (PointerNode*)malloc(sizeof(PointerNode));// 分配失敗則拋出內存不足的錯誤if (ptr == NULL) {ereport(ERROR, (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("malloc fails, out of memory")));}}// 返回分配得到的指針節點return ptr;
}

CStoreMemAlloc::FreePointerNode 函數

??CStoreMemAlloc 類中的 FreePointerNode 方法用于釋放一個指針節點,具體作用和功能如下:

描述:該方法用于釋放一個指針節點,該節點可能被用于管理 CStoreMemAlloc 類中的內存指針。
參數:ptr 為要釋放的指針節點。
功能:如果指針節點緩存未滿,將節點放入緩存中以便后續復用。如果指針節點緩存已滿,直接使用 free 釋放節點。

??函數源碼如下所示:(路徑:src/gausskernel/storage/cstore/cstore_mem_alloc.cpp

/** @Description: 釋放一個指針節點* @Param[IN] ptr: 要釋放的指針節點* @See also: 無*/
void CStoreMemAlloc::FreePointerNode(PointerNode* ptr)
{// 如果指針節點緩存未滿,將節點放入緩存中if (m_ptrNodeCacheCount < MaxPtrNodeCacheLen) {m_ptrNodeCache[m_ptrNodeCacheCount++] = ptr;} else {// 如果緩存已滿,直接使用free釋放節點free(ptr);}
}

CStoreMemAlloc::Repalloc 函數

??CStoreMemAlloc 類中的 Repalloc 方法用于重新分配內存(相當于 remalloc 操作),并根據需要注冊新分配的內存取消注冊舊內存。具體作用和功能如下:

描述:該方法用于重新分配內存,類似于系統中的 remalloc 操作,同時支持內存的注冊和取消注冊。
參數:old_size:舊內存的大小。size:新內存的大小。pointer:要釋放的舊內存指針。registered:如果在調用 Palloc() 時傳遞 true,則為 true;如果傳遞 false,則為 false。
功能:斷言,確保內存指針和大小的合法性。調用內部的 InnerMalloc 方法重新分配內存。如果分配失敗,拋出內存不足的錯誤。將舊內存中的數據拷貝到新分配的內存中。如果在 Palloc() 中傳遞 true,則注冊新分配的內存,取消注冊舊內存。斷言,確保計數器大于0。釋放舊內存。返回新分配的內存指針。

??函數源碼如下所示:(路徑:src/gausskernel/storage/cstore/cstore_mem_alloc.cpp

/** @Description: 重新分配內存(remalloc)從系統中* @Param[IN] old_size: 舊內存大小* @Param[IN] size:     新內存大小* @Param[IN] pointer:  要釋放的內存指針* @Param[IN] registered: 如果在 Palloc() 中傳遞 true,則為 true;*                        如果在 Palloc() 中傳遞 false,則為 false。* @See also: 無*/
void* CStoreMemAlloc::Repalloc(void* pointer, Size size, Size old_size, bool registered)
{// 斷言,確保內存指針和大小的合法性Assert(pointer != NULL);Assert(size > 0);// 調用內部的 InnerMalloc 方法重新分配內存void* ptr = InnerMalloc(size);// 如果分配失敗,拋出內存不足的錯誤if (ptr == NULL) {ereport(ERROR, (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of memory")));}// 將舊內存中的數據拷貝到新分配的內存中errno_t rc = memcpy_s(ptr, size, pointer, old_size);securec_check_c(rc, "\0", "\0");// 如果在 Palloc() 中傳遞 true,則注冊新分配的內存,取消注冊舊內存if (registered) {Register(ptr);Unregister(pointer);// 斷言,確保計數器大于0Assert(m_count > 0);}// 釋放舊內存free(pointer);// 返回新分配的內存指針return ptr;
}

CStoreMemAlloc::Pfree

??CStoreMemAlloc 類中的 Pfree 方法用于將內存釋放到系統,同時根據需要取消注冊內存指針。具體作用和功能如下:

描述:該方法用于釋放內存到系統,可以選擇是否取消注冊內存指針。
參數:pointer:要釋放的內存指針。registered:如果在調用 Palloc() 時傳遞 true,則為 true;如果傳遞 false,則為 false。
功能:斷言,確保內存指針的合法性。如果在 Palloc() 中傳遞 true,則取消注冊內存指針。釋放內存到系統。

??函數源碼如下所示:(路徑:src/gausskernel/storage/cstore/cstore_mem_alloc.cpp

/** @Description: 釋放內存到系統* @Param[IN] pointer: 要釋放的內存指針* @Param[IN] registered: 如果在 Palloc() 中傳遞 true,則為 true;*                        如果在 Palloc() 中傳遞 false,則為 false。* @See also: 無*/
void CStoreMemAlloc::Pfree(void* pointer, bool registered)
{// 斷言,確保內存指針的合法性Assert(pointer);// 如果在 Palloc() 中傳遞 true,則取消注冊內存指針if (registered) {Unregister(pointer);}// 釋放內存到系統free(pointer);
}

CStoreMemAlloc::Register 函數

??CStoreMemAlloc 類中的 Register 方法用于注冊內存指針,將其添加到內存指針管理表中。具體作用和功能如下:

描述:該方法用于將內存指針注冊,將其添加到內存指針管理表中,以便在事務結束時進行統一的處理。
參數:pointer:要注冊的內存指針。
功能:斷言,確保 MaxPointersArryLen 是2的冪。計算內存指針在管理表中的索引位置。如果鏈表為空,頭尾節點都指向新分配的節點。如果鏈表不為空,在鏈表尾部添加新節點。增加內存指針計數器。

??函數源碼如下所示:(路徑:src/gausskernel/storage/cstore/cstore_mem_alloc.cpp

/** @Description: 注冊內存指針* @Param[IN] pointer: 要注冊的內存指針* @See also: AllocPointerNode()*/
void CStoreMemAlloc::Register(void* pointer)
{// 斷言,確保 MaxPointersArryLen 是2的冪Assert((MaxPointersArryLen & (MaxPointersArryLen - 1)) == 0);// 計算索引位置int idx = PointerGetDatum(pointer) & (MaxPointersArryLen - 1);PointerNode* nodePtr = m_tab[idx].tail;// 如果尾節點為空,說明鏈表為空if (nodePtr == NULL) {// 頭尾節點都指向新分配的節點Assert(m_tab[idx].header == NULL);m_tab[idx].header = m_tab[idx].tail = (PointerNode*)AllocPointerNode();m_tab[idx].header->ptr = pointer;m_tab[idx].header->next = NULL;} else {// 否則在鏈表尾部添加新節點nodePtr->next = (PointerNode*)AllocPointerNode();nodePtr->next->ptr = pointer;nodePtr->next->next = NULL;m_tab[idx].tail = nodePtr->next;}// 增加計數器++m_count;
}

CStoreMemAlloc::Unregister 函數

??CStoreMemAlloc 類中的 Unregister 方法用于取消注冊內存指針,將其從內存指針管理表中移除。具體作用和功能如下:

描述:該方法用于取消注冊內存指針,將其從內存指針管理表中移除,以便在事務結束時進行統一的處理。
參數:pointer:要取消注冊的內存指針。
功能:斷言,確保內存指針和計數器的合法性。確定包含該指針的節點列表。在節點列表中查找指針,如果找到則移除該節點。如果取消注冊的是尾節點,需要修改尾指針。重置并釋放節點。減少計數器。斷言,確保找到了要取消注冊的指針節點。

??函數源碼如下所示:(路徑:src/gausskernel/storage/cstore/cstore_mem_alloc.cpp

/** @Description: 取消注冊內存指針* @Param[IN] pointer: 要取消注冊的內存指針* @See also: FreePointerNode()*/
void CStoreMemAlloc::Unregister(const void* pointer)
{// 斷言,確保內存指針和計數器的合法性Assert(pointer && m_count > 0);// Step 1: 確定包含該指針的節點列表Assert((MaxPointersArryLen & (MaxPointersArryLen - 1)) == 0);int idx = PointerGetDatum(pointer) & (MaxPointersArryLen - 1);// Step 2: 在節點列表中查找指針PointerNode* nodePtr = m_tab[idx].header;Assert(nodePtr);PointerNode* prePtr = NULL;while (nodePtr != NULL) {if (nodePtr->ptr == pointer) {// 如果前一個節點為空,說明要取消注冊的是頭節點if (prePtr == NULL) {m_tab[idx].header = nodePtr->next;// 如果這個列表只有一個節點if (m_tab[idx].tail == nodePtr) {Assert(m_tab[idx].header == NULL);m_tab[idx].tail = NULL;}} else {// 否則,修改前一個節點的 next 指針prePtr->next = nodePtr->next;// 如果取消注冊的是尾節點,需要修改尾指針if (m_tab[idx].tail == nodePtr) {m_tab[idx].tail = prePtr;Assert(m_tab[idx].tail->next == NULL);}}// 重置并釋放節點nodePtr->Reset();FreePointerNode(nodePtr);break;}prePtr = nodePtr;nodePtr = nodePtr->next;}// 減少計數器--m_count;// 斷言,確保找到了要取消注冊的指針節點Assert(nodePtr != NULL);
}

CStoreMemAlloc::Reset 函數

??CStoreMemAlloc 類中的 Reset 方法用于重置內存指針管理器的狀態釋放所有注冊的內存。具體作用和功能如下:

描述:該方法用于在事務結束時,重置內存指針管理器的狀態,釋放所有注冊的內存。
功能:如果存在注冊的內存指針:Step 1: 釋放 m_tab 中的每個列表中的內存指針。遍歷 m_tab 數組,釋放每個列表中的內存指針。注意,必須將列表的頭尾節點重置為 NULL,因為線程可能被重用。斷言,確保釋放的內存數和計數器一致。Step 2: 釋放緩存的節點(如果有的話)。釋放緩存的節點,以便在下一次使用時重新分配。

??這個方法的目的是確保在事務結束時,所有注冊的內存都被正確釋放,以避免內存泄漏。函數源碼如下所示:(路徑:src/gausskernel/storage/cstore/cstore_mem_alloc.cpp

/** @Description: 重置內存指針管理器狀態,釋放所有注冊的內存*/
void CStoreMemAlloc::Reset()
{uint32 i = 0;uint32 freeNum = 0;// 如果存在注冊的內存指針if (m_count) {// Step 1: 釋放 m_tab 中的每個列表for (i = 0; i < MaxPointersArryLen; ++i) {PointerNode* nodePtr = m_tab[i].header;PointerNode* tmpPtr = NULL;// 釋放每個列表中的內存指針while ((nodePtr != NULL) && (nodePtr->ptr != NULL)) {free(nodePtr->ptr);tmpPtr = nodePtr->next;free(nodePtr);nodePtr = tmpPtr;++freeNum;}// 注意,必須將 header 和 tail 重置為 NULL// 因為線程可能被重用m_tab[i].header = NULL;m_tab[i].tail = NULL;}// 斷言,確保釋放的內存數和計數器一致Assert(m_count == freeNum);m_count = 0;}// Step 2: 釋放緩存的節點(如果有的話)for (i = 0; i < m_ptrNodeCacheCount; ++i) {free(m_ptrNodeCache[i]);}m_ptrNodeCacheCount = 0;
}

CStoreMemAlloc::Init 函數

??這段代碼是 CStoreMemAlloc 類中的 Init 方法。該方法用于初始化內存指針管理器的狀態。具體作用和功能如下:

描述:該方法用于在開始新的事務時,初始化內存指針管理器的狀態。
功能:重置計數器。斷言,確保 MaxPointersArryLen 是2的冪。初始化 m_tab 數組,將每個列表的頭尾節點都設置為 NULL。初始化緩存節點計數器。

??這個方法的目的是確保在每次開始新的事務時,內存指針管理器都處于初始狀態。函數源碼如下所示:(路徑:src/gausskernel/storage/cstore/cstore_mem_alloc.cpp

/** @Description: 初始化內存指針管理器*/
void CStoreMemAlloc::Init()
{// 重置計數器m_count = 0;// 斷言,確保 MaxPointersArryLen 是2的冪Assert((MaxPointersArryLen & (MaxPointersArryLen - 1)) == 0);// 初始化 m_tab 數組for (uint32 i = 0; i < MaxPointersArryLen; ++i) {m_tab[i].header = NULL;m_tab[i].tail = NULL;}// 初始化緩存節點計數器m_ptrNodeCacheCount = 0;
}

總結

CStoreMemAlloc
作用: CStoreMemAlloc 類用于管理列存儲中的內存分配和釋放
功能:

  • Palloc 方法: 分配內存,并根據需要注冊到管理器。
  • FreePointerNode 方法: 釋放緩存的節點。
  • Repalloc 方法: 重新分配內存,同時處理注冊和取消注冊。
  • Pfree 方法: 釋放內存,同時處理取消注冊。
  • Register 方法: 注冊內存指針,將其添加到管理表。
  • Unregister 方法: 取消注冊內存指針,將其從管理表中移除。
  • Reset 方法: 重置管理器狀態,釋放所有注冊的內存。
  • Init 方法: 初始化管理器狀態。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/160356.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/160356.shtml
英文地址,請注明出處:http://en.pswp.cn/news/160356.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

杭電oj 2064 漢諾塔III C語言

#include <stdio.h>void main() {int n, i;long long sum[35] { 2,8,26 };for (i 3; i < 35; i)sum[i] 3 * sum[i - 1] 2;while (~scanf_s("%d", &n))printf("%lld\n", sum[n - 1]); }

問鼎web服務

華子目錄 www簡介常見Web服務程序介紹&#xff1a;服務器主機主要數據瀏覽器網址及http介紹urlhttp請求方法 http協議請求的工作流程www服務器類型靜態網站動態網站 快速安裝Apache安裝準備工作httpd所需目錄主配置文件 實驗操作 www簡介 Web網絡服務也叫www&#xff08;world…

編碼的發展歷史

編碼的發展歷史 ASCII&#xff1a; ASCII編碼使用7位二進制數表示一個字符&#xff0c;范圍從0到127。每個字符都有一個唯一的ASCII碼值與之對應。例如&#xff0c;大寫字母"A"的ASCII碼是65&#xff0c;小寫字母"a"的ASCII碼是97。 ASCII字符集包括英文…

linux服務器安裝gitlab

一、安裝gitlab sudo yum install curl policycoreutils-python openssh-server openssh-clients sudo systemctl enable sshd sudo systemctl start sshd sudo firewall-cmd --permanent --add-servicehttp curl https://packages.gitlab.com/install/repositories/gitla…

LabVIEW中將SMU信號連接到PXI背板觸發線

LabVIEW中將SMU信號連接到PXI背板觸發線 本文介紹如何將信號從PXI&#xff08;e&#xff09;SMU卡路由到PXI&#xff08;e&#xff09;機箱上的背板觸發線。該過程涉及使用NI-DCPowerVI將SMU信號導出到PXI_TRIG線上。 在繼續操作之前&#xff0c;請確保在開發PC上安裝了兼容版…

MySQL啟動MySQL8.0并指定配置文件

MySQL啟動MySQL8.0并指定配置文件 mkdir -p /mysql8hello/config ; mkdir -p /mysql8hello/data ; mkdir -p /mysql8hello/logs; mkdir -p /mysql8hello/conf; vim /mysql8hello/config/my.cnf; # 啟動報錯就修改成777&#xff0c;但是會提示風險 chmod 644 /mysql8hello/co…

d3dx9_43.dll缺失怎么辦?教你一分鐘修復d3dx9_43.dll丟失問題

今天&#xff0c;與大家分享關于“d3dx9_43.dll丟失的5個解決方法”的主題。在我們的日常生活和工作中&#xff0c;我們可能會遇到各種各樣的問題&#xff0c;而d3dx9_43.dll丟失就是其中之一。那么&#xff0c;什么是d3dx9_43.dll呢&#xff1f;它為什么會丟失&#xff1f;又該…

【LeetCode刷題-鏈表】--25.K個一組翻轉鏈表

25.K個一組翻轉鏈表 思路&#xff1a; 把鏈表節點按照k個一組分組&#xff0c;可以使用一個指針head依次指向每組的頭節點&#xff0c;這個指針每次向前移動k步&#xff0c;直至鏈表結尾&#xff0c;對于每個分組&#xff0c; 先判斷它的長度是否大于等于k&#xff0c;若是&am…

什么是Zero-shot(零次學習)

1 Zero-shot介紹 Zero-shot學習&#xff08;ZSL&#xff09;是機器學習領域的一種先進方法&#xff0c;它旨在使模型能夠識別、分類或理解在訓練過程中未見過的類別或概念。這種學習方法對于解決現實世界中常見的長尾分布問題至關重要&#xff0c;即對于一些罕見或未知類別的樣…

商務俄語學習,柯橋基礎入門教學,千萬別小看俄語中的“что”

1、что до (чего) 至于 例&#xff1a; что до меня, то я не могу согласиться 至于我&#xff0c;我不能同意。 А что до зимовки... Ты приедешь в этом году? 說到冬天和過冬…你今年回來嗎…

在windows筆記本中安裝tensorflow1.13.2版本的gpu環境2

tensorflow1.13.2版本的gpu環境 看python-anacona的安裝只需要看1.1部分即可 目錄 1.1 Anaconda安裝 1.2 tensorflow-gpu安裝 1.3 python編譯器-pycharm安裝 1.1 Anaconda安裝 從鏡像源處下載anaconda&#xff0c;地址&#xff1a;Index of /anaconda/archive/ | 北京…

PTA-6-45 工廠設計模式-運輸工具

題目如下&#xff1a; 工廠類用于根據客戶提交的需求生產產品&#xff08;火車、汽車或拖拉機&#xff09;。火車類有兩個子類屬性&#xff1a;車次和節數。拖拉機類有1個子類方法耕地&#xff0c;方法只需簡單輸出“拖拉機在耕地”。為了簡化程序設計&#xff0c;所有…

基于docker實現JMeter分布式壓測

為什么需要分布式&#xff1f; 在工作中經常需要對一些關鍵接口做高QPS的壓測&#xff0c;JMeter是由Java 語言開發&#xff0c;沒創建一個線程&#xff08;虛擬用戶&#xff09;&#xff0c;JVM默認會為每個線程分配1M的堆棧內存空間。受限于單臺試壓機的配置很難實現太高的并…

LeetCode59.螺旋矩陣

LeetCode59.螺旋矩陣 1.問題描述2.解題思路3.代碼 1.問題描述 給你一個正整數 n &#xff0c;生成一個包含 1 到 n2 所有元素&#xff0c;且元素按順時針順序螺旋排列的 n x n 正方形矩陣 matrix 。 示例 1&#xff1a; 輸入&#xff1a;n 3 輸出&#xff1a;[[1,2,3],[8,9,…

Codeforces Round 822 (Div. 2)(D前綴和+貪心加血量)

A.選三條相鄰的邊遍歷一次求最小值 #include<bits/stdc.h> using namespace std; const int N 1e610,mod1e97; #define int long long int n,m; vector<int> g[N]; int a[N]; void solve() {cin>>n;int res2e18;for(int i1;i<n;i) cin>>a[i];sort…

談一談什么是接口測試?怎樣做接口測試?

掃盲內容&#xff1a; 1.什么是接口&#xff1f; 2.接口都有哪些類型&#xff1f; 3.接口的本質是什么&#xff1f; 4.什么是接口測試&#xff1f; 5.問什么要做接口測試&#xff1f; 6.怎樣做接口測試&#xff1f; 7.接口測測試點是什么&#xff1f; 8.接口測試都要掌…

童裝店鋪如何通過軟文增加客流量

在信息超負載、媒介粉塵化、產品同質化多重因素下&#xff0c;傳統營銷疲態盡顯、日漸式微&#xff0c;很難支撐新環境下品牌和企業的持續增長。聚焦童裝行業更是如此&#xff0c;一方面用戶迭代速度快&#xff0c;另一方面&#xff0c;新時代父母的育兒觀念更加精細化&#xf…

安裝pytorch

cuda≤11.6&#xff0c;觀察控制面板 觀察torch對應cuda版本 https://download.pytorch.org/whl/torch/ 安裝cuda11.6.0 CUDA Toolkit Archive | NVIDIA Developer cmd輸入nvcc -V 編輯國內鏡像源 .condarc anaconda prompt輸入 查看環境 conda env list 安裝py3.9…

MySQL面試,MySQL事務,MySQL鎖,MySQL集群,主從,MySQL分區,分表,InnoDB

文章目錄 數據庫-MySQLMySQL主從、集群模式簡單介紹1、主從模式 Replication2、集群模式3、主從模式部署注意事項 UNION 和 UNION ALL 區別分庫分表1.垂直拆分2、水平拆分 MySQL有哪些數據類型1、整數類型**&#xff0c;2、實數類型**&#xff0c;3、字符串類型**&#xff0c;4…

DDoS攻擊頻發,科普防御DDoS攻擊的幾大有效方法

談到目前最兇猛、頻率高&#xff0c;且令人深惡痛絕的網絡攻擊&#xff0c;DDoS攻擊無疑能在榜上占有一席之地。各種規模的企業報包括組織機構都可能受到影響&#xff0c;它能使企業宕機數小時以上&#xff0c;給整個互聯網造成無數損失。可以說&#xff0c;怎樣防御DDoS攻擊是…