Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Gunosy.go #3 ~ expvar.go ~ #gunosygo

Gunosy.go #3 ~ expvar.go ~ #gunosygo

Gunosy.go #3 の発表資料です。

Bca2e4847cad171859e093aaf88a6c22?s=128

zoncoen

June 25, 2014
Tweet

More Decks by zoncoen

Other Decks in Programming

Transcript

  1. Gunosy.go #3 ~ expvar.go ~ Kenta Mori (@zoncoen)

  2. Contents 1. expvar package ͱ͸ʁ 2. expvar ͷجຊతͳಈ࡞֬ೝ 3. ࣮ફɿΞΫηε਺Λެ։͢Δ

    4. ·ͱΊ
  3. ࣗݾ঺հ • ৿݈ଠ (@zoncoen) - ໋ཱؗ (ੜ໋Պֶ) → ಸྑઌ୺ (৘ใ)

    - ৽ଔݚमத@DeNA - Baby Gopher
  4. What is the expvar pkg? • αʔό্ͷύϒϦοΫม਺΁ͷඪ४Խ͞Ε ͨΠϯλϑΣʔεΛఏڙ • ม਺͸

    HTTP αʔό্ͷ /debug/vars ʹ JSON ϑΥʔϚοτͰެ։͞ΕΔ ?
  5. ͻͱ·ͣ࢖ͬͯΈΔ

  6. ҎԼͷίʔυΛ࣮ߦͯ͠ɺ http://localhost:8080/debug/vars ʹΞΫηε import ( _ “expvar" "net/http" ) !

    func main() { http.ListenAndServe(":8080", nil) }
  7. ͳΜ͔ग़ͯ͘Δ { "cmdline": ["/var/folders/c3/vwntnjg517v2pxzd6072hrnjhggkq_/T/go- build578951979/command-line-arguments/_obj/exe/demo"], "memstats": {“Alloc”:278640,"TotalAlloc":364488,"Sys": 4069608,"Lookups":29,"Mallocs":972,"Frees":450,"HeapAlloc": 278640,"HeapSys":1048576,"HeapIdle":630784,"HeapInuse": 417792,"HeapReleased":593920,"HeapObjects":522,"StackInuse":

    ! … snip … ! {"Size":12288,"Mallocs":0,"Frees":0},{"Size":14080,"Mallocs": 0,"Frees":0},{"Size":16384,"Mallocs":0,"Frees":0},{"Size": 17664,"Mallocs":0,"Frees":0},{"Size":20480,"Mallocs":0,"Frees":0}, {"Size":21248,"Mallocs":0,"Frees":0},{"Size":24576,"Mallocs": 0,"Frees":0},{"Size":24832,"Mallocs":0,"Frees":0},{"Size": 28672,"Mallocs":0,"Frees":0},{"Size":32768,"Mallocs":4,"Frees":0}]} }
  8. import expvar ͷಈ࡞ 1. HTTPαʔόͷ /debug/vars ʹϋϯυϥΛ ొ࿥ 2. os.Args

    Λ ม਺ cmdline ͱͯ͠ొ࿥ 3. runtime.Memstats Λ ม਺ memstats ͱ͠ ͯొ࿥
  9. ͖ͬ͞ͷΞϨ { "cmdline": ["/var/folders/c3/vwntnjg517v2pxzd6072hrnjhggkq_/T/go- build578951979/command-line-arguments/_obj/exe/expvar"], "memstats": {“Alloc”:278640,"TotalAlloc":364488,"Sys": 4069608,"Lookups":29,"Mallocs":972,"Frees":450,"HeapAlloc": 278640,"HeapSys":1048576,"HeapIdle":630784,"HeapInuse": 417792,"HeapReleased":593920,"HeapObjects":522,"StackInuse":

    ! … snip … ! {"Size":12288,"Mallocs":0,"Frees":0},{"Size":14080,"Mallocs": 0,"Frees":0},{"Size":16384,"Mallocs":0,"Frees":0},{"Size": 17664,"Mallocs":0,"Frees":0},{"Size":20480,"Mallocs":0,"Frees":0}, {"Size":21248,"Mallocs":0,"Frees":0},{"Size":24576,"Mallocs": 0,"Frees":0},{"Size":24832,"Mallocs":0,"Frees":0},{"Size": 28672,"Mallocs":0,"Frees":0},{"Size":32768,"Mallocs":4,"Frees":0}]} }
  10. 1. HTTPαʔόͷ /debug/vars ʹϋϯυϥΛ ొ࿥ // expvar.go L332-336 func init()

    { http.HandleFunc("/debug/vars", expvarHandler) Publish("cmdline", Func(cmdline)) Publish("memstats", Func(memstats)) }
  11. 2. os.Args Λ ม਺ cmdline ͱͯ͠ొ࿥ // expvar.go L322-324 func

    cmdline() interface{} { return os.Args } ! // expvar.go L332-336 func init() { http.HandleFunc("/debug/vars", expvarHandler) Publish("cmdline", Func(cmdline)) Publish("memstats", Func(memstats)) }
  12. 3. runtime.Memstats Λ ม਺ memstats ͱ ͯ͠ొ࿥ // expvar.go L326-330

    func memstats() interface{} { stats := new(runtime.MemStats) runtime.ReadMemStats(stats) return *stats } ! // expvar.go L332-336 func init() { http.HandleFunc("/debug/vars", expvarHandler) Publish("cmdline", Func(cmdline)) Publish("memstats", Func(memstats)) }
  13. جຊ͸͜Ε͚ͩ

  14. // expvar.go L332-336 func init() { http.HandleFunc("/debug/vars", expvarHandler) Publish("cmdline", Func(cmdline))

    Publish("memstats", Func(memstats)) } Publish() ͱ͸
  15. // expvar.go L244-248 var ( mutex sync.RWMutex vars = make(map[string]Var)

    varKeys []string // sorted ) ! // expvar.go L253-262 func Publish(name string, v Var) { mutex.Lock() defer mutex.Unlock() if _, existing := vars[name]; existing { log.Panicln("Reuse of exported var name:", name) } vars[name] = v varKeys = append(varKeys, name) sort.Strings(varKeys) } ม਺ name Λ export (name͕͢Ͱʹొ࿥͞Ε͍ͯΔͱ log.Panic ) varKeys: sort ࡁΈ key vars: key ͱ value ͷ Map
  16. // expvar.go L308-320 func expvarHandler(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type",

    "application/json; charset=utf-8") fmt.Fprintf(w, "{\n") first := true Do(func(kv KeyValue) { if !first { fmt.Fprintf(w, ",\n") } first = false fmt.Fprintf(w, "%q: %s", kv.Key, kv.Value) }) fmt.Fprintf(w, "\n}\n") } export ͞Εͨม਺͸ expvarHandler ʹΑͬͯ JSON Ͱެ։͞ΕΔ
  17. // expvar.go L300-306 func Do(f func(KeyValue)) { mutex.RLock() defer mutex.RUnlock()

    for _, k := range varKeys { f(KeyValue{k, vars[k]}) } } Do() ͸Ҿ਺ͷ func ʹ KeyValue Λ౉࣮ͯ͠ߦ
  18. ࣮ફɿࣗ෼Ͱม਺Λొ࿥͢Δ

  19. ΞΫηεΧ΢ϯλ num_calls Λ export import ( "expvar" "net/http" ) !

    var numCalls = expvar.NewInt("num_calls") ! func helloHandler(w http.ResponseWriter, req *http.Request) { numCalls.Add(1) io.WriteString(w, "Hello Gopher!\n”) } ! func main() { http.HandleFunc("/", helloHandler) http.ListenAndServe(":8080", nil) }
  20. /debug/vars ʹ ΞΫηε͢Δͱ export ͨ͠ num_calls ͕औಘͰ͖Δ { "cmdline": ["/var/folders/c3/vwntnjg517v2pxzd6072hrnjhggkq_/T/go-

    build507427005/command-line-arguments/_obj/exe/demo"], "memstats": {“Alloc”:336232,"TotalAlloc":336240,"Sys": 4069608,"Lookups":13,"Mallocs":839,"Frees":1,"HeapAlloc": 336232,"HeapSys": ! … snip … ! 21248,"Mallocs":0,"Frees":0},{"Size":24576,"Mallocs":0,"Frees":0}, {"Size":24832,"Mallocs":0,"Frees":0},{"Size":28672,"Mallocs": 0,"Frees":0},{"Size":32768,"Mallocs":4,"Frees":0}]}, "num_calls": 1 }
  21. Debug ʹศར (?)

  22. ม਺ͷܕ͸ Int, Float, String RWMutex ͰΞτϛοΫʹมߋ͞ΕΔ // expvar.go L43-46 type

    Int struct { mu sync.RWMutex i int64 } ! // expvar.go L67-70 type Float struct { mu sync.RWMutex f float64 } ! // expvar.go L217-220 type String struct { mu sync.RWMutex s string }
  23. ม਺ͷܕ͸ Int, Float, String RWMutex ͰΞτϛοΫʹมߋ͞ΕΔ // expvar.go L48-64 func

    (v *Int) String() string { v.mu.RLock() defer v.mu.RUnlock() return strconv.FormatInt(v.i, 10) } ! func (v *Int) Add(delta int64) { v.mu.Lock() defer v.mu.Unlock() v.i += delta } ! func (v *Int) Set(value int64) { v.mu.Lock() defer v.mu.Unlock() v.i = value }
  24. ·ͱΊ • expvar Λ࢖͏ͱ Server ্ͷม਺Λ JSON ϑΥʔϚοτͰ؆୯ʹऔಘͰ͖Δ • Debug

    ʹศར (?) • ศརͳར༻ํ๏ͱ͔ࢥ͍ͭ͘ਓ͸ڭ͑ͯԼ͍͞