Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Goをカンストさせる話

4,874 views

Published on

Goをカンストさせる話

Published in: Entertainment & Humor
  • Hey guys! Who wants to chat with me? More photos with me here 👉 http://www.bit.ly/katekoxx
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here

Goをカンストさせる話

  1. 1. Go をカンストさせる話 Maxing out Go
  2. 2. こんにちは
  3. 3. select してますか ?
  4. 4. 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 commandn") go doCommand( x, withDeadline( x.Ctx, time.Now().Add(4*time.Second), ), cmd.Cmd, cmd.Arg, ) case <-x.Ctx.Done(): break loop } } }(x)
  5. 5. 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 の処理に飛ぶ
  6. 6. 大事なことは src/runtime/select.go に 全部書いてある
  7. 7. 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)
  8. 8. tcase uint16 // total count of scase[]
  9. 9. uint16
  10. 10. 65535
  11. 11. 敵を 65535 体倒すとデスペナルテ 所持ギルの上限は 65 ぐれメタルを 1 回の戦闘で複数体倒しても合計値が 65535 でカウンタ 率を 65535% にしたらダメー 35 ターン経過させると全滅
  12. 12. HUMAN BEINGS CANNOT HELP MAXING IT OUT
  13. 13. 実験 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)
  14. 14. 実験 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)
  15. 15. 実験 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]:
  16. 16. 実験 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) 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) 以下 65536 ま で続く
  17. 17. 結果 コンパイルが終わらない CPU100% やがてメモリを食いつくして OOM Killer に殺される OOM Killer のイメージ ( オオアリク イ )
  18. 18. 諦めるのはまだ早い
  19. 19. reflect.Select
  20. 20. 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 相当の処理を書ける
  21. 21. 実行結果 ubuntu:gotorture:% go run uint16maxselect.go ready fatal error: selectrecv: too many cases goroutine 1 [running]: runtime.throw(0x521ce0, 0x1a) ...
  22. 22. too many cases
  23. 23. Questions?
  24. 24. ないですね
  25. 25. ご清聴ありがとうございました

×