Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Gunosy.go #3 ~ expvar.go ~ #gunosygo
Search
Sponsored
·
Ship Features Fearlessly
Turn features on and off without deploys. Used by thousands of Ruby developers.
→
zoncoen
June 25, 2014
Programming
770
1
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Gunosy.go #3 ~ expvar.go ~ #gunosygo
Gunosy.go #3 の発表資料です。
zoncoen
June 25, 2014
More Decks by zoncoen
See All by zoncoen
About Merpay Engineering Productivity Team
zoncoen
0
1.9k
Perl の HTTP/2 事情 / HTTP2 in Perl
zoncoen
0
500
Perl でも React.js の server-side rendering がしたい! / perl meets javascript with reactjs
zoncoen
0
2.2k
YAPC::Asia 2014
zoncoen
0
2.7k
同期的にプレゼンテーションするツールをつくった話
zoncoen
1
1k
Gunosy.go #4 ~ flag.go ~ #gunosygo
zoncoen
0
250
初心者がGoでpercol実装してみた話 / Golang + Reveal.js + Websocket で同期的にプレゼンテーションしたい #hikarie_go
zoncoen
0
2.6k
Other Decks in Programming
See All in Programming
例外の正しい扱い方 そのエラー try-catchして大丈夫?
jinwatanabe
0
260
そのテスト、説明できますか?~LWテスト戦略FW~のご紹介
nakahara
0
150
Webフレームワークの ベンチマークについて
yusukebe
0
170
セキュリティの専門家じゃなくてもできる。「セキュリティ意識」をアップデートして サプライチェーン攻撃への耐性を高めよう。
tk3fftk
5
880
並列実装の現場、2ヶ月間実務でAIを使い倒したAIもPCも私も限界が近い
ming_ayami
0
130
AIで効率化できた業務・日常
ochtum
0
140
気圧・高度・GPSを記録&可視化するアプリ「Koudo」を作った話
hjmkth
1
290
Make SRE Operations Easier with Azure SRE Agent
kkamegawa
0
6.9k
決定論的オーケストレーションの設計と実装 / Design and Implementation of Deterministic Orchestration
nrslib
4
1.4k
net-httpのHTTP/2対応について
naruse
0
500
Creating Composable Callables in Contemporary C++
rollbear
0
150
dRuby over BLE
makicamel
2
380
Featured
See All Featured
What's in a price? How to price your products and services
michaelherold
247
13k
Getting science done with accelerated Python computing platforms
jacobtomlinson
2
240
Public Speaking Without Barfing On Your Shoes - THAT 2023
reverentgeek
1
430
Side Projects
sachag
455
43k
A better future with KSS
kneath
240
18k
Deep Space Network (abreviated)
tonyrice
0
210
Odyssey Design
rkendrick25
PRO
2
700
Why Our Code Smells
bkeepers
PRO
340
58k
ピンチをチャンスに:未来をつくるプロダクトロードマップ #pmconf2020
aki_iinuma
128
56k
Test your architecture with Archunit
thirion
1
2.3k
Designing for Timeless Needs
cassininazir
1
260
Leadership Guide Workshop - DevTernity 2021
reverentgeek
1
310
Transcript
Gunosy.go #3 ~ expvar.go ~ Kenta Mori (@zoncoen)
Contents 1. expvar package ͱʁ 2. expvar ͷجຊతͳಈ࡞֬ೝ 3. ࣮ફɿΞΫηεΛެ։͢Δ
4. ·ͱΊ
ࣗݾհ • ݈ଠ (@zoncoen) - ໋ཱؗ (ੜ໋Պֶ) → ಸྑઌ (ใ)
- ৽ଔݚमத@DeNA - Baby Gopher
What is the expvar pkg? • αʔό্ͷύϒϦοΫมͷඪ४Խ͞Ε ͨΠϯλϑΣʔεΛఏڙ • ม
HTTP αʔό্ͷ /debug/vars ʹ JSON ϑΥʔϚοτͰެ։͞ΕΔ ?
ͻͱ·ͣͬͯΈΔ
ҎԼͷίʔυΛ࣮ߦͯ͠ɺ http://localhost:8080/debug/vars ʹΞΫηε import ( _ “expvar" "net/http" ) !
func main() { http.ListenAndServe(":8080", nil) }
ͳΜ͔ग़ͯ͘Δ { "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}]} }
import expvar ͷಈ࡞ 1. HTTPαʔόͷ /debug/vars ʹϋϯυϥΛ ొ 2. os.Args
Λ ม cmdline ͱͯ͠ొ 3. runtime.Memstats Λ ม memstats ͱ͠ ͯొ
͖ͬ͞ͷΞϨ { "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}]} }
1. HTTPαʔόͷ /debug/vars ʹϋϯυϥΛ ొ // expvar.go L332-336 func init()
{ http.HandleFunc("/debug/vars", expvarHandler) Publish("cmdline", Func(cmdline)) Publish("memstats", Func(memstats)) }
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)) }
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)) }
جຊ͜Ε͚ͩ
// expvar.go L332-336 func init() { http.HandleFunc("/debug/vars", expvarHandler) Publish("cmdline", Func(cmdline))
Publish("memstats", Func(memstats)) } Publish() ͱ
// 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
// 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 Ͱެ։͞ΕΔ
// 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 Λ࣮ͯ͠ߦ
࣮ફɿࣗͰมΛొ͢Δ
ΞΫηεΧϯλ 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) }
/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 }
Debug ʹศར (?)
มͷܕ 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 }
มͷܕ 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 }
·ͱΊ • expvar Λ͏ͱ Server ্ͷมΛ JSON ϑΥʔϚοτͰ؆୯ʹऔಘͰ͖Δ • Debug
ʹศར (?) • ศརͳར༻ํ๏ͱ͔ࢥ͍ͭ͘ਓڭ͑ͯԼ͍͞