中文亚洲精品无码_熟女乱子伦免费_人人超碰人人爱国产_亚洲熟妇女综合网

當前位置: 首頁 > news >正文

網(wǎng)站如何做電腦和手機appseo創(chuàng)業(yè)

網(wǎng)站如何做電腦和手機app,seo創(chuàng)業(yè),防水網(wǎng)站建設,網(wǎng)頁設計綜合實訓論文返回:SQLite—系列文章目錄 上一篇:SQLite中的原子提交(四) 下一篇:自己編譯SQLite或將SQLite移植到新的操作系統(tǒng)(六) ?概述 SQLite使用動態(tài)內存分配來獲得 用于存儲各種對象的內存 (例如…

??返回:SQLite—系列文章目錄???

上一篇:SQLite中的原子提交(四)

下一篇:自己編譯SQLite或將SQLite移植到新的操作系統(tǒng)(六)

?概述

SQLite使用動態(tài)內存分配來獲得 用于存儲各種對象的內存 (例如:數(shù)據(jù)庫連接和預準備語句)并構建 數(shù)據(jù)庫文件的內存緩存,用于保存查詢結果。 在制作動態(tài)內存分配子系統(tǒng)方面付出了很多努力 SQLite 可靠、可預測、穩(wěn)健、安全、高效。

本文檔概述了 SQLite的。目標受眾是正在調整其 使用 SQLite 在苛刻的環(huán)境中實現(xiàn)最佳性能。 本文檔中的任何內容都不是使用 SQLite 所需的知識。這 SQLite的默認設置和配置在大多數(shù)情況下都能很好地工作 應用。但是,本文檔中包含的信息可能 對于正在調整 SQLite 以符合特殊 要求或在異常情況下運行。

1.?特點

SQLite 核心及其內存分配子系統(tǒng)提供 以下功能:

  • 對分配失敗具有魯棒性。如果內存分配失敗(也就是說, 如果 malloc() 或 realloc() 返回 NULL) 然后 SQLite 將優(yōu)雅地恢復。SQLite 將首先嘗試 若要從未固定的緩存頁中釋放內存,請重試分配 請求。 如果做不到這一點,SQLite 將停止什么 它正在執(zhí)行并將SQLITE_NOMEM錯誤代碼返回到應用程序,否則它將 在沒有請求的內存的情況下湊合著過。

  • 沒有內存泄漏。應用程序負責銷毀它分配的任何對象。 (例如,應用程序sqlite3_finalize必須在 每個數(shù)據(jù)庫連接上的每個預準備語句和?sqlite3_close()。但只要 應用程序配合,SQLite永遠不會泄漏內存。這是 即使面對內存分配失敗或其他系統(tǒng)也是如此 錯誤。

  • 內存使用限制。sqlite3_soft_heap_limit64()?機制允許應用程序 設置SQLite努力保持在以下的內存使用限制。SQLite的 將嘗試重用其緩存中的內存,而不是分配新的內存 內存,因為它接近軟限制。

  • Zero-malloc 選項。該應用程序可以選擇為 SQLite 提供多個大容量內存緩沖區(qū) 在啟動時,SQLite 將使用這些提供的緩沖區(qū)進行所有 它的內存分配需要,從不調用系統(tǒng) malloc()或 free()。

  • 應用程序提供的內存分配器。該應用程序可以為 SQLite 提供指向替代方案的指針 啟動時的內存分配器。替代內存分配器 將用于代替系統(tǒng) malloc() 和 free()。

  • 防止故障和碎片化。可以對SQLite進行配置,以便受某些使用限制 下面詳細介紹了它,它保證永遠不會使內存分配失敗 或對堆進行碎片化。 此屬性對于長時間運行、高可靠性非常重要 內存分配錯誤可能導致的嵌入式系統(tǒng) 到整個系統(tǒng)故障。

  • 內存使用情況統(tǒng)計信息。應用程序可以查看它們正在使用的內存量,并檢測何時 內存使用量接近或超過設計邊界。

  • 與內存調試器配合得很好。SQLite中的內存分配結構化,因此標準 可以使用第三方內存調試器(例如?DMalloc?或?Valgrind)來驗證是否正確 內存分配行為。

  • 對分配器的最小調用。系統(tǒng) malloc()和 free()實現(xiàn)效率低下 在許多系統(tǒng)上。SQLite致力于減少整體處理時間 通過盡量減少其對 malloc()和 free()的使用。

  • 開放獲取。可插拔的SQLite擴展甚至應用程序本身都可以 訪問相同的底層內存分配 SQLite 通過?sqlite3_malloc()、sqlite3_realloc()?和?sqlite3_free()?接口使用的例程。

2.?測試

SQLite源代碼樹中的大多數(shù)代碼都專門用于測試和驗證??煽啃詫QLite很重要。 測試基礎設施的任務之一是確保 SQLite不會濫用動態(tài)分配的內存,即SQLite 不會泄漏內存,并且 SQLite 響應 正確到動態(tài)內存分配失敗。

測試基礎結構驗證 SQLite 不會濫用 使用專門檢測的動態(tài)分配內存 內存分配器。已啟用檢測的內存分配器 在編譯時使用?SQLITE_MEMDEBUG?選項。儀器化 內存分配器比默認內存分配器慢得多,并且 因此,不建議在生產中使用。但是當 在測試期間啟用, 檢測內存分配器執(zhí)行以下檢查:

  • 邊界檢查。檢測的內存分配器將哨兵值放在兩端 以驗證 SQLite 中沒有任何內容寫入 超出分配范圍。

  • 釋放后使用內存。當每個內存塊被釋放時,每個字節(jié)都會被 無意義的位模式。這有助于確保沒有內存 被釋放后使用。

  • 釋放未從 malloc 獲得的內存。來自檢測內存分配器的每個內存分配都包含 用于驗證釋放的每個分配是否都到位的哨兵 來自先前的 malloc。

  • 未初始化的內存。檢測的內存分配器初始化每個內存分配 到無意義的位模式,以幫助確保用戶不 關于分配內存內容的假設。

無論檢測的內存分配器是否 使用時,SQLite 會跟蹤當前簽出的內存量。 有數(shù)百個測試腳本用于測試 SQLite。在 在每個腳本的末尾,所有對象都被銷毀,并對 確保所有內存都已釋放。記憶就是這樣 檢測到泄漏。請注意,內存泄漏檢測在以下位置生效 在測試構建和生產構建期間的所有時間。每當 其中一位開發(fā)人員運行任何單獨的測試腳本,內存泄漏 檢測處于活動狀態(tài)。因此,在開發(fā)過程中確實會出現(xiàn)內存泄漏 被快速檢測和修復。

SQLite 對內存不足 (OOM) 錯誤的響應使用 可以模擬內存故障的專用內存分配器覆蓋。 覆蓋層是插入內存分配器之間的一層 以及 SQLite 的其余部分。覆蓋層通過大多數(shù)內存分配 請求直接傳遞到底層分配器,并將 結果返回給請求者。但疊加層可以設置為 導致第 N 個內存分配失敗。要運行 OOM 測試,覆蓋 首先設置為在第一次分配嘗試時失敗。然后進行一些測試 運行腳本并驗證是否正確捕獲了分配 并處理。然后,疊加層設置為在第二個失敗 分配,然后重復測試。故障點繼續(xù)推進 一次分配一個,直到整個測試過程運行到 完成而不出現(xiàn)內存分配錯誤。這整個 測試序列運行兩次。在第一次傳遞時, overlay 設置為僅第 N 個分配失敗。在第二遍時, 疊加設置為第 N 次和所有后續(xù)分配失敗。

請注意,內存泄漏檢測邏輯甚至繼續(xù)工作 使用 OOM 覆蓋時。這將驗證 SQLite 即使遇到內存分配錯誤,也不會泄漏內存。 另請注意,OOM 覆蓋可以與任何底層內存一起使用 分配器,包括用于檢查的檢測內存分配器 用于內存分配誤用。通過這種方式,可以驗證 OOM 錯誤不會引起其他類型的內存使用錯誤。

最后,我們觀察到檢測的內存分配器和 內存泄漏檢測器既適用于整個 SQLite 測試套件,又適用于整個 SQLite 測試套件?TCL 測試套件提供超過 99% 的聲明測試覆蓋率,并且?TH3?測試線束提供?100% 的分支測試覆蓋率,無泄漏泄漏。這是 正確使用動態(tài)內存分配的有力證據(jù) 在SQLite中無處不在。

2.1.?reallocarray()的使用

reallocarray() 接口是最近的一項創(chuàng)新(大約 2014 年) 來自 OpenBSD 社區(qū),這些社區(qū)致力于防止 下一個 避免 32 位整數(shù)的“Heartbleed”錯誤?內存分配大小計算上的算術溢出。這 reallocarray() 函數(shù)同時具有 unit-size 和 count 參數(shù)。 分配足夠的內存來容納每個 X 字節(jié)的 N 個元素的數(shù)組 在大小上,稱為“reallocarray(0,X,N)”。這比 將 “malloc(X*N)” 調用為 reallocarray() 的傳統(tǒng)技術 消除了 X*N 乘法溢出的風險,并且 導致 malloc() 返回的緩沖區(qū)大小與 應用程序預期。

SQLite 不使用 reallocarray()。原因是 reallocarray() 對 SQLite 沒有用。事實證明,SQLite從不做內存 分配是兩個整數(shù)的簡單乘積。取而代之的是 SQLite 是否分配“X+C”或“N*X+C”或“M*N*X+C”或 “N*X+M*Y+C”,依此類推。reallocarray() 接口沒有幫助 在這些情況下避免整數(shù)溢出。

然而,內存分配計算中的整數(shù)溢出 大小是SQLite想要處理的問題。防止 問題,所有SQLite內部內存分配都使用薄包裝器進行 采用有符號的 64 位整數(shù)大小參數(shù)的函數(shù)。SQLite的 源代碼經(jīng)過審計,以確保攜帶所有大小的計算 out 也使用 64 位有符號整數(shù)。SQLite將 拒絕一次性分配超過 2GB 的內存。(共同點 使用,SQLite很少一次分配超過8KB的內存 因此,2GB 的分配限制不是負擔。所以 64 位大小參數(shù) 為檢測溢出提供了大量余量。同樣的審計 驗證所有大小的計算是否都以 64 位有符號整數(shù)的形式完成 還驗證是否無法溢出 64 位整數(shù) 在計算過程中。

用于確保內存分配大小計算的代碼審核 在每次 SQLite 發(fā)布之前,SQLite 中的 do not overflow 都會重復。

3.?配置

SQLite中的默認內存分配設置是合適的 適用于大多數(shù)應用。但是,具有不尋常或特別的應用程序 嚴格的要求可能希望將配置調整為更接近 使SQLite符合他們的需求。 編譯時和啟動時配置選項都可用。

3.1.?替代的低級內存分配器

SQLite源代碼包括幾種不同的內存分配 可以在編譯時或在有限范圍內選擇的模塊 在開始時間。

3.1.1.?默認內存分配器

默認情況下,SQLite 使用 malloc()、realloc() 和 free() 例程 從標準 C 庫中獲取內存分配需求。這些例程 被一個薄包裝器包圍,該包裝器還提供“memsize()”函數(shù) 這將返回現(xiàn)有分配的大小。memsize() 函數(shù) 需要準確計算未完成的字節(jié)數(shù) 記憶;memsize() 確定要從未完成的字節(jié)中刪除多少字節(jié) 釋放分配時計數(shù)。默認分配器實現(xiàn) memsize() 通過始終在每個 malloc() 請求上分配 8 個額外的字節(jié)和 將分配的大小存儲在該 8 字節(jié)標頭中。

對于大多數(shù)應用程序,建議使用默認內存分配器。 如果您沒有迫切的使用替代內存的需求 分配器,然后使用默認值。

3.1.2.?調試內存分配器

如果使用?SQLITE_MEMDEBUG?compile-time 選項編譯 SQLite, 然后圍繞系統(tǒng) malloc()、realloc()、 和 free()。 繁重的包裝器分配了大約 100 字節(jié)的額外空間 每次分配。額外的空間用于放置哨兵值 在分配的兩端返回到 SQLite 核心。當一個 分配被釋放, 檢查這些哨兵以確保 SQLite 核心沒有溢出 任一方向的緩沖區(qū)。當系統(tǒng)庫為 GLIBC 時, heavy wrapper 還利用 GNU backtrace() 函數(shù)來檢查 堆棧并記錄 malloc() 調用的祖先函數(shù)。什么時候 運行 SQLite 測試套件時,沉重的包裝器還記錄了 當前測試用例。后兩個功能可用于 跟蹤測試套件檢測到的內存泄漏源。

設置SQLITE_MEMDEBUG時使用的重型包裝器 確保每個新分配都填充了無意義的數(shù)據(jù),然后 將分配返回給調用方。并且一旦分配 是免費的,它又充滿了無意義的數(shù)據(jù)。這兩個操作有幫助 以確保 SQLite 核心不會對狀態(tài)做出假設 新分配的內存,并且在之后未使用內存分配 他們已經(jīng)獲釋。

SQLITE_MEMDEBUG?使用的重型包裝紙旨在使用 僅在 SQLite 的測試、分析和調試期間。厚重的包裝紙 具有顯著的性能和內存開銷,可能不應該 用于生產。

3.1.3.?Win32 本機內存分配器

如果 SQLite 是使用?SQLITE_WIN32_MALLOC?編譯時選項為 Windows 編譯的,則會使用不同的瘦包裝器 HeapAlloc()、HeapReAlloc() 和 HeapFree()。薄包裝器使用 配置的 SQLite 堆,這將與默認進程不同 如果使用了?SQLITE_WIN32_HEAP_CREATE?編譯時選項,則為 heap。在 此外,當進行分配或釋放時,HeapValidate() 將是 如果 SQLite 是在啟用 assert() 和?SQLITE_WIN32_MALLOC_VALIDATE?編譯時選項的情況下編譯的,則調用。

3.1.4.?零故障內存分配器

當使用?SQLITE_ENABLE_MEMSYS5?選項編譯 SQLite 時,一個 不使用 malloc() 的替代內存分配器包含在 建。SQLite開發(fā)人員引用了這種替代內存分配器 作為“memsys5”。即使它包含在構建中,memsys5 也是 默認情況下處于禁用狀態(tài)。 若要啟用 memsys5,應用程序必須調用以下 SQLite 啟動時的接口:

sqlite3_config(SQLITE_CONFIG_HEAP, pBuf, szBuf, mnReq);

在上面的調用中,pBuf 是指向一個大的連續(xù)塊的指針 SQLite將用于滿足其所有內存的內存空間 分配需求。pBuf 可能指向靜態(tài)數(shù)組,也可能指向靜態(tài)數(shù)組 是從其他一些特定于應用程序的機制獲取的內存。 szBuf 是一個整數(shù),即內存空間的字節(jié)數(shù) 由pBuf指出。mnReq 是另一個整數(shù),即 分配的最小大小。對?sqlite3_malloc(N)?的任何調用,其中 N 小于 mnReq 將四舍五入為 mnReq。mnReq 必須是 二的冪。我們稍后將看到 mnReq 參數(shù)為 對于減小?n?的值很重要,因此也很重要?羅布森證明中的尺寸要求。

memsys5 分配器設計用于嵌入式系統(tǒng), 盡管沒有什么可以阻止它在工作站上的使用。 szBuf 通常在幾百 KB 到幾千字節(jié)之間 十幾兆字節(jié),具體取決于系統(tǒng)要求和內存預算。

memsys5 使用的算法可以稱為“二次方, 第一次適合“。所有內存分配的大小 請求四舍五入為 2 的冪,請求得到滿足 通過 pBuf 中足夠大的第一個空閑插槽。相鄰釋放 使用伙伴系統(tǒng)合并分配。如果使用得當, 該算法提供了防止碎片和 細分,如下所述。

3.1.5.?實驗記憶分配器

用于零 malloc 內存分配器的名稱“memsys5”意味著 確實有幾個額外的內存分配器可用 有。默認內存分配器為“memsys1”。調試 內存分配器是“memsys2”。這些已經(jīng)涵蓋。

如果SQLite是用SQLITE_ENABLE_MEMSYS3編譯的,那么另一個 零 malloc 內存分配器,類似于 memsys5,包含在 源代碼樹。必須激活 memsys3 分配器,如 memsys5 通過調用?sqlite3_config(SQLITE_CONFIG_HEAP,...)。機芯3 使用提供的內存緩沖區(qū)作為所有內存分配的源。 memsys3 和 memsys5 之間的區(qū)別在于 memsys3 使用 不同的內存分配算法似乎在以下方面運行良好 實踐,但不提供數(shù)學 保證內存碎片和故障。Memsys3 是 Memsys5 的前身。SQLite開發(fā)人員現(xiàn)在認為 memsys5 優(yōu)于 memsys3 以及所有需要零 malloc 內存的應用程序 分配器應優(yōu)先使用 memsys5 而不是 memsys3。Memsys3 是 被視為實驗性和已棄用,可能會被刪除 從 SQLite 未來版本中的源代碼樹。

Memsys4 和 memsys6 是實驗性內存分配器 于 2007 年左右推出,隨后從 源樹在 2008 年左右,在很明顯他們 沒有增加任何新值。

將來的版本中可能會添加其他實驗性內存分配器 的 SQLite。人們可能會預料到這些將被稱為 memsys7、memsys8、 等等。

3.1.6.?應用程序定義的內存分配器

新的內存分配器不必是 SQLite 源代碼樹的一部分 也不包含在 sqlite3.c?合并中。個別應用可以 在啟動時向 SQLite 提供自己的內存分配器。

要使 SQLite 使用新的內存分配器,應用程序 只需調用:

sqlite3_config(SQLITE_CONFIG_MALLOC, pMem);

在上面的調用中,pMem 是指向sqlite3_mem_methods對象的指針 它定義了特定于應用程序的內存分配器的接口。?sqlite3_mem_methods對象實際上只是一個包含 指向函數(shù)的指針,以實現(xiàn)各種內存分配基元。

在多線程應用程序中,當且僅當啟用SQLITE_CONFIG_MEMSTATUS時,才會序列化對sqlite3_mem_methods的訪問。 如果禁用SQLITE_CONFIG_MEMSTATUS,則sqlite3_mem_methods中的方法必須滿足其自己的序列化需求。

3.1.7.?內存分配器覆蓋

應用程序可以在 SQLite 核心和底層內存分配器。 例如,SQLite 的內存不足測試邏輯使用可以模擬內存分配的覆蓋層 失敗。

可以使用

sqlite3_config(SQLITE_CONFIG_GETMALLOC, pOldMem);

接口,以獲取指向現(xiàn)有內存分配器的指針。 現(xiàn)有分配器由疊加層保存,并用作 執(zhí)行實際內存分配的回退。然后疊加是 插入代替現(xiàn)有的內存分配器,使用?如上所述的 sqlite3_config(SQLITE_CONFIG_MALLOC,...)。

3.1.8.?No-op 內存分配器存根

如果使用?SQLITE_ZERO_MALLOC?選項編譯 SQLite,則?默認內存分配器將被省略,并替換為存根 從不分配任何內存的內存分配器。對 存根內存分配器將報告沒有可用的內存。

無操作內存分配器本身沒有用。它只存在 作為占位符,以便SQLite具有要鏈接的內存分配器 在可能沒有 malloc()、free() 或 realloc() 的系統(tǒng)上 標準庫。 使用?SQLITE_ZERO_MALLOC?編譯的應用程序需要 將?sqlite3_config()?與?SQLITE_CONFIG_MALLOC?或?SQLITE_CONFIG_HEAP?一起使用來指定新的備用內存分配器 在開始使用 SQLite 之前。

3.2.?頁面緩存內存

在大多數(shù)應用程序中,數(shù)據(jù)庫頁面緩存子系統(tǒng) SQLite使用比所有其他部分更多的動態(tài)分配內存 SQLite組合??吹綌?shù)據(jù)庫頁面緩存并不罕見 消耗的內存是 SQLite 其余部分總和的 10 倍以上。

SQLite可以配置為從以下位置進行頁面緩存內存分配 固定大小的單獨且獨特的內存池 插槽。這可能有兩個優(yōu)點:

  • 由于分配的大小都相同,因此內存分配器可以 操作速度更快。分配器無需費心進行合并 相鄰的空閑插槽或搜索插槽 大小合適。所有未分配的內存插槽都可以存儲在 鏈表。分配包括從 列表。解除分配只是在列表的開頭添加一個條目。

  • 對于單個分配大小,Robson 證明中的?n?參數(shù)為 1,分配器所需的總內存空間為 1 (N) 正好等于使用的最大內存 (M)。 無需額外的內存來覆蓋分段開銷,因此 降低內存需求。這對于 頁面緩存內存,因為頁面緩存構成了最大的組件 SQLite的內存需求。

默認情況下,頁面緩存內存分配器處于禁用狀態(tài)。 應用程序可以在啟動時啟用它,如下所示:

sqlite3_config(SQLITE_CONFIG_PAGECACHE, pBuf, sz, N);

pBuf 參數(shù)是指向連續(xù)字節(jié)范圍的指針,該字節(jié) SQLite 將用于頁面緩存內存分配。緩沖區(qū)必須是 大小至少為 sz*N 字節(jié)。“sz”參數(shù) 是每個頁面緩存分配的大小。N 是最大值 可用分配的數(shù)量。

如果 SQLite 需要大于“sz”字節(jié)的頁面緩存條目或 如果它需要超過 N 個條目,則回退到使用 通用內存分配器。

3.3.?Lookaside 內存分配器

SQLite數(shù)據(jù)庫連接使許多 小而短的內存分配。 這最常發(fā)生在使用?sqlite3_prepare_v2()?編譯 SQL 語句時,但在使用?sqlite3_step()?運行準備好的語句時,這種情況的程度也較小。這些小內存 分配用于保存表的名稱等內容 和列、解析樹節(jié)點、單個查詢結果值、 和 B-Tree 光標對象。因此,有 對 malloc() 和 free() 的大量調用 - malloc() 和 free() 最終使用了分配的 CPU 時間的很大一部分 到 SQLite。

SQLite?版本 3.6.1?(2008-08-06) 引入了 Lookaside 內存分配器 幫助減少內存分配負載。在后備分配器中, 每個數(shù)據(jù)庫連接都預分配一個大塊內存 (通常在 60 到 120 KB 的范圍內)并劃分該塊 最多成小的固定大小的“插槽”,每個插槽大約100到1000字節(jié)。這 成為 Lookaside 內存池。此后,內存分配 與數(shù)據(jù)庫連接相關聯(lián),并且不會太大 滿意地使用其中一個后備池插槽,而不是通過調用 通用內存分配器。更大的分配繼續(xù) 使用通用內存分配器,以及發(fā)生的分配 當后備池插槽全部簽出時。 但在許多情況下,內存 撥款足夠少,而且很少有未完成的 可以從后臺滿足新的內存請求 池。

由于后備分配的大小始終相同,因此分配 解除分配算法非???。沒有 需要合并相鄰的空閑插槽或搜索插槽 特定大小。每個數(shù)據(jù)庫連接都維護一個單一鏈接 未使用的插槽列表。分配請求只需拉取第一個 元素。解除分配只是將元素推回 列表的前面。 此外,假定每個數(shù)據(jù)庫連接已經(jīng)是 在單個線程中運行(中已經(jīng)有互斥鎖 地方來強制執(zhí)行此操作),因此不需要額外的互斥 序列化對 Lookaside 插槽空閑列表的訪問。 因此,后備內存 分配和解除分配非常快。在速度測試中 Linux 和 Mac OS X 工作站,SQLite 表現(xiàn)出整體性能 改進高達 10% 和 15%,具體取決于工作負載如何 并配置了 lookaway。

后備內存池的大小具有全局默認值 但也可以逐個連接進行配置。 要更改后備內存池的默認大小,請執(zhí)行以下操作: 編譯時,使用?-DSQLITE_DEFAULT_LOOKASIDE=SZ,N?選項。 要更改后備內存池的默認大小,請執(zhí)行以下操作: start-time,使用?sqlite3_config()?接口:

sqlite3_config(SQLITE_CONFIG_LOOKASIDE, sz, cnt);

“sz”參數(shù)是每個后備時隙的大小(以字節(jié)為單位)。 “cnt”參數(shù)為 每個數(shù)據(jù)庫連接的后備內存插槽總數(shù)。 總金額 分配給每個數(shù)據(jù)庫連接的后備內存為 sz*cnt 字節(jié)。

可以使用以下調用更改單個數(shù)據(jù)庫連接“db”的后備池:

sqlite3_db_config(db, SQLITE_DBCONFIG_LOOKASIDE, pBuf, sz, cnt);

“pBuf”參數(shù)是指向內存空間的指針,該指針將是 用于 Lookaside 內存池。如果 pBuf 為 NULL,則 SQLite 將使用?sqlite3_malloc()?為內存池獲取自己的空間。 “sz” 和 “cnt” 參數(shù)是每個后備槽的大小 和插槽數(shù)。如果 pBuf 不為 NULL,則 必須至少指向 sz*cnt 字節(jié)的內存。

只有在存在以下情況時,才能更改后備配置 沒有未完成的數(shù)據(jù)庫連接的后備分配。 因此,應在創(chuàng)建 使用?sqlite3_open()(或等效項)及之前的數(shù)據(jù)庫連接 評估連接上的任何 SQL 語句。

3.3.1.?雙尺寸后備箱

從 SQLite 版本 3.31.0 (2020-01-22) 開始, Lookaside 支持兩個內存池,每個內存池的大小不同 槽。小插槽池使用 128 字節(jié)插槽,大插槽使用 池使用?SQLITE_DBCONFIG_LOOKASIDE?指定的任何大小(默認為 1200 字節(jié))。像這樣將池一分為二 允許 Lookaside 更頻繁地覆蓋內存分配 同時減少每個數(shù)據(jù)庫連接堆的使用 從 120KB 降至 48KB。

配置繼續(xù)使用SQLITE_DBCONFIG_LOOKASIDE或 SQLITE_CONFIG_LOOKASIDE配置選項,如上所述, 使用參數(shù)“sz”和“cnt”。用于 Lookaside 仍然是 sz*cnt 字節(jié)。但是空間是分配的 在小插槽 lookaside 和大槽 lookaside 之間,帶有 優(yōu)先考慮小插槽外觀??倲?shù) 插槽通常會超過“CNT”,因為“SZ”通常很多 大于 128 字節(jié)的小插槽大小。

默認后備配置已從 100 個插槽更改為 每個 1200 字節(jié) (120KB) 為 40 個插槽,每個插槽 1200 字節(jié) (48KB). 此空間最終被分配為 93 個插槽 每個 128 字節(jié)和 30 個插槽,每個插槽 1200 字節(jié)。所以更多的旁觀 插槽可用,但使用的堆空間要少得多。

默認的后備配置,小插槽的大小, 以及如何在小插槽之間分配堆空間的詳細信息 和大插槽,從一個版本到一個版本都可能發(fā)生變化。 下一個。

3.4.?內存狀態(tài)

默認情況下,SQLite 會保留有關其內存使用情況的統(tǒng)計信息。這些 統(tǒng)計數(shù)據(jù)有助于確定內存量 應用程序確實需要。統(tǒng)計數(shù)據(jù)也可用于 高可靠性系統(tǒng)確定 如果內存使用量接近或超過限制?的 Robson 證明,因此內存分配子系統(tǒng)為 容易發(fā)生故障。

大多數(shù)內存統(tǒng)計信息都是全局的,因此跟蹤 必須使用互斥鎖序列化統(tǒng)計信息。統(tǒng)計數(shù)據(jù)被翻轉 默認情況下處于打開狀態(tài),但存在禁用它們的選項。通過禁用 記憶統(tǒng)計, SQLite 避免在每個內存分配上輸入和保留互斥鎖 和解除分配。在以下系統(tǒng)上,這種節(jié)省可能很明顯 互斥操作成本高昂。要禁用內存統(tǒng)計信息,請 在啟動時使用以下接口:

sqlite3_config(SQLITE_CONFIG_MEMSTATUS, onoff);

“onoff”參數(shù)為 true 以啟用內存跟蹤 statistics 和 false 禁用統(tǒng)計信息跟蹤。

假設啟用了統(tǒng)計信息,則可以使用以下例程 要訪問它們,請執(zhí)行以下操作:

sqlite3_status(verb, &current, &highwater, resetflag);

“verb”參數(shù)確定訪問的統(tǒng)計信息。 定義了各種動詞。這 隨著?sqlite3_status()?接口的成熟,列表預計會增長。 所選參數(shù)的當前值寫入整數(shù) “當前”和最高歷史價值 寫入整數(shù)“highwater”。如果 resetflag 為 true,則 通話后,高水位線將重置為當前值 返回。

使用不同的接口來查找與 單一數(shù)據(jù)庫連接:

sqlite3_db_status(db, verb, &current, &highwater, resetflag);

此接口與此接口類似,只是它需要指向?數(shù)據(jù)庫連接作為其第一個參數(shù),并返回有關 一個對象,而不是整個SQLite庫。?sqlite3_db_status()?接口目前只能識別 單個動詞SQLITE_DBSTATUS_LOOKASIDE_USED,盡管是附加動詞 將來可能會添加。

每個連接的統(tǒng)計信息不使用全局變量,因此 不需要互斥鎖即可更新或訪問。因此, 即使SQLITE_CONFIG_MEMSTATUS連接處于關閉狀態(tài),每個連接的統(tǒng)計信息也會繼續(xù)運行。

3.5.?設置內存使用限制

sqlite3_soft_heap_limit64()?接口可用于設置 未完成內存總量的上限 SQLite的通用內存分配器將允許出色 一次。如果嘗試分配比指定更多的內存 根據(jù)軟堆限制,則SQLite將首先嘗試釋放緩存 內存,然后再繼續(xù)分配請求。軟堆 限制機制僅在啟用內存統(tǒng)計信息且 效果最好 如果 SQLite 庫是使用?SQLITE_ENABLE_MEMORY_MANAGEMENT?編譯時選項編譯的。

從這個意義上說,軟堆限制是“軟的”:如果 SQLite 無法 為了釋放足夠的輔助內存以保持在限制以下,它會去 提前并分配額外的內存并超出其限制。發(fā)生這種情況 根據(jù)使用額外內存比失敗更好的理論 徹底。

從SQLite版本3.6.1(2008-08-06)開始, 軟堆限制僅適用于 通用內存分配器。軟堆限制不知道 關于或與之互動?PageCache 內存分配器或?Lookaside 內存分配器。 此缺陷可能會在將來的版本中得到解決。

4.?針對內存分配失敗的數(shù)學保證

動態(tài)內存分配問題,特別是 內存分配器故障問題,已通過以下方式進行研究 J. M. Robson和結果發(fā)表為:

JM羅布森?!坝嘘P動態(tài)的某些函數(shù)的邊界 存儲分配“。 協(xié)會雜志 Computing Machinery,第 21 卷,第 8 期,1974 年 7 月, 第491-499頁。

讓我們使用以下表示法(類似于但不完全相同 羅布森的符號):

N內存分配系統(tǒng)所需的原始內存量 為了保證內存分配不會失敗。
M應用程序簽出的最大內存量 在任何時間點。
n最大內存分配與最小內存分配的比率。我們假設 每個內存分配大小都是最小內存的整數(shù)倍 分配大小。

羅布森證明了以下結果:

N?=? M*(1 + (log2? n)/2) -? n?+ 1

通俗地說,羅布森證明表明,為了保證 無故障操作,任何內存分配器都必須使用內存池 大小?N?超過有史以來的最大內存量 將?M?用一個乘數(shù),該乘數(shù)取決于?n, 最大與最小分配大小的比率。在其他 字,除非所有內存分配的大小完全相同 (n=1) 則系統(tǒng)需要訪問比實際更多的內存 一次性使用。此外,我們看到盈余的數(shù)量 所需的內存隨著最大與最小之比的快速增長而迅速增長 分配增加,因此有強烈的動機保留所有 分配盡可能接近相同的大小。

羅布森的證明是建設性的。 他提供了一種用于計算分配序列的算法 以及由于以下原因導致分配失敗的解除分配操作 內存碎片(如果可用) 內存多達一個字節(jié) 小于?N。 而且,Robson 展示了一個 2 次冪的首次擬合內存分配器 (例如由?memsys5?實現(xiàn))永遠不會使內存分配失敗 前提是可用內存為?N?個字節(jié)或更多字節(jié)。

值?M?和?n?是應用程序的屬性。 如果應用程序的構造方式是?M?和?n?都是已知的,或者至少具有已知的上限,并且如果 應用用途?memsys5?內存分配器,并提供?N?個字節(jié) 使用可用內存空間SQLITE_CONFIG_HEAP然后 Robson 證明沒有內存分配請求會失敗 在應用程序中。 換句話說,應用程序開發(fā)人員可以選擇一個值 對于?N,這將保證不調用任何 SQLite 接口 將永遠回到SQLITE_NOMEM。內存池永遠不會成為 如此碎片化,以至于無法滿足新的內存分配請求。 這是一個重要的屬性 軟件故障可能導致人身傷害、人身傷害或 丟失不可替代的數(shù)據(jù)。

4.1.?計算和控制參數(shù)?M?和?n

Robson 證明分別應用于每個內存分配器 SQLite使用:

  • 通用內存分配器 (memsys5)。
  • pagecache 內存分配器。
  • 后備內存分配器。

對于?memsys5?以外的分配器, 所有內存分配的大小都相同。因此,n=1 因此?N=M。換句話說,內存池需要 不大于任何給定時刻使用的最大內存量。

頁面緩存內存的使用在以下情況下更難控制 SQLite 版本 3.6.1,但計劃在隨后的 該版本將使控制頁面緩存內存變得更加容易。 在引入這些新機制之前,唯一的辦法 要控制 Pagecache,內存將使用?cache_size 編譯指示。

安全關鍵型應用程序通常需要修改 默認 Lookaside 內存配置,以便當初始 Lookaside 內存緩沖區(qū)在?sqlite3_open()?期間分配 生成的內存分配不會太大,以至于強制?n?參數(shù)過大。為了控制?n, 最好盡量將最大內存分配保持在 2 或 4 以下 千 字節(jié)。因此,后臺的合理默認設置 內存分配器可能是以下任一項:?

sqlite3_config(SQLITE_CONFIG_LOOKASIDE, 32, 32);  /* 1K */
sqlite3_config(SQLITE_CONFIG_LOOKASIDE, 64, 32);  /* 2K */
sqlite3_config(SQLITE_CONFIG_LOOKASIDE, 32, 64);  /* 2K */
sqlite3_config(SQLITE_CONFIG_LOOKASIDE, 64, 64);  /* 4K */

另一種方法是最初禁用后備內存 分配器:

sqlite3_config(SQLITE_CONFIG_LOOKASIDE, 0, 0);

然后讓應用程序維護一個單獨的池 Lookaside 內存緩沖區(qū),它可以在創(chuàng)建數(shù)據(jù)庫連接時將其分發(fā)給數(shù)據(jù)庫連接。在一般情況下,應用程序只會 具有單個數(shù)據(jù)庫連接,因此后備內存池 可以由單個大緩沖區(qū)組成。

sqlite3_db_config(db, SQLITE_DBCONFIG_LOOKASIDE, aStatic, 256, 500);

后備內存分配器的真正目的是提高性能 優(yōu)化,而不是作為確保無故障內存分配的方法, 因此,完全禁用后備內存并非沒有道理 用于安全關鍵操作的分配器。通用內存分配器是最困難的內存池 進行管理,因為它支持不同大小的分配。由于?n?是?M?上的乘數(shù),我們希望將 n?保持為小 盡可能。這主張將?memsys5?的最小分配大小保持在盡可能大的位置。在大多數(shù)應用中,后備內存分配器能夠處理少量分配。所以 將?memsys5?的最小分配大小設置為 2、4 甚至 8 倍于后備分配的最大大小。 最小分配大小 512 是一個合理的設置。

除了保持?n?小之外,人們還希望保持 受控的最大內存分配。 對通用內存分配器的大量請求 可能來自多個來源:

  1. 包含大字符串或 BLOB 的 SQL 表行。
  2. 編譯為大型預處理語句的復雜 SQL 查詢。
  3. sqlite3_prepare_v2()?內部使用的 SQL 解析器對象。
  4. 數(shù)據(jù)庫連接對象的存儲空間。
  5. 溢出到通用的頁面緩存內存分配 內存分配器。
  6. 為新數(shù)據(jù)庫連接分配的備用緩沖區(qū)。

最后兩個分配可以通過以下方式控制和/或消除 配置?pagecache 內存分配器, 并適當?shù)財R置內存分配器,如上所述。?數(shù)據(jù)庫連接對象所需的存儲空間取決于 在某種程度上取決于數(shù)據(jù)庫文件的文件名的長度,但是 在 32 位系統(tǒng)上很少超過 2KB。(需要更多空間 64 位系統(tǒng),因為指針的大小增加。 每個解析器對象使用大約 1.6KB 的內存。因此,元素 3 到 6 上面可以很容易地控制,以保持最大的內存分配 大小小于 2KB。

如果應用程序設計為管理小塊數(shù)據(jù), 則數(shù)據(jù)庫不應包含任何大型字符串或 BLOB 因此,上述要素 1 不應是一個因素。如果數(shù)據(jù)庫 確實包含大字符串或 BLOB,應使用增量 BLOB I/O?和包含 大字符串或 BLOB 不應通過任何其他方式進行更新 而不是增量 BLOB I/O。否則,sqlite3_step()?例程需要將整行讀入 在某個時候的連續(xù)內存,這將至少涉及 一個大內存分配。

大型內存分配的最終來源是要容納的空間 編譯復雜 SQL 生成的預準備語句?操作。SQLite開發(fā)人員正在進行的工作正在減少 此處所需的空間量。但是大型和復雜的查詢可能會 仍然需要幾千字節(jié)的預準備語句?大小。目前唯一的解決方法是讓應用程序 將復雜的 SQL 操作分解為兩個或更多更小、更簡單的操作 包含在單獨準備的語句中的操作。

考慮到所有因素,應用程序通常應該能夠 將其最大內存分配大小保持在 2K 或 4K 以下。這 給出對數(shù)2(n) 的值為 2 或 3。這將 將?N?限制為?M?的 2 到 2.5 倍。

應用程序所需的最大通用內存量 由應用程序同時打開數(shù)據(jù)庫連接和預準備語句對象的數(shù)量等因素決定 用途,以及準備好的語句的復雜性。對于任何 給定應用,這些因素通常是固定的,可以 使用SQLITE_STATUS_MEMORY_USED實驗確定。 一個典型的應用程序可能只使用大約 40KB 的通用 記憶。這給出的?N?值約為 100KB。

4.2.?延展性失效

如果配置了 SQLite 中的內存分配子系統(tǒng) 用于無擊穿操作,但實際內存使用量超過?由羅布森證明設定的設計極限,SQLite通常會繼續(xù) 才能正常運行。?pagecache 內存分配器和后備內存分配器自動故障轉移?到 Memsys5?通用內存分配器。它通常是?memsys5?內存分配器將繼續(xù)運行的情況 即使?M?和/或?n?超過限值也不會碎裂?由羅布森證明強加。羅布森證明表明它是 內存分配可能會中斷并在此過程中失敗 情況,但這樣的失敗需要特別 卑鄙的分配和解除分配序列 - 一個序列 從未觀察到 SQLite 跟隨。所以在實踐中通常是 羅布森施加的限制可以超出 相當大的利潤,沒有不良影響。

盡管如此,應用程序開發(fā)人員仍應進行監(jiān)控 內存分配子系統(tǒng)的狀態(tài),并在以下情況下發(fā)出警報 內存使用量接近或超過 Robson 限制。這樣, 該應用將為操作人員提供豐富的預警井 在失敗之前。 SQLite的內存統(tǒng)計接口為應用程序提供了 完成監(jiān)控部分所需的所有機制 這個任務。

5.?內存接口的穩(wěn)定性

更新:從SQLite版本3.7.0(2010-07-21)開始, 所有SQLite內存分配接口 被認為是穩(wěn)定的,并將在將來的版本中受支持。

http://www.risenshineclean.com/news/7829.html

相關文章:

  • 網(wǎng)頁設計與網(wǎng)站建設大作業(yè)友情鏈接搜讀
  • 網(wǎng)上購物app進一步優(yōu)化落實
  • 做網(wǎng)站開發(fā)需要什么證書重慶百度推廣關鍵詞優(yōu)化
  • 想做個ktv的網(wǎng)站怎么做網(wǎng)絡廣告策劃方案范文
  • 武漢市建設廳網(wǎng)站國內最新新聞摘抄
  • 微博推廣軟件網(wǎng)站的seo是什么意思
  • 電子請柬網(wǎng)站開發(fā)app推廣實名認證接單平臺
  • 政府網(wǎng)站頁面設計標準win10優(yōu)化大師怎么樣
  • 上海哪家網(wǎng)站建得好百度seo最成功的優(yōu)化
  • 福州外文網(wǎng)站建設網(wǎng)絡推廣平臺幾大類
  • 企業(yè)網(wǎng)站制作公司24小時接單seo sem
  • wordpress郵件模板seo實戰(zhàn)視頻
  • 服務器windos做網(wǎng)站整合營銷傳播方案
  • 家居網(wǎng)站建設全網(wǎng)營銷微信營銷軟件免費版
  • wordpress的cms插件山東進一步優(yōu)化
  • 校園網(wǎng)上超市網(wǎng)站建設推廣b站在線觀看人數(shù)在哪
  • 免費個人網(wǎng)站空間申請2023年10月疫情還會嚴重嗎
  • 網(wǎng)站建設7個基本流程寧波seo外包服務商
  • 如果在瀏覽器上做一網(wǎng)站廣告大約需要多少錢門戶網(wǎng)站排行榜
  • 什么樣的網(wǎng)站空間做電影網(wǎng)站不卡seo深圳網(wǎng)絡推廣
  • wordpress分享到qq空間班級優(yōu)化大師官方免費下載
  • 全屏網(wǎng)站怎么做網(wǎng)絡推廣運營推廣
  • 專業(yè)網(wǎng)站建設86215信息流優(yōu)化師是做什么的
  • 專業(yè)提供網(wǎng)站建設服務舉一個網(wǎng)絡營銷的例子
  • 沈陽全網(wǎng)推廣公司哪家好免費seo培訓
  • 網(wǎng)站后臺banner更換佛山seo關鍵詞排名
  • 做論壇網(wǎng)站時應該注意什么印度疫情最新消息
  • 為什么要用國外服務器做網(wǎng)站搜索引擎優(yōu)化英文簡稱為
  • 做網(wǎng)站找哪個軟件網(wǎng)店運營具體做什么
  • 海珠區(qū)疫情嚴重嗎鄭州seo代理外包