15- Redis 中的 整數集合 數據結構

整數集合是 Set 對象的底層實現之一。當一個 Set 對象只包含整數值元素,并且元素數量不大時,就會使用整數集合這個數據結構作為底層實現。

1. 整數集合結構設計

整數集合本質上是一塊連續內存空間,它的結構定義如下:

typedef struct intset {// 編碼方式uint32_t encoding;// 集合包含的元素數量uint32_t length;// 保存元素的數組int8_t contents[];
} intset;

可以看到,保存元素的容器是一個 contents 數組,雖然 contents 被生命為 int8_t 類型的數組,但是實際上 contents 數組并不保存任何 int8_t 類型的元素,contents 數組的真正類型取決于 intset 結構體里的 encoding 屬性的值。比如:

  • 如果 encoding 屬性值為 INTSET_ENC_INT16,那么 contents 就是一個 int16_t 類型的數組,數組中每一個元素的類型都是 int16_t;

  • 如果 encoding 屬性值為 INTSET_ENC_INT32,那么 contents 就是一個 int32_t 類型的數組,數組中每一個元素的類型都是 int32_t;

  • 如果 encoding 屬性值為 INTSET_ENC_INT64,那么 contents 就是一個 int64_t 類型的數組,數組中每一個元素的類型都是 int64_t;

不同類型的 contents 數組,意味著數組的大小也會不同。

2. 整數集合的升級操作

整數集合會有一個升級規則,就是當我們將一個新元素加入到整數集合里面,如果新元素的類型(int32_t)比整數集合現有所有元素的類型(int16_t)都要長時,整數集合需要先進行升級,也就是按新元素的類型(int32_t)擴展 contents 數組的空間大小,然后才能將新元素加入到整數集合里,當然升級的過程中,也要維持整數集合的有序性。

為什么管理混合類型會增加復雜度:

從計算機的基本原理來看,int16_tint32_t 在內存中的占用大小、表達范圍以及在某些情況下的處理方式上存在區別,這些區別導致了在處理它們時的一些差異。在數據結構內部同時管理 int16_tint32_t 類型的數據,意味著每次操作數據(如添加、刪除、查找)時,都需要判斷并根據不同的類型作相應處理。這不僅在編碼時增加了分支判斷的復雜度,還可能導致在執行時增加額外的判斷開銷。此外,混合類型的數據存儲可能導致內存布局的非連續性和對齊問題,進而影響訪問效率。

因此,雖然 int16_tint32_t 在概念上是相似的(都是用來存儲整數的類型),但它們在內存占用、表達范圍和處理細節上的這些區別,決定了在統一的數據結構中同時管理這些不同類型會使得結構管理變得更加復雜。Redis 的整數集合通過類型升級來避免這種復雜性,從而使得數據存儲、訪問和維護更加高效和一致。

整數集合升級的過程不會重新分配一個新類型的數組,而是在原本的數組上擴展空間,然后再將每個元素按間隔類型大小分割,如果 encoding 屬性值為 INTSET_ENC_INT16,則每個元素的間隔就是 16 位。

舉個例子,假設有一個整數集合里有 3 個類型為 int16_t 的元素。

現在,往這個整數集合中加入一個新元素 65535,這個新元素需要用 int32_t 類型來保存,所以整數集合要進行升級操作,首先需要為 contents 數組擴容,在原本空間的大小上再擴容多 80 位(4 × 32 - 3 × 16 = 80),這樣就能保存下四個類型為 int32_t 的元素

擴容完 contents 數組空間大小后,需要將之前的三個元素轉換為 int32_t 類型,并將轉換后的元素放置到正確的位上面,并且需要維持底層數組的有序性不變,整個轉換過程如下:

整數集合升級有什么好處呢?

如果要讓一個數組同時保存 int16_t、int32_t、int64_t 類型的元素,最簡單的做法就是直接使用 int64_t 類型的數組。不過這樣的話,當如果元素都是 int16_t 類型的,就會造成內存浪費的情況。

整數集合升級就能避免這種情況,如果一直向整數集合添加 int16_t 類型的元素,那么整數集合的底層實現就一直是用 int16_t 類型的數組,只有在我們要將 int32_t 類型或 int64_t 類型的元素添加到集合時,才會對數組進行升級操作。

因此,整數集合升級的好處是節省內存資源

整數集合支持降級操作嗎?

不支持降級操作,一旦對數組進行了升級,就會一直保持升級后的狀態。比如前面的升級操作的例子,如果刪除了 65535 元素,整數集合的數組還是 int32_t 類型的,并不會因此降級為 int16_t 類型。

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

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

相關文章

Chrome DevTools 使用攻略

Chrome DevTools是谷歌瀏覽器提供的一套強大的開發工具,對于前端開發人員來說是不可或缺的利器。下面將從多個方面介紹Chrome DevTools的使用攻略: 一、啟動方式 通過快捷鍵: 在Windows/Linux上,按下 F12、Ctrl Shift I 或 C…

集成學習筆記

集成學習 簡介 決策樹 GBDT 擬合殘差 一般 GBDT XGBOOST 弓 1 能表達樣本落入的子節點,但是不能把表示結構 2 3.正則項 – 懲罰 防止過擬合,比如一個值總共有10顆樹都是由同一顆樹決定的,過擬合 5 找到一種方式不依賴于損失函數 …

Android開發之內訪Sqlite數據庫(六)

文章目錄 1. Android開發之外訪Sqlite數據庫1.1 Sqlite數據庫的優點1.2 Sqlite接口簡介接口中的抽象方法接口中的實例方法接口的構造方法示例步驟例子 —— 實現增刪改查 1. Android開發之外訪Sqlite數據庫 SQLite是一個軟件庫,實現了自給自足的、無服務器的、零配…

python的優勢有哪些?

python的優點很多,下面簡單地列舉一些: 簡單 Python的語法非常優雅,甚至沒有像其他語言的大括號,分號等特殊符號,代表了一種極簡主義的設計思想。閱讀Python程序像是在讀英語。 易學 Python入手非常快,學習…

K8s:無狀態

無狀態服務 無狀態服務是指服務的實例之間沒有持久化狀態,每個實例都是相同的,可以互換使用。 調度器 ReplicationController 簡稱 RC是 Kubernetes 早期版本中用來確保 Pod 副本始終運行的 API 對象。它通過監控 Pod 副本的數量,確保任何…

vue 常用的 UI 框架及表格

vue 3 常用的 UI 框架及表格 常用 UI 框架 Element PlusAnt Design VueiViewVxe UIVuetifyBootstrap VueMuse UI 專業表格 SpreadJSAG GridVxe Table

Linux——內存管理代碼分析

虛空間管理 頁框和頁的關系 頁框 將內存空間分為一個個大小相等的分區(比如:每個分區4KB),每個分區就是一個頁框,也叫頁幀,即物理頁面,是linux劃分內存空間的結果。 每個頁框都有一個頁框號,即內存塊號、物理塊號。 頁 將用戶…

深度學習之指數移動平均模型(EMA)介紹

指數移動平均模型(Exponential Moving Average Model,EMA)是一種用于平滑時間序列數據的技術。它通過對數據進行加權平均來減少噪音和波動,從而提取出數據的趨勢。 在深度學習中,EMA 常常用于模型的參數更新和優化過程…

完整指南:遠程管理 Linux 服務器的 Xshell6 和 Xftp6 使用方法(Xshell無法啟動:要繼續使用此程序........,的解決方法)

😀前言 在當今軟件開發領域,遠程管理 Linux 服務器已成為日常工作的重要組成部分。隨著團隊成員分布在不同的地理位置,遠程登錄工具的使用變得至關重要,它們為開發人員提供了訪問和管理服務器的便捷方式。本文將介紹兩款功能強大的…

python隨機顯示四級詞匯 修改版直接顯示釋義

python隨機顯示四級詞匯 修改版直接顯示釋義 添加暫停 和繼續(按下中建滾輪觸發) 按下右鍵 退出程序 解決在暫停后 ,重新調用update_word 會明顯發現每隔5秒更新一次單詞的速率已經改變 速率改變的問題可能是由于暫停期間沒有清除之前的定時器所導致的。為了確保重新調用updat…

Linux高級進階-ssh配置

Ubuntu-system 允許使用root遠程登陸 apt install ssh -y在/etc/ssh/sshd_config 文件修改PermitRootLogin yes systemctl restart ssh遠程連接軟件用戶名為root

Ubuntu系統中Apache Web服務器的配置與實戰

?? 歡迎大家來訪Srlua的博文(づ ̄3 ̄)づ╭?~?? 🌟🌟 歡迎各位親愛的讀者,感謝你們抽出寶貴的時間來閱讀我的文章。 我是Srlua小謝,在這里我會分享我的知識和經驗。&am…

Educational Codeforces Round 166(Div.2) A~D

A.Verify Password(字符串) 題意: Monocarp正在開發他的新網站,目前面臨的挑戰是如何讓用戶選擇強密碼。 Monocarp認為,強密碼應滿足以下條件: 密碼只能由小寫拉丁字母和數字組成;字母后面不…

PasteCode系列系統說明

定義 PasteCode系列是指項目是基于PasteTemplate構建的五層以上項目,包括不僅限于 Domain EntityFrameworkCore Application.Contracts Application HttpApi.Host 熟悉ABP vNext就很好理解了,因為PasteTemplate就是基于ABP的框架精簡而來!在…

一些Mysql面試題

InnoDB是如何存儲數據的? InnoDB 的數據是按「數據頁」為單位來讀寫的,默認數據頁大小為 16 KB。每個數據頁之間通過雙向鏈表的形式組織起來,物理上不連續,但是邏輯上連續。 數據頁內包含用戶記錄,每個記錄之間用單向…

【java 如何將字符串反轉?】

文章目錄 概要示例(1)使用StringBuilder的reverse方法(2)使用charAt和循環(3)使用雙指針(4)使用遞歸 總結 概要 在Java中,有多種方法可以將字符串反轉,我這里…

代碼隨想錄訓練營第二天 977有序數組的平方 209長度最小的子數組 59螺旋矩陣II

第一題: 題目鏈接:977. 有序數組的平方 - 力扣(LeetCode) 思路: 先將數組求完平方和后進行排序,很簡單,主要是排序算法的考察。 這里采用快排 快排的思路: 取這個數組的中間值…

代碼隨想錄算法訓練營第四十六 | ● 139.單詞拆分 ● 關于多重背包,你該了解這些! ● 背包問題總結篇!

139.單詞拆分 視頻講解&#xff1a;https://www.bilibili.com/video/BV1pd4y147Rh https://programmercarl.com/0139.%E5%8D%95%E8%AF%8D%E6%8B%86%E5%88%86.html class Solution { public:bool wordBreak(string s, vector<string>& wordDict) {unordered_set<st…

java stream流之groupby的用法

簡單分組 按照年齡對 Person 對象進行分組&#xff1a; 代碼示例 import java.util.*; import java.util.stream.Collectors;public class SimpleGrouping {public static void main(String[] args) {List<Person> people Arrays.asList(new Person("Alice"…

上市即交付,比亞迪秦L DM-i萬人交車暨千媒眾測開營

6月6日&#xff0c;“引領中級 開創油耗2時代”秦L DM-i萬人交車暨千媒眾測開營儀式在比亞迪大本營深圳盛大舉行。 眾多車主代表親臨現場&#xff0c;與全國各地的比亞迪4S店千店聯動&#xff0c;將秦L DM-i全國交付推向新的高潮。發布即量產&#xff0c;上市即交付&#xff0…