【Go】Map 的空間利用率統計

Go 中 map 利用率

今天刷 B 站看見有 Up 主在講布隆過濾器,提到了利用率的問題,假設有一組數據,范圍分布非常廣,使用布隆過濾器時如何盡量少的減少內存使用,感覺除了針對特定數據的定向優化外沒什么特別好的辦法,類似于 Google 那種加數據頭以跳過大段間隙那樣。然后想到類似的問題應該廣泛存在于所有使用哈希表的數據結構中,那 go 中 map 的利用率如何呢?

數據收集

在 go 中 map 是一個內置的數據結構,沒有一個簡單的方法來拿到它占用的內存,以下兩種方法供參考:

pprof

通過 pprof 定向收集內存分配和使用,我們可以直觀的得到某個函數占用了多少內存:

package main
import ("net/http"_ "net/http/pprof"
)func demo() {n := 90000m := make(map[int64]int64)for i := 0; i < n; i++ {m[int64(i)] = int64(i)}for {}
}func TestSize(t *testing.T) {go func() {http.ListenAndServe(":3390", nil)}()demo()
}

然后通過 go tool pprof -http :9090 http://127.0.0.1:3390/debug/pprof/heap 觀察 demo 的內存使用情況就可以了:

                                         2468.70kB   100% |   github.com/520MianXiangDuiXiang520/MapSize.TestSize /Users/junebao/Project/MapSize/mapsize_test.go:23 (inline)2468.70kB 40.77% 83.09%  2468.70kB 40.77%                | github.com/520MianXiangDuiXiang520/MapSize.demo /Users/junebao/Project/MapSize/mapsize_test.go:13

如上,我們就可以知道九萬個 int64 的鍵值對占用了 2468.70KB

上面的辦法簡單粗暴,但要統計起來很麻煩

unsafe

我們知道 map 的底層結構其實是 runtime_hmap 那通過 unsafe 理論上就可以強轉得到原始結構,只要知道了數據桶和溢出桶的個數,我們也可以計算出 map 的真實內存:

func Size[K comparable, V any](m map[K]V) int64 {var zeroK Kvar zeroValue VkeySize := unsafe.Sizeof(zeroK)valueSize := unsafe.Sizeof(zeroValue)vo := reflect.ValueOf(m)hm := (*hmap)(unsafe.Pointer(vo.Pointer()))bn := 1<<hm.B + uintptr(hm.noverflow)bz := unsafe.Sizeof(bmap{}) + (keySize+valueSize)*bucketCntreturn int64(unsafe.Sizeof(hmap{}) + bz*bn)
}

這個方法的缺點在于數值不精確,一來是 noverflow 是一個統計值,某些情況下可能會導致得到的溢出桶數量略小于真實數量,二來 bmap 中的 overflow 指針會根據鍵值對的類型有所變化,上面的程序中并沒有計算該字段,因為鍵值對都不包含指針,理論上 map 會使用 hmap 的拓展字段存儲溢出指針,總體來說該方法得到的值會小于真實值,但作為參考足夠。如同樣的九萬個鍵值對使用上面方法得到的大小是 2457.976KB 比 pprof 版本少了 11KB

統計

func main() {for i := 0; i < 1000; i++ {n := i * 100m := make(map[int64]int64)for i := 0; i < n; i++ {m[int64(i)] = int64(i)}res := Size(m)t := int64(16 * n)fmt.Printf("%d,%d,%d,%d,%f\n", n, res, t, res-t, float64(t)/float64(res))}
}

以 100 為 步幅測試一千組用例,導入 CSV 用 python 繪制出圖表:

import matplotlib.pyplot as plt
import csvclass MapSizeStatistic:"""A statistic of map storage usage in go where key-value pairs are all int64"""def __init__(self):self.utilization_list = []with open("./int64.csv") as fp:reader = csv.reader(fp)self.utilization_list = [float(i[-1]) for i in reader]print(self.utilization_list)def draw_utilization(self):x = [i*100 for i in range(len(self.utilization_list))]plt.plot(x, self.utilization_list)plt.show()if __name__ == '__main__':mss = MapSizeStatistic()mss.draw_utilization()

結果如下:

將鍵全部使用隨機數,得到結果如下:

幾乎沒有差別,周期性變化非常明顯,可以確定引起利用率變化的主要原因在于元素數量,而利用率突然降低的節點就是發生了等量擴容。

從上面的測試可以看到最高利用率在 0.8 左右,最低利用率只有 0.4, 平均只有 0.5 左右

總結

總體利用率在 50% 左右,主要影響因素在于等量擴容,雖然 map 本就是空間換時間,但如果確實需要優化并且走投無路時,希望這些數據或許可以提供一些參考(分片,卡利用率的點……)

最后放上一張合影:

代碼

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

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

相關文章

ap模式和sta模式共存_AP+AC組網下的本地轉發及集中轉發

現在越來越多的企業都有自己的無線網絡&#xff0c;而無線網絡的組網方式一般都是使用ACAP模式進行組網&#xff0c;使用無線網絡能夠提供經濟、高效的網絡接入方式。相比有線網絡&#xff0c;無線網絡下只要能接入無線網的地方都可以使用網絡&#xff0c;用戶可以自由移動。而…

《JS權威指南學習總結--6.7屬性的特性》

內容要點&#xff1a; 一.ES5中查詢和設置屬性的API 1.可以通過這些API給原型對象添加方法&#xff0c;并將它們設置成不可枚舉的&#xff0c;這讓它們看起來更像內置方法。 2.可以通過這些API給對象定義不能修改或刪除的屬性&#xff0c;借此 "鎖定" 這個對象。 3.數…

【干貨分享】流程DEMO-事務呈批表

流程名&#xff1a; 事務呈批表 業務描述&#xff1a; 辦公采購、會議費用等事務的申請。流程發起時&#xff0c;會檢查預算&#xff0c;如果預算不夠&#xff0c;將不允許發起費用申請&#xff0c;如果預算夠用&#xff0c;將發起流程&#xff0c;同時占用相應金額的預算&…

【譯】TcMalloc: Thread-Caching Malloc

TcMalloc 的核心是分層緩存&#xff0c;前端沒有鎖競爭&#xff0c;可以快速分配和釋放較小的內存對象&#xff08;一般是 256 KB&#xff09;前端有兩種實現&#xff0c;分別是 pre-CPU 和 pre-Thread 模式&#xff0c;前者申請一塊大的連續內存&#xff0c;每一個邏輯 CPU 將…

kotlin編譯失敗_Kotlin使用GraalVM開發原生命令行應用

背景之前用kotlin開發過一款根據建表DDL語句生成plantuml ER圖的應用。被問如何使用&#xff0c;答曰"給你一個jar包&#xff0c;然后執行java -jar ddl2plantuml.jar ./ddl.sql ./er.puml 就可以了。是不是so easy?"結果被吐槽了一番&#xff0c;為什么不能像命令行…

Swift - 添加純凈的Alamofire

Swift - 添加純凈的Alamofire 如果你有代碼潔癖,不能容忍任何多余的東西,請繼續往下看. 1. 下載Alamofire (https://github.com/Alamofire/Alamofire) 2. 解壓縮并打開 Alamofire.xcworkspace 3. 刪除不必要的內容 (根據你的需求自己定) 4. 順便把文件夾里面的無關內容也刪除掉…

jquery 獲取系統默認年份_你沒有看錯,爬網頁數據,C# 也可以像 Jquery 那樣

一&#xff1a;背景1. 講故事前段時間搞了一個地方性民生資訊號&#xff0c;資訊嘛&#xff0c;都是我抄你的&#xff0c;你抄官媒的&#xff0c;小市民都喜歡奇聞異事&#xff0c;所以就存在一個需求&#xff0c;如何去定向抓取奇聞異事的地方號上的新聞&#xff0c;其實做起來…

linux下怎么編譯運行C語言程序?

linux下的C語言編譯器是gcc&#xff0c;C的編譯器是g。 linux下編程可以使用編輯器vi或vim&#xff0c;建議使用vim&#xff0c;因為它有語法高亮顯示。程序編寫好后&#xff0c;假設你的程序名為test.c&#xff0c;可以使用gcc -o test test.c。test就是編譯好的可執行程序./t…

undertow 怎么創建線程_為什么很多SpringBoot開發者放棄了Tomcat,選擇了Undertow

點擊上方“后端技術精選”&#xff0c;選擇“置頂公眾號”技術文章第一時間送達&#xff01;作者&#xff1a;阿邁達toutiao.com/a6775476659416990212/前言在SpringBoot框架中&#xff0c;我們使用最多的是Tomcat&#xff0c;這是SpringBoot默認的容器技術&#xff0c;而且是內…

一起玩轉CoordinatorLayout

作為Material Design風格的重要組件,CoordinatorLayout協調多種組件的聯動&#xff0c;實現各種復雜的效果&#xff0c;在實際項目中扮演著越來越重要的角色。本篇博客將由淺到深&#xff0c;帶你一起玩轉CoordinatorLayout。 官方文檔對CoordinatorLayout是這樣描述的&#xf…

離散數學圖論旅行規劃問題_2020年MathorCup高校數學建模挑戰賽——C 題 倉內揀貨優化問題...

下面的鏈接是精華版思路&#xff0c;亮點是對第六問的探討。高度概括一下&#xff1a;第一問曼哈頓&#xff0c;第二問用免疫&#xff0c;三問增加任務單&#xff0c;四問增加揀貨員&#xff0c;五問改變復核臺&#xff0c;六問亮點來探討~ 有點皮MathorCup C題 倉內揀貨優化問…

Asp.NetWebForm的控件屬性

一&#xff1a;GridView&#xff1a; 1.綁定ID 的值&#xff1a;DataKeyNames"Id", 2.自動產生列的意思:AutoGenerateColumns 3.如何注冊腳本&#xff1a;ClientScript.RegisterStartupScript(this.GetType(),"text","alert(刪除成功)"&#xf…

【VBA編程】10.自定義集合

自定義集合類型&#xff0c;類似于變量聲明&#xff0c;只是要將Dim關鍵字和New collection關鍵字搭配起來使用&#xff0c;其語法描述如下&#xff1a;其中集合名的命名方式同于標準變量的命名 Dim 集合名 As New collection 對于已經定義的集合對象&#xff0c;可以使用集合的…

git fork clone 區別_Working with Git | Git 與 GitHub

關于各位好&#xff0c;這里是 Chinas Prices Project 項目的知乎專欄。關于 CPP 項目&#xff0c;您可以在這篇文章里了解到更多的信息。若您對這個項目感興趣&#xff0c;我們非常歡迎您與我們交流您的想法與見解。在一個團隊的成員同時為一個項目進行開發工作時&#xff0c;…

舒適的路線(codevs 1001)

題目描述 DescriptionZ小鎮是一個景色宜人的地方&#xff0c;吸引來自各地的觀光客來此旅游觀光。Z小鎮附近共有N(1<N≤500)個景點&#xff08;編號為1,2,3,…,N&#xff09;&#xff0c;這些景點被M&#xff08;0<M≤5000&#xff09;條道路連接著&#xff0c;所有道路都…

PHP_Smarty

模板 數據與表現層的標簽分離 smarty是PHP 與 HTML代碼的分離 小型模板類 $smarty 的工作流程&#xff1a; 把需要顯示的全局變量&#xff0c;賦值塞到對象內部的屬性上&#xff0c;一個數組中.編譯模板&#xff0c;把{$標簽},解析成相應的<?php echo 代碼引入編譯后的PHP文…

讀中文_挑戰來了!康輝喊你讀中文十級繞口令!

文章來源&#xff1a;央視頻漢語橋木甬讀桶不讀涌&#xff0c;月農讀膿不讀朧。米更讀粳不讀梗&#xff0c;日青讀晴不讀睛。米宗讀粽不讀綜&#xff0c;言丁讀訂不讀釘。土竟讀境不是鏡&#xff0c;土平讀坪不是評。耳令讀聆不讀嶺&#xff0c;火登讀燈不讀澄。言甬讀誦不讀蛹…

ios 自定義鍵盤

由于項目需要&#xff0c;需要自定義鍵盤。ios系統鍵盤會緩存鍵盤輸入&#xff0c;并保存在系統目錄下的文件里&#xff0c;并且是明文存儲&#xff0c;存在帳號密碼泄漏風險。在別人代碼基礎上修改了下&#xff0c;美化了下界面&#xff0c;去掉了字符輸入&#xff0c;加了點擊…

對象入參指定泛型類型_為什么要使用泛型,而不是直接將類型作為參數傳遞?

其實很多類型系統都是用類型參數的的形式來實現Universal Type的&#xff0c;Parametric Polymorphism 和System F可以了解一下&#xff0c;如果只局限于一兩個熱門語言的話&#xff0c;可能會有此疑問&#xff0c;但是從type theory的角度來說&#xff0c;高階類型本身就是typ…

【GOF23設計模式】迭代器模式

【GOF23設計模式】迭代器模式 來源&#xff1a;http://www.bjsxt.com/ 一、【GOF23設計模式】_迭代器模式、JDK內置迭代器、內部類迭代器 1 package com.test.iterator;2 /**3 * 自定義的迭代器接口4 */5 public interface MyIterator {6 void first(); //將游標指向第…