Rumah > Artikel > pembangunan bahagian belakang > Anda mungkin pernah mendengar tentang melakukan GC pada peta Golang?
, apabila memadamkan pasangan nilai kunci, sebenarnya tidak dipadamkan, tetapi ditanda. Oleh itu, kerana terdapat lebih banyak pasangan nilai kunci, adakah ia akan menyebabkan banyak pembaziran memori? Pertama sekali, jawapannya ialah ya, ia berkemungkinan besar menyebabkan OOM, dan terdapat perbincangan tentang perkara ini: github.com/golang/go/issues/20135. Maksud umum ialah dalam yang besar, operasi sebenarnya tidak melepaskan memori dan boleh menyebabkan memori OOM.
Jadi pendekatan umum ialah map
membina semula petadelete
. Komponen bekas
. Ini boleh dielakkan sedikit sebanyak. go-zero
Mula-mula mari kita lihat bagaimana safemap
yang disediakan oleh orang asli safemap
dipadamkan?
go
map
Pemadaman peta asli
1 package main 2 3 func main() { 4 m := make(map[int]string, 9) 5 m[1] = "hello" 6 m[2] = "world" 7 m[3] = "go" 8 9 v, ok := m[1] 10 _, _ = fn(v, ok) 11 12 delete(m, 1) 13 } 14 15 func fn(v string, ok bool) (string, bool) { 16 return v, ok 17 }
Laksanakan baris 12 go tool compile -S -N -l testmap.go | grep "CALL"
, pelaksanaan sebenar ialah
0x0071 00113 (test/testmap.go:4) CALL runtime.makemap(SB) 0x0099 00153 (test/testmap.go:5) CALL runtime.mapassign_fast64(SB) 0x00ea 00234 (test/testmap.go:6) CALL runtime.mapassign_fast64(SB) 0x013b 00315 (test/testmap.go:7) CALL runtime.mapassign_fast64(SB) 0x0194 00404 (test/testmap.go:9) CALL runtime.mapaccess2_fast64(SB) 0x01f1 00497 (test/testmap.go:10) CALL "".fn(SB) 0x0214 00532 (test/testmap.go:12) CALL runtime.mapdelete_fast64(SB) 0x0230 00560 (test/testmap.go:7) CALL runtime.gcWriteBarrier(SB) 0x0241 00577 (test/testmap.go:6) CALL runtime.gcWriteBarrier(SB) 0x0252 00594 (test/testmap.go:5) CALL runtime.gcWriteBarrier(SB) 0x025c 00604 (test/testmap.go:3) CALL runtime.morestack_noctxt(SB)
Jenis parameter bagi fungsi ini adalah konkrit delete
, runtime.mapdelete_fast64
beroperasi sama seperti yang asal
. int64
mapdelete_fast64
delete
mapdelete
mapdelete
Analisis kod umum adalah seperti di atas dan kod khusus dibiarkan untuk dibaca oleh semua orang. Sebenarnya, proses umum ialah: Perlindungan tulis untuk mengelakkan penulisan serentak Tanya sama ada
key
count--
di kawasan yang luas, . key
map
Malah, titik permulaan adalah serupa dengan pemadaman tag key
, yang menghalang empty
yang sama daripada dimasukkan pada masa hadapan, menghapuskan keperluan untuk operasi pengembangan dan pengecutan.
Tetapi ini tidak sesuai untuk sesetengah senario Jika pembangun tidak akan memasukkan mysql
yang sama lagi pada masa hadapan, ia berkemungkinan akan mengakibatkan key
.
Jadi sebagai tindak balas kepada situasi di atas, key
berkembang OOM
. Mari lihat bagaimana
go-zero
safemap
safemap
safemap
safemap
Pratetapkan ambang pemadaman
Jika dicetuskan, ia akan diletakkan dalam pratetap baharunewmap
boleh. Saham map
Jadi jelaslah mengapa dua key
ditetapkan: map
Sebagai prinsipal penyimpanan, jika operasi
dirtyOld
Sebagai simpanan sementara, apabila ambang tercapai, bahagian delete
dirtyNew
akan disimpan Jadi semasa operasi migrasi, apa yang perlu kita lakukan adalah : key/value
menunjuk ke dirtyOld
. dirtyNew
dirtyNew
dirtyOld
Anda mungkin mempunyai soalan: Bukankah ini bermakna
key/value
Malah, semasa? prosestophash=empty
, ia telah ditandai Tapis keluar kekuncidaripada
.for-range
supaya kunci yang tidak diperlukan tidak akan ditambahkan padatophash dan tidak akan menjejaskan
dirtyNew
dirtyOld
Untuk butiran pelaksanaan lanjut, anda boleh melihat kod sumber!
Alamat projek
Sokong kami!
Atas ialah kandungan terperinci Anda mungkin pernah mendengar tentang melakukan GC pada peta Golang?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!