map的容量的获取
在go语言中,有两个内建函数分别是len(),cap(),前者用于获取容器的具体内容个数,后者用于获取容器分配的容量大小,但是这个cap对象是不能获取到map具体分配的容量大小的。有没有办法获取到呢,办法是有的,且看下文。
首先我们先使用gdb调试工具,查看一下map对象的具体结构是什么样子的。
一个及其简单的代码如下:
package main
func main() {
m := make(map[string]int)
m["a"] = 1
m["b"] = 2
}
接下来我们编译这个简单的代码,并进行调试
# go build -o test -gcflags="-N -l" main.go 这里goflags是编译时指定的参数, -N 表示禁止优化,-l表示禁止内联。 便于调试
使用gdb进行调试
# gdb test
(gdb) b main.main
Breakpoint 1 at 0x401000: file /media/sf_goproject/src/map.go, line 3.
(gdb) r # 开始运行
Starting program: /media/sf_goproject/src/test
(gdb) n
m := make(map[string]int)
(gdb) ptype mtype = struct hash<string, int> {
int count;
uint8 flags;
uint8 B;
uint32 hash0;
struct bucket<string, int> *buckets;
struct bucket<string, int> *oldbuckets;
uintptr nevacuate;
[2]*[]*runtime.bmap *overflow;
} *
从上面的调试可以看到map对象的数据结构,在golang的runtime包的的haspmap.go中有这个结构的详细介绍:
// A header for a Go map.
type hmap struct {
// Note: the format of the Hmap is encoded in ../../cmd/internal/gc/reflect.go and
// ../reflect/type.go. Don't change this structure without also changing that code!
count int // # live cells == size of map. Must be first (used by len() builtin)
flags uint8
B uint8 // log_2 of # of buckets (can hold up to loadFactor * 2^B items)
hash0 uint32 // hash seed
buckets unsafe.Pointer // array of 2^B Buckets. may be nil if count==0.
oldbuckets unsafe.Pointer // previous bucket array of half the size, non-nil only when growing
nevacuate uintptr // progress counter for evacuation (buckets less than this have been evacuated)
// If both key and value do not contain pointers and are inline, then we mark bucket
// type as containing no pointers. This avoids scanning such maps.
// However, bmap.overflow is a pointer. In order to keep overflow buckets
// alive, we store pointers to all overflow buckets in hmap.overflow.
// Overflow is used only if key and value do not contain pointers.
// overflow[0] contains overflow buckets for hmap.buckets.
// overflow[1] contains overflow buckets for hmap.oldbuckets.
// The first indirection allows us to reduce static size of hmap.
// The second indirection allows to store a pointer to the slice in hiter.
overflow *[2]*[]*bmap
}
所以B代表了map的容量 既然我们知道了数据的的结构,便可根据结构得到容量的内容。代码示例如下。
package main
type hmap struct {
count int
flags uint8
B uint8
hash0 uint32
buckets unsafe.Pointer
oldbuckets unsafe.Pointer
}
func main() {
m := make(map[string]string)
c, b := getInfo(m)
fmt.Println("count: ", c, "b: ", b)
for i := 0; i < 10000; i++ {
m[strconv.Itoa(i)] = strconv.Itoa(i)
if i%200 == 0 {
c, b := getInfo(m)
cap := math.Pow(float64(2), float64(b))
fmt.Printf("count: %d, b: %d, load: %f\n", c, b, float64(c)/cap)
}
}
println("开始删除------")
for i := 0; i < 10000; i++ {
delete(m, strconv.Itoa(i))
if i%200 == 0 {
c, b := getInfo(m)
cap := math.Pow(float64(2), float64(b))
fmt.Println("count: ", c, "b:", b, "load: ", float64(c)/cap)
}
}
debug.FreeOSMemory()
c, b = getInfo(m)
fmt.Println("释放后: ", "count: ", c, "b:", b)
}
func getInfo(m map[string]string) (int, int) {
point := (**hmap)(unsafe.Pointer(&m))
value := *point
return value.count, int(value.B)
}
一些记录:
1. 在看许多文章中有说到map分配的键值被删除之后,内存是不会释放的。但是在我测试的过程中,发现内存是可以释放的。可能是版本的原因,测试的版本是1.7.1
2. map是非并发安全的,使用过程中需要自己去控制加锁。
map的容量的获取的更多相关文章
- 在map中根据value获取key
原文:http://blog.csdn.net/mexican_jacky/article/details/51789548 //根据map的value获取map的key private static ...
- map中根据value获取key
public static String getKeyByValue(Map map, Object value) { String keys=""; Iterator it = ...
- java map遍历、排序,根据value获取key
Map 四种遍历: Map<String,String> map = new HashMap<String, String>(); map.put("one" ...
- java里面获取map的key和value的方法
获取map的key和value的方法分为两种形式: map.keySet():先获取map的key,然后根据key获取对应的value: map..entrySet():同时查询map的key和val ...
- Map四种获取key和value值的方法,以及对map中的元素排序(转)
获取map的值主要有四种方法,这四种方法又分为两类,一类是调用map.keySet()方法来获取key和value的值,另一类则是通过map.entrySet()方法来取值,两者的区别在于,前者主要是 ...
- C++ map通过key获取value
c++的map中通过key获取value的方法 一般是value =map[key],或者另一种迭代器的方式 1.在map中,由key查找value时,首先要判断map中是否包含key. 2.如果不 ...
- cocos基础教程(5)数据结构介绍之cocos2d::Map<K,V>
1.概述 cocos2d::Map<K,V> 是一个内部使用了 std::unordered_map的关联容器模版. std::unordered_map 是一个存储了由key-value ...
- ceph之crush map
编辑crush map: 1.获取crush map: 2.反编译crush map: 3.至少编辑一个设备,桶, 规则: 4.重新编译crush map: 5.重新注入crush map: 获取cr ...
- Map笔记
Map,是一个接口,是以键值对的方式存储的,并且键是无序且不可重复的.Map和Collection没有什么关系,Map是一对一对的存,而Collection是一个一个的存. 下面有一个子接口:Sort ...
随机推荐
- ADALINE小demo
线性逼近 clear;clc;close all x = [1,0.5; 1.5,1.1; 3,3; -1.2,-1]; y = x(:,2); x = [ones(size(x,1),1),x(:, ...
- POJ1065--Wooden Sticks(动态规划)
There is a pile of n wooden sticks. The length and weight of each stick are known in advance. The st ...
- java后台技术
本文旨在梳理服务端开发技术栈,希望帮助后端开发同学更全面了解Java服务端主要涉及的知识点 1. 语言相关 1.1 Java 核心知识点 Java的类加载机制 JVM相关:JVM内存模型和结构,GC原 ...
- kosaraju算法
这个是求一个图有几个强联通分量的算法 先讲一下应该流程 首先输入一个图G,创建一个反向的图GT 图G 对图进行dfs遍历,纪录每个点结束搜索的时间p[i] p[1]=2 p[2]=1 p[3]=5 ...
- hdu 5055
http://acm.hdu.edu.cn/showproblem.php?pid=5055 n个digit能组合出的最大无前导0奇数 无聊的模拟 #include <cstdio> #i ...
- shell工具-sort
sort sort命令是在Linux里非常有用,它将文件进行排序,并将排序结果标准输出 基本语法 sort [选项] [参数] 选项说明 选项 说明 -n 依照数值大小排序 -r 以相反的顺序排序 - ...
- 关于synchronized和lock 的使用及其在线程间的通信
题目要求:子线程循环10次,接着主线程循环100次,接着又回到子线程循环10次,接着再回到主线程又循环100,如此循环50次 synchronized的使用 import java.util.conc ...
- 论文笔记(1)-Dropout-Improving neural networks by preventing co-adaptation of feature detectors
Improving neural networks by preventing co-adaptation of feature detectors 是Hinton在2012年6月份发表的,从这篇文章 ...
- 第5件事 做一个有taste的产品人
1.taste的意思是品位,也就是说产品经理应该是一个有品位的产品人.什么叫品位呢?品位指的是对事物有分辨与鉴赏的能力.品位是形象的展示,品位是内在气质的复出,品位是人生价值的体验,品位是道德修养的内 ...
- android.os.NetworkOnMainThreadException的解决方案
06-24 18:04:36.857: E/AndroidRuntime(22251): FATAL EXCEPTION: main 06-24 18:04:36.857: E/AndroidRunt ...