Upload
moriyoshi-koizumi
View
2.872
Download
0
Embed Size (px)
Citation preview
Goをカンストさせる話
Maxing out Go
こんにちは
select してますか ?
select
go func(x *Daemon) {defer func() {
x.WaitGroup.Done()log.Printf("Daemon %s stopped", x.Name)
}()loop:
for {select {case cmd := <-x.CmdChan:
log.Printf("Daemon %s received command\n")go doCommand(
x,withDeadline(
x.Ctx,time.Now().Add(4*time.Second),
),cmd.Cmd,cmd.Arg,
)case <-x.Ctx.Done():
break loop}
}}(x)
selectの実装はどうなっているのか ?
case x=<-❶ case x->❷ case x=<-❸ case x=<-❹goroutine1
case x=<-❶ case x->❷goroutine2
goroutine 1
goroutine 2
goroutine 1goroutine 1
goroutine 2
goroutine 1
chan ❶ chan ❷ chan ❸ chan ❹
1. chanの waitキューに入れる2. 起こされるまで待つ3. どれに起こされたか調べる4. 該当する caseの処理に飛ぶ
大事なことはsrc/runtime/select.goに
全部書いてある
src/runtime/runtime.go
// Select statement header.// Known to compiler.// Changes here must also be made in src/cmd/internal/gc/select.go's selecttype.type hselect struct { tcase uint16 // total count of scase[] ncase uint16 // currently filled scase[] pollorder *uint16 // case poll order lockorder *uint16 // channel lock order scase [1]scase // one per case (in order of appearance)}
// Select case descriptor.// Known to compiler.// Changes here must also be made in src/cmd/internal/gc/select.go's selecttype.type scase struct { elem unsafe.Pointer // data element c *hchan // chan pc uintptr // return pc (for race detector / msan) kind uint16
tcase uint16 // total count of scase[]
uint16
65535
敵を 65535体倒すとデスペナルティの威力が最大に
所持ギルの上限は 65535ギルはぐれメタルを 1回の戦闘で複数体倒しても合計値が 65535でカウンタース
シンクロ率を 65535%にしたらダメージがオーバーフローした
65535ターン経過させると全滅扱い
HUMAN BEINGSCANNOT
HELPMAXING
ITOUT
実験
package main
import "fmt"
func main() { c := [65536]chan int{} f := fmt.Println select { case i := <-c[0]: f(i) case i := <-c[1]: f(i) case i := <-c[2]: f(i) case i := <-c[3]: f(i) case i := <-c[4]: f(i) case i := <-c[5]: f(i) case i := <-c[6]:
実験
package main
import "fmt"
func main() { c := [65536]chan int{} f := fmt.Println select { case i := <-c[0]: f(i) case i := <-c[1]: f(i) case i := <-c[2]: f(i) case i := <-c[3]: f(i) case i := <-c[4]: f(i) case i := <-c[5]: f(i) case i := <-c[6]: f(i) case i := <-c[7]: f(i)
実験
package main
import "fmt"
func main() { c := [65536]chan int{} f := fmt.Println select { case i := <-c[0]: f(i) case i := <-c[1]: f(i) case i := <-c[2]: f(i) case i := <-c[3]: f(i) case i := <-c[4]: f(i) case i := <-c[5]: f(i) case i := <-c[6]: f(i) case i := <-c[7]: f(i) case i := <-c[8]: f(i) case i := <-c[9]: f(i) case i := <-c[10]: f(i) case i := <-c[11]: f(i) case i := <-c[12]: f(i) case i := <-c[13]: f(i) case i := <-c[14]: f(i) case i := <-c[15]: f(i) case i := <-c[16]: f(i) case i := <-c[17]: f(i) case i := <-c[18]: f(i) case i := <-c[19]: f(i) case i := <-c[20]: f(i)
実験
package main
import "fmt"
func main() {c := [65536]chan int{}f := fmt.Printlnselect {case i := <-c[0]:
f(i)case i := <-c[1]:
f(i)case i := <-c[2]:
f(i)case i := <-c[3]:
f(i)case i := <-c[4]:
f(i)case i := <-c[5]:
f(i)case i := <-c[6]:
f(i)case i := <-c[7]:
f(i)case i := <-c[8]:
f(i)case i := <-c[9]:
f(i)case i := <-c[10]:
f(i)case i := <-c[11]:
f(i)case i := <-c[12]:
f(i)case i := <-c[13]:
f(i)case i := <-c[14]:
f(i)case i := <-c[15]:
f(i)case i := <-c[16]:
f(i)case i := <-c[17]:
f(i)case i := <-c[18]:
f(i)case i := <-c[19]:
f(i)case i := <-c[20]:
f(i)case i := <-c[21]:
f(i)case i := <-c[22]:
f(i)case i := <-c[23]:
f(i)case i := <-c[24]:
f(i)case i := <-c[25]:
f(i)case i := <-c[26]:
f(i)case i := <-c[27]:
f(i)case i := <-c[28]:
f(i)case i := <-c[29]:
f(i)case i := <-c[30]:
f(i)case i := <-c[31]:
f(i)case i := <-c[32]:
f(i)case i := <-c[33]:
f(i)case i := <-c[34]:
f(i)case i := <-c[35]:
f(i)case i := <-c[36]:
f(i)case i := <-c[37]:
f(i)case i := <-c[38]:
f(i)case i := <-c[39]:
f(i)case i := <-c[40]:
f(i)case i := <-c[41]:
f(i)case i := <-c[42]:
f(i)case i := <-c[43]:
f(i)case i := <-c[44]:
f(i)case i := <-c[45]:
f(i)case i := <-c[46]:
f(i)case i := <-c[47]:
f(i)case i := <-c[48]:
f(i)case i := <-c[49]:
f(i)case i := <-c[50]:
f(i)case i := <-c[51]:
f(i)case i := <-c[52]:
f(i)case i := <-c[53]:
f(i)case i := <-c[54]:
f(i)case i := <-c[55]:
f(i)case i := <-c[56]:
f(i)case i := <-c[57]:
f(i)case i := <-c[58]:
f(i)case i := <-c[59]:
f(i)case i := <-c[60]:
f(i)case i := <-c[61]:
f(i)case i := <-c[62]:
f(i)case i := <-c[63]:
f(i)case i := <-c[64]:
f(i)case i := <-c[65]:
f(i)case i := <-c[66]:
f(i)case i := <-c[67]:
f(i)case i := <-c[68]:
f(i)case i := <-c[69]:
f(i)case i := <-c[70]:
f(i)case i := <-c[71]:
f(i)case i := <-c[72]:
f(i)case i := <-c[73]:
f(i)case i := <-c[74]:
f(i)case i := <-c[75]:
f(i)case i := <-c[76]:
f(i)case i := <-c[77]:
f(i)case i := <-c[78]:
f(i)case i := <-c[79]:
f(i)case i := <-c[80]:
f(i)case i := <-c[81]:
f(i)case i := <-c[82]:
f(i)case i := <-c[83]:
f(i)case i := <-c[84]:
f(i)case i := <-c[85]:
f(i)case i := <-c[86]:
f(i)case i := <-c[87]:
f(i)case i := <-c[88]:
f(i)case i := <-c[89]:
f(i)case i := <-c[90]:
f(i)case i := <-c[91]:
f(i)case i := <-c[92]:
f(i)case i := <-c[93]:
f(i)case i := <-c[94]:
f(i)case i := <-c[95]:
f(i)
以下 65536まで続く
結果
コンパイルが終わらない
CPU100%
やがてメモリを食いつくして OOM Killerに殺される
OOM Killer のイメージ (オオアリクイ )
諦めるのはまだ早い
reflect.Select
reflect.Select
func main() { cases := [65536]reflect.SelectCase{} for i, _ := range cases { cases[i] = reflect.SelectCase{ Dir: reflect.SelectRecv, Chan: reflect.ValueOf(make(chan int)), } } go func() { for { i := rand.Int() % len(cases) cases[i].Chan.Send(reflect.ValueOf(i)) time.Sleep(time.Second) } }() fmt.Println("ready") for { c, v, ok := reflect.Select(cases[:]) fmt.Println(c, v, ok) }}
リフレクションで select相当の処理を書ける
実行結果
ubuntu:gotorture:% go run uint16maxselect.goreadyfatal error: selectrecv: too many cases
goroutine 1 [running]:runtime.throw(0x521ce0, 0x1a)...
too many cases
Questions?
ないですね
ご清聴ありがとうございました