Skip to content

sysmon

sysmon adalah fungsi biasa, secara harfiah berarti system monitor, setelah menghapus bagian komentar hanya sekitar 200 baris kode. Ia akan dialokasikan thread terpisah saat tahap bootstrap program untuk启动, kemudian akan terus memonitor status program Go saat runtime di background dan mengambil tindakan yang sesuai. Bagian kode tentang启动nya dapat dilihat di fungsi runtime.main:

go
func main() {
    ...
  mp := getg().m
  mainStarted = true
  systemstack(func() {
        newm(sysmon, nil, -1)
    })
    ...
}

System monitor sendiri hanya sebuah for loop, interval setiap putaran loop adalah 20 mikrodetik, seiring dengan kenaikan idle index program, interval waktu maksimal akan meningkat hingga 10 milidetik. Di setiap putaran loop, ia terutama melakukan beberapa hal berikut:

  • Assist scheduling goroutine, preempt goroutine yang berjalan dalam waktu lama
  • Memeriksa kondisi memori dan menentukan apakah perlu melakukan garbage collection
  • Memeriksa status network poller dan menangani event network yang timeout
  • Memeriksa dan membersihkan cache memori yang tidak digunakan

Assist Scheduling

Scheduling assist adalah salah satu tugas penting sysmon, terutama mencakup dua aspek:

Preempt Goroutine

Ketika sebuah goroutine berjalan terlalu lama tanpa melakukan operasi yang dapat di-preempt (seperti alokasi memori, operasi channel, dll), sysmon akan mendeteksi dan memaksanya untuk di-preempt.

go
// Check for locked threads
// Preempt G if it's running too long
if now-gp.preemptAt > 10*1000*1000 { // 10ms
    gp.preempt = true
    gp.stackGuard0 = stackPreempt
}

Mekanisme ini mencegah sebuah goroutine memonopoli CPU terlalu lama, memastikan fairness scheduling.

Check Network Poller

Sysmon juga bertanggung jawab untuk memeriksa status network poller, menangani event network yang timeout.

go
// Check network poller
if netpollinited() {
    list, delta := netpoll(0)
    if delta != 0 {
        // Handle netpoll events
    }
}

Memory Management

Garbage Collection Trigger

Sysmon secara berkala memeriksa apakah perlu memaksa garbage collection. Jika sudah lebih dari forcegcperiod (2 menit) sejak GC terakhir, sysmon akan memicu GC paksa.

go
// Check if we need to force a GC
if t := (gcTrigger{kind: gcTriggerTime, now: now}); t.test() && forcegc.idle.Load() {
    lock(&forcegc.lock)
    forcegc.idle.Store(false)
    var list gList
    list.push(forcegc.g)
    injectglist(&list)
    unlock(&forcegc.lock)
}

Memory Scavenging

Sysmon juga bertanggung jawab untuk mengembalikan memori yang tidak digunakan ke sistem operasi.

go
// Scavenge free memory
if scavengeThreshold > 0 {
    scavenge(scavengeThreshold)
}

Implementation Details

Startup

Sysmon dimulai di akhir fungsi runtime.main, setelah semua inisialisasi selesai:

go
func main() {
    // Initialize runtime
    ...
    
    // Start sysmon
    systemstack(func() {
        newm(sysmon, nil, -1)
    })
    
    // Start user goroutines
    ...
}

Fungsi newm membuat thread OS baru untuk menjalankan sysmon.

Main Loop

Loop utama sysmon terlihat seperti ini:

go
func sysmon() {
    var (
        idle           uint32
        lastScavenge   int64
        scavengeSleep  uint32
        forceGCIdle    int64
    )
    
    for {
        // Calculate sleep time based on idle state
        sleep := calculateSleep(&idle)
        
        // Perform monitoring tasks
        checkPreempt()
        checkNetpoll()
        checkForceGC()
        scavengeMemory()
        
        // Sleep
        usleep(sleep)
    }
}

Sleep Time Calculation

Waktu tidur sysmon disesuaikan berdasarkan status idle program:

go
func calculateSleep(idle *uint32) uint32 {
    if *idle == 0 {
        *idle = 1
        return 20 * 1000 // 20 microseconds
    }
    
    if *idle < 10 {
        *idle++
    }
    
    delay := uint32(20 * 1000 * *idle)
    if delay > 10*1000*1000 { // Cap at 10ms
        delay = 10 * 1000 * 1000
    }
    
    return delay
}

Ketika program sibuk, sysmon akan lebih sering terbangun untuk merespons dengan cepat. Ketika program idle, sysmon akan mengurangi frekuensi untuk menghemat CPU.

Summary

Sysmon adalah komponen penting runtime Go, berfungsi sebagai "watchdog" untuk program Go. Meskipun kodenya relatif sederhana, ia memainkan peran kunci dalam:

  • Menjaga fairness scheduling dengan preempt goroutine yang berjalan terlalu lama
  • Memastikan garbage collection berjalan tepat waktu
  • Mengelola memori secara efisien dengan scavenging
  • Menangani event network yang timeout

Karena sysmon berjalan di thread terpisah, ia dapat terus bekerja bahkan ketika semua P sedang sibuk, memastikan monitoring yang andal.

Golang by www.golangdev.cn edit