map简单的问题

来源:1-9 神奇的内置数据结构

shy_login

2021-05-29 10:47:10

​如果申请一个大小为20的map,会分配几个bucket?源码定义每个bucket大小为8;是buckets数组会有4个bucket?(2的幂次 20->32)所以B是2吗?不太理解  谢谢老师

相关截图:

http://img.mukewang.com/climg/60b1a94e09b1e36207850139.jpg

http://img.mukewang.com/climg/60b1aa1509c389cc13270513.jpg

写回答

2回答

Xargin

2021-05-29

你理解的没问题,所以接下来你需要的只是调试:

~/test git:master ❯❯❯ cat map.go                                                                                                       ✱ ◼
package main

func main() {
var m = make(map[int]int, 20)
println(m)
}


~/test git:master ❯❯❯ cat map.go ✱ ◼
package main

func main() {
var m = make(map[int]int, 20)
println(m)
}
~/test git:master ❯❯❯ dlv debug map.go ✱ ◼
Type 'help' for list of commands.
(dlv) b main.main
Breakpoint 1 set at 0x105edbf for main.main() ./map.go:3
(dlv) c
> main.main() ./map.go:3 (hits goroutine(1):1 total:1) (PC: 0x105edbf)
1: package main
2:
=> 3: func main() {
4: var m = make(map[int]int, 20)
5: println(m)
6: }
(dlv) disass
TEXT main.main(SB) /Users/xargin/test/map.go
map.go:3 0x105edb0 65488b0c2530000000 mov rcx, qword ptr gs:[0x30]
map.go:3 0x105edb9 483b6110 cmp rsp, qword ptr [rcx+0x10]
map.go:3 0x105edbd 767a jbe 0x105ee39
=> map.go:3 0x105edbf* 4883ec60 sub rsp, 0x60
map.go:3 0x105edc3 48896c2458 mov qword ptr [rsp+0x58], rbp
map.go:3 0x105edc8 488d6c2458 lea rbp, ptr [rsp+0x58]
map.go:4 0x105edcd 0f57c0 xorps xmm0, xmm0
map.go:4 0x105edd0 0f11442428 movups xmmword ptr [rsp+0x28], xmm0
map.go:4 0x105edd5 0f57c0 xorps xmm0, xmm0
map.go:4 0x105edd8 0f11442438 movups xmmword ptr [rsp+0x38], xmm0
map.go:4 0x105eddd 0f57c0 xorps xmm0, xmm0
map.go:4 0x105ede0 0f11442448 movups xmmword ptr [rsp+0x48], xmm0
map.go:4 0x105ede5 488d0534c60000 lea rax, ptr [rip+0xc634]
map.go:4 0x105edec 48890424 mov qword ptr [rsp], rax
map.go:4 0x105edf0 48c744240814000000 mov qword ptr [rsp+0x8], 0x14
map.go:4 0x105edf9 488d442428 lea rax, ptr [rsp+0x28]
map.go:4 0x105edfe 4889442410 mov qword ptr [rsp+0x10], rax
map.go:4 0x105ee03 e8a8d4faff call $runtime.makemap
map.go:4 0x105ee08 488b442418 mov rax, qword ptr [rsp+0x18]
map.go:4 0x105ee0d 4889442420 mov qword ptr [rsp+0x20], rax
map.go:5 0x105ee12 e83900fdff call $runtime.printlock
map.go:5 0x105ee17 488b442420 mov rax, qword ptr [rsp+0x20]
map.go:5 0x105ee1c 48890424 mov qword ptr [rsp], rax
map.go:5 0x105ee20 e82b09fdff call $runtime.printpointer
map.go:5 0x105ee25 e8b602fdff call $runtime.printnl
map.go:5 0x105ee2a e8a100fdff call $runtime.printunlock
map.go:6 0x105ee2f 488b6c2458 mov rbp, qword ptr [rsp+0x58]
map.go:6 0x105ee34 4883c460 add rsp, 0x60
map.go:6 0x105ee38 c3 ret
map.go:3 0x105ee39 e8029dffff call $runtime.morestack_noctxt
<autogenerated>:1 0x105ee3e e96dffffff jmp $main.main
(dlv) b makemap
Breakpoint 2 set at 0x100c2c3 for runtime.makemap() /usr/local/go/src/runtime/map.go:303
(dlv) c
> runtime.makemap() /usr/local/go/src/runtime/map.go:303 (hits goroutine(1):1 total:1) (PC: 0x100c2c3)
Warning: debugging optimized function
298: // makemap implements Go map creation for make(map[k]v, hint).
299: // If the compiler has determined that the map or the first bucket
300: // can be created on the stack, h and/or bucket may be non-nil.
301: // If h != nil, the map can be created directly in h.
302: // If h.buckets != nil, bucket pointed to can be used as the first bucket.
=> 303: func makemap(t *maptype, hint int, h *hmap) *hmap {
304: mem, overflow := math.MulUintptr(uintptr(hint), t.bucket.size)
305: if overflow || mem > maxAlloc {
306: hint = 0
307: }
308:
(dlv) n
> runtime.makemap() /usr/local/go/src/runtime/map.go:304 (PC: 0x100c2d1)
Warning: debugging optimized function
299: // If the compiler has determined that the map or the first bucket
300: // can be created on the stack, h and/or bucket may be non-nil.
301: // If h != nil, the map can be created directly in h.
302: // If h.buckets != nil, bucket pointed to can be used as the first bucket.
303: func makemap(t *maptype, hint int, h *hmap) *hmap {
=> 304: mem, overflow := math.MulUintptr(uintptr(hint), t.bucket.size)
305: if overflow || mem > maxAlloc {
306: hint = 0
307: }
308:
309: // initialize Hmap
(dlv) n
> runtime.makemap() /usr/local/go/src/runtime/map.go:305 (PC: 0x100c2e5)
Warning: debugging optimized function
300: // can be created on the stack, h and/or bucket may be non-nil.
301: // If h != nil, the map can be created directly in h.
302: // If h.buckets != nil, bucket pointed to can be used as the first bucket.
303: func makemap(t *maptype, hint int, h *hmap) *hmap {
304: mem, overflow := math.MulUintptr(uintptr(hint), t.bucket.size)
=> 305: if overflow || mem > maxAlloc {
306: hint = 0
307: }
308:
309: // initialize Hmap
310: if h == nil {
(dlv) n
> runtime.makemap() /usr/local/go/src/runtime/map.go:310 (PC: 0x100c2f2)
Warning: debugging optimized function
305: if overflow || mem > maxAlloc {
306: hint = 0
307: }
308:
309: // initialize Hmap
=> 310: if h == nil {
311: h = new(hmap)
312: }
313: h.hash0 = fastrand()
314:
315: // Find the size parameter B which will hold the requested # of elements.
(dlv) n
> runtime.makemap() /usr/local/go/src/runtime/map.go:313 (PC: 0x100c300)
Warning: debugging optimized function
308:
309: // initialize Hmap
310: if h == nil {
311: h = new(hmap)
312: }
=> 313: h.hash0 = fastrand()
314:
315: // Find the size parameter B which will hold the requested # of elements.
316: // For hint < 0 overLoadFactor returns false since hint < bucketCnt.
317: B := uint8(0)
318: for overLoadFactor(hint, B) {
(dlv) n
> runtime.makemap() /usr/local/go/src/runtime/map.go:318 (PC: 0x100c317)
Warning: debugging optimized function
313: h.hash0 = fastrand()
314:
315: // Find the size parameter B which will hold the requested # of elements.
316: // For hint < 0 overLoadFactor returns false since hint < bucketCnt.
317: B := uint8(0)
=> 318: for overLoadFactor(hint, B) {
319: B++
320: }
321: h.B = B
322:
323: // allocate initial hash table
(dlv) n
> runtime.makemap() /usr/local/go/src/runtime/map.go:319 (PC: 0x100c319)
Warning: debugging optimized function
314:
315: // Find the size parameter B which will hold the requested # of elements.
316: // For hint < 0 overLoadFactor returns false since hint < bucketCnt.
317: B := uint8(0)
318: for overLoadFactor(hint, B) {
=> 319: B++
320: }
321: h.B = B
322:
323: // allocate initial hash table
324: // if B == 0, the buckets field is allocated lazily later (in mapassign)
(dlv) n
> runtime.makemap() /usr/local/go/src/runtime/map.go:318 (PC: 0x100c321)
Warning: debugging optimized function
313: h.hash0 = fastrand()
314:
315: // Find the size parameter B which will hold the requested # of elements.
316: // For hint < 0 overLoadFactor returns false since hint < bucketCnt.
317: B := uint8(0)
=> 318: for overLoadFactor(hint, B) {
319: B++
320: }
321: h.B = B
322:
323: // allocate initial hash table
(dlv) n
> runtime.makemap() /usr/local/go/src/runtime/map.go:319 (PC: 0x100c319)
Warning: debugging optimized function
314:
315: // Find the size parameter B which will hold the requested # of elements.
316: // For hint < 0 overLoadFactor returns false since hint < bucketCnt.
317: B := uint8(0)
318: for overLoadFactor(hint, B) {
=> 319: B++
320: }
321: h.B = B
322:
323: // allocate initial hash table
324: // if B == 0, the buckets field is allocated lazily later (in mapassign)
(dlv) n
> runtime.makemap() /usr/local/go/src/runtime/map.go:318 (PC: 0x100c321)
Warning: debugging optimized function
313: h.hash0 = fastrand()
314:
315: // Find the size parameter B which will hold the requested # of elements.
316: // For hint < 0 overLoadFactor returns false since hint < bucketCnt.
317: B := uint8(0)
=> 318: for overLoadFactor(hint, B) {
319: B++
320: }
321: h.B = B
322:
323: // allocate initial hash table

(dlv) p h
*runtime.hmap {
count: 0,
flags: 0,
B: 2,
noverflow: 0,
hash0: 1797362353,
buckets: unsafe.Pointer(0xc00008e000),
oldbuckets: unsafe.Pointer(0x0),
nevacuate: 0,
extra: *runtime.mapextra nil,}
(dlv)


3

Xargin

2021-05-29

count 是在 map 里已经存了元素的时候才会有值的,hint 只是说大概可能会有多少个元素,提前分配足够的 bucket,减少一部分扩容成本(实际应用中很多时候 hint 也没啥用)

0

Go高级工程师实战营

慕课网与 GoCN 社区官方联手打造,定义行业Go高级人才培养标准,4个月,快速晋升为P6+/D7级高级人才。

458 学习 · 266 问题

查看课程