Rumah  >  Artikel  >  pembangunan bahagian belakang  >  Anda mungkin pernah mendengar tentang melakukan GC pada peta Golang?

Anda mungkin pernah mendengar tentang melakukan GC pada peta Golang?

藏色散人
藏色散人ke hadapan
2021-08-13 14:26:462558semak imbas

, 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 mapmembina semula petadelete. Komponen bekas

terbina dalam

. Ini boleh dielakkan sedikit sebanyak. go-zeroMula-mula mari kita lihat bagaimana safemap yang disediakan oleh orang asli safemap dipadamkan?

gomapPemadaman peta asli

Kod ujian adalah seperti di atas, kita boleh lulus:

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

, jadi mari kita lihat

. int64mapdelete_fast64deletemapdeletemapdelete

Amaran gambar panjang! ! !

Analisis kod umum adalah seperti di atas dan kod khusus dibiarkan untuk dibaca oleh semua orang. Sebenarnya, proses umum ialah:

Anda mungkin pernah mendengar tentang melakukan GC pada peta Golang?

Perlindungan tulis untuk mengelakkan penulisan serentak

Tanya sama ada
    yang akan dipadamkan wujud
  1. Jika
  2. wujud, tandakan bendera untuk pemadaman
  3. key
  4. Jadi jika anda memadam count-- di kawasan yang luas,
  5. sebenar yang disimpan
tidak akan dipadamkan, tetapi semasa status kunci akan ditanda sebagai

. keymapMalah, 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

mengelakkan masalah ini?

go-zerosafemapsafemapsafemap

secara langsung menganalisis mengapa ia direka bentuk seperti ini daripada operasi :

safemap

Pratetapkan Anda mungkin pernah mendengar tentang melakukan GC pada peta Golang? ambang pemadaman

Jika dicetuskan, ia akan diletakkan dalam pratetap baharu
  1. Kedua-dua adalah keseluruhan, jadi hanya satu newmap boleh. Saham
  2. map Jadi jelaslah mengapa dua key ditetapkan:

map Sebagai prinsipal penyimpanan, jika operasi

mencapai ambang , ia akan Mencetuskan penghijrahan.
  1. dirtyOld Sebagai simpanan sementara, apabila ambang tercapai, bahagian delete
  2. dirtyNew akan disimpan Jadi semasa operasi migrasi, apa yang perlu kita lakukan adalah : key/value
  3. asal dikosongkan, kunci/nilai yang disimpan disimpan semula ke
melalui untuk-julat, dan kemudian

menunjuk ke dirtyOld. dirtyNewdirtyNewdirtyOldAnda mungkin mempunyai soalan: Bukankah ini bermakna

tidak dipadamkan hanya ditanda

key/valueMalah, semasa? proses tophash=empty, ia telah ditandai Tapis keluar kekunci

daripada for-range supaya kunci yang tidak diperlukan tidak akan ditambahkan pada tophash dan tidak akan menjejaskan

.

dirtyNewdirtyOld

Ini sebenarnya konsep kutipan sampah generasi lama dan generasi baru.

Anda mungkin pernah mendengar tentang melakukan GC pada peta Golang?Untuk butiran pelaksanaan lanjut, anda boleh melihat kod sumber!

Alamat projek

github.com/tal-tech/go-zeroSelamat datang untuk menggunakan go-zero dan

star

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!

Kenyataan:
Artikel ini dikembalikan pada:learnku.com. Jika ada pelanggaran, sila hubungi admin@php.cn Padam