Se ha denunciado esta presentación.
Utilizamos tu perfil de LinkedIn y tus datos de actividad para personalizar los anuncios y mostrarte publicidad más relevante. Puedes cambiar tus preferencias de publicidad en cualquier momento.

Goをカンストさせる話

4.926 visualizaciones

Publicado el

Goをカンストさせる話

Publicado en: Entretenimiento y humor
  • Hey guys! Who wants to chat with me? More photos with me here 👉 http://www.bit.ly/katekoxx
       Responder 
    ¿Estás seguro?    No
    Tu mensaje aparecerá aquí

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. ご清聴ありがとうございました

×