Dengan pengecualian langka ( satu , dua << aslinya diformat lebih buruk, IMO ) artikel tentang "profiling" di golang adalah cetak ulang dari anotasi ke paket pprof (bahkan bukan artikel lama ini ) dan kemudian sedikit pengalaman pribadi tentang bagaimana (tidak) berhasil dengan bantuan pprof menemukan masalahnya.
, "" . - / , , () . " ", .
: "" - "". ( , .) ( ) " ", ( " ") 20+.
" " - " ". ( ) . , "", "". , " " . "". " " .
. , , ( ) "" go. - , goroutines …
, - ́ "pprof.WriteHeapProfile()". : " " "" 512. ( "").
"́ ": "WriteTo()" "" "debug=2":
pprof.Lookup("heap").WriteTo(some_file, 2)
pprof, . , " " .
, "net/http/pprof" curl/wget. , : "http.ListenAndServe()" , . .. "ListenAndServe()" . "go …" goroutine.
pprof ( ). .
1. HeapProfile
import (
"runtime"
"runtime/pprof"
)
…
// Debug: pprof.WriteHeapProfile()
memprofile := "/run/dnsd/memprofile"
f, _ := os.Create(memprofile)
runtime.GC() // get up-to-date statistics
pprof.WriteHeapProfile(f)
f.Close()
…
// Debug: pprof http listener
// go http.ListenAndServe("localhost:8080", nil)
, . — curl.
2.
( 512 4…6 ), 99% .
goroutine "main.apiCall.func1()" 10923 "". (, .. "" 512 . - …)
# go tool pprof -nodefraction=0 -inuse_objects memprofile.3+
File: dnsd
Type: inuse_objects
Time: Dec 24, 2020 at 10:38am (MSK)
Entering interactive mode (type "help" for commands, "o" for options)
(pprof) top
Showing nodes accounting for 19387, 100% of 19387 total
Showing top 10 nodes out of 32
flat flat% sum% cum cum%
10923 56.34% 56.34% 10923 56.34% main.apiCall.func1
8192 42.26% 98.60% 8192 42.26% regexp.mergeRuneSets.func2
256 1.32% 99.92% 256 1.32% bufio.NewWriterSize
16 0.083% 100% 16 0.083% compress/flate.(*dictDecoder).init
3. /
:
// To complete report processing even after return on timeout
go func () {
defer report.DelNotifier(commands.UUID)
signals := make(chan os.Signal, 1)
signal.Notify(signals, syscall.SIGHUP, syscall.SIGINT, syscall.SIGKILL, syscall.SIGTERM)
for {
select {
case index := <-callback:
if (index + 1) >= len(Workers) {
done <- struct{}{}
return
}
case t:= <- timer: // t++ on each tick, t=-1 at the end
if t > 0 {
xl.Warn("apiCall: Timer tick while still not enough reports from workers!")
}
if t < 0 { // Time is over
xl.Err("apiCall: Time over while still not enough reports from workers!")
err = fmt.Errorf("Time over")
done <- struct{}{}
return
}
case exitSignal = <-signals:
xl.Warnf("apiCall: Interrupt is detected: %s", exitSignal)
xl.Warn("apiCall: Waiting for timeout to complete report processing...")
err = fmt.Errorf("Interrupt")
done <- struct{}{}
return
}
}
} ()
4.
, "" "commands.UUID" (commands "" ). , .. "" defer. , . - . - :
go func (uuid string) {
…
} (commands.UUID)
SIGKILL (""), . , - - .
, "". - ? :
signal.Notify(signals, syscall.SIGHUP, syscall.SIGINT, syscall.SIGKILL, syscall.SIGTERM)
, "defer report.DelNotifier()" . "signal.Notify()" , . , "os.Signal" " " . . , , " ".
, , " ". "" , "" — .
5. Happy end
:
defer signal.Stop(signals)
, :
# go tool pprof -nodefraction=0 -inuse_objects memprofile.1
File: dnsd
Type: inuse_objects
Time: Dec 25, 2020 at 11:56am (MSK)
No samples were found with the default sample value type.
Try "sample_index" command to analyze different sample values.
Entering interactive mode (type "help" for commands, "o" for options)
(pprof) top
Showing nodes accounting for 0, 0% of 0 total
flat flat% sum% cum cum%
() . . " " .
.
, "" ( ""). () , .. "" ( "" ).
golang, , " ". ( ) :
. ( " ") "", . — …
"" goroutine ( "" ).
"defer …" ( - goroutine, ).
"" ( "signal.Notify()") .
go1.14. 1.8. 1.8 30 . .
Saya harus menahan diri untuk tidak mencoba go1.15. Karena para hipster yang menyelinap masuk melanggar dukungan X.509 "CommonName" saat memeriksa sertifikat. (Secara tradisional) tidak mengetahui bahwa selain dari Internet publik ada segala macam segmen "tertutup", dengan kelambatan yang tinggi untuk membuat perubahan.
Jadi itu saja.
Kritik yang membangun dan mengacungkan jari "mana aku bodoh" disambut dengan baik.
Mengambil kesempatan ini, semua orang dengan tahun 2021 mendatang!