SlideShare a Scribd company logo
1 of 25
Download to read offline
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 commandn")
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)
tcase uint16 // total count of scase[]
uint16
65535
敵を 65535 体倒すとデスペナルテ
所持ギルの上限は 65
ぐれメタルを 1 回の戦闘で複数体倒しても合計値が 65535 でカウンタ
率を 65535% にしたらダメー
35 ターン経過させると全滅
HUMAN BEINGS
CANNOT
HELP
MAXING
IT
OUT
実験
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)
実験
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]:
実験
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 ま
で続く
結果
コンパイルが終わらない
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.go
ready
fatal error: selectrecv: too many cases
goroutine 1 [running]:
runtime.throw(0x521ce0, 0x1a)
...
too many
cases
Questions?
ないですね
ご清聴ありがとうございました

More Related Content

What's hot

Python で munin plugin を書いてみる
Python で munin plugin を書いてみるPython で munin plugin を書いてみる
Python で munin plugin を書いてみるftnk
 
RでGISハンズオンセッション
RでGISハンズオンセッションRでGISハンズオンセッション
RでGISハンズオンセッションarctic_tern265
 
Introduction to cython
Introduction to cythonIntroduction to cython
Introduction to cythonAtsuo Ishimoto
 
Siv3Dで楽しむゲームとメディアアート開発
Siv3Dで楽しむゲームとメディアアート開発Siv3Dで楽しむゲームとメディアアート開発
Siv3Dで楽しむゲームとメディアアート開発Ryo Suzuki
 
第12回計算機構成
第12回計算機構成第12回計算機構成
第12回計算機構成眞樹 冨澤
 
第10回 計算機構成
第10回 計算機構成第10回 計算機構成
第10回 計算機構成眞樹 冨澤
 
EmacsとGlossでお絵描きしてみるよ
EmacsとGlossでお絵描きしてみるよEmacsとGlossでお絵描きしてみるよ
EmacsとGlossでお絵描きしてみるよKiwamu Okabe
 
Spectacular Future with clojure.spec
Spectacular Future with clojure.specSpectacular Future with clojure.spec
Spectacular Future with clojure.specKent Ohashi
 
テーマ「最適化 その2」
テーマ「最適化 その2」テーマ「最適化 その2」
テーマ「最適化 その2」technocat
 
Cloud TPU Driver API ソースコード解析
Cloud TPU Driver API ソースコード解析Cloud TPU Driver API ソースコード解析
Cloud TPU Driver API ソースコード解析Mr. Vengineer
 
C# ドキドキ ライブ コーディング!! ~ 小島の分 ~ | BuriKaigi 2020
C# ドキドキ ライブ コーディング!! ~ 小島の分 ~ | BuriKaigi 2020C# ドキドキ ライブ コーディング!! ~ 小島の分 ~ | BuriKaigi 2020
C# ドキドキ ライブ コーディング!! ~ 小島の分 ~ | BuriKaigi 2020Fujio Kojima
 
データサイエンスワールドからC++を眺めてみる
データサイエンスワールドからC++を眺めてみるデータサイエンスワールドからC++を眺めてみる
データサイエンスワールドからC++を眺めてみるShintaro Fukushima
 
C# 式木 (Expression Tree) ~ LINQをより深く理解するために ~
C# 式木 (Expression Tree) ~ LINQをより深く理解するために ~C# 式木 (Expression Tree) ~ LINQをより深く理解するために ~
C# 式木 (Expression Tree) ~ LINQをより深く理解するために ~Fujio Kojima
 
Haskell勉強会 14.1〜14.3 の説明資料
Haskell勉強会 14.1〜14.3 の説明資料Haskell勉強会 14.1〜14.3 の説明資料
Haskell勉強会 14.1〜14.3 の説明資料Etsuji Nakai
 

What's hot (19)

Python で munin plugin を書いてみる
Python で munin plugin を書いてみるPython で munin plugin を書いてみる
Python で munin plugin を書いてみる
 
RでGISハンズオンセッション
RでGISハンズオンセッションRでGISハンズオンセッション
RでGISハンズオンセッション
 
Introduction to cython
Introduction to cythonIntroduction to cython
Introduction to cython
 
python-geohex
python-geohexpython-geohex
python-geohex
 
Subprocess no susume
Subprocess no susumeSubprocess no susume
Subprocess no susume
 
Siv3Dで楽しむゲームとメディアアート開発
Siv3Dで楽しむゲームとメディアアート開発Siv3Dで楽しむゲームとメディアアート開発
Siv3Dで楽しむゲームとメディアアート開発
 
第12回計算機構成
第12回計算機構成第12回計算機構成
第12回計算機構成
 
第10回 計算機構成
第10回 計算機構成第10回 計算機構成
第10回 計算機構成
 
Mock and patch
Mock and patchMock and patch
Mock and patch
 
EmacsとGlossでお絵描きしてみるよ
EmacsとGlossでお絵描きしてみるよEmacsとGlossでお絵描きしてみるよ
EmacsとGlossでお絵描きしてみるよ
 
Spectacular Future with clojure.spec
Spectacular Future with clojure.specSpectacular Future with clojure.spec
Spectacular Future with clojure.spec
 
テーマ「最適化 その2」
テーマ「最適化 その2」テーマ「最適化 その2」
テーマ「最適化 その2」
 
Emcjp item21
Emcjp item21Emcjp item21
Emcjp item21
 
Cloud TPU Driver API ソースコード解析
Cloud TPU Driver API ソースコード解析Cloud TPU Driver API ソースコード解析
Cloud TPU Driver API ソースコード解析
 
C# ドキドキ ライブ コーディング!! ~ 小島の分 ~ | BuriKaigi 2020
C# ドキドキ ライブ コーディング!! ~ 小島の分 ~ | BuriKaigi 2020C# ドキドキ ライブ コーディング!! ~ 小島の分 ~ | BuriKaigi 2020
C# ドキドキ ライブ コーディング!! ~ 小島の分 ~ | BuriKaigi 2020
 
データサイエンスワールドからC++を眺めてみる
データサイエンスワールドからC++を眺めてみるデータサイエンスワールドからC++を眺めてみる
データサイエンスワールドからC++を眺めてみる
 
C# 式木 (Expression Tree) ~ LINQをより深く理解するために ~
C# 式木 (Expression Tree) ~ LINQをより深く理解するために ~C# 式木 (Expression Tree) ~ LINQをより深く理解するために ~
C# 式木 (Expression Tree) ~ LINQをより深く理解するために ~
 
Haskell勉強会 14.1〜14.3 の説明資料
Haskell勉強会 14.1〜14.3 の説明資料Haskell勉強会 14.1〜14.3 の説明資料
Haskell勉強会 14.1〜14.3 の説明資料
 
CLR/H No.35-2
CLR/H No.35-2CLR/H No.35-2
CLR/H No.35-2
 

Viewers also liked

Goでヤフーの分散オブジェクトストレージを作った話 Go Conference 2017 Spring
Goでヤフーの分散オブジェクトストレージを作った話 Go Conference 2017 SpringGoでヤフーの分散オブジェクトストレージを作った話 Go Conference 2017 Spring
Goでヤフーの分散オブジェクトストレージを作った話 Go Conference 2017 SpringYahoo!デベロッパーネットワーク
 
Go conference 2017 Lightning talk
Go conference 2017 Lightning talkGo conference 2017 Lightning talk
Go conference 2017 Lightning talkmokelab
 
マイクロサービスバックエンドAPIのためのRESTとgRPC
マイクロサービスバックエンドAPIのためのRESTとgRPCマイクロサービスバックエンドAPIのためのRESTとgRPC
マイクロサービスバックエンドAPIのためのRESTとgRPCdisc99_
 
Coding in the context era
Coding in the context eraCoding in the context era
Coding in the context eralestrrat
 
My client wanted their apps synced, and I made it with Go
My client wanted their apps synced, and I made it with GoMy client wanted their apps synced, and I made it with Go
My client wanted their apps synced, and I made it with GoToru Furukawa
 
20171105 go con2017_lt
20171105 go con2017_lt20171105 go con2017_lt
20171105 go con2017_ltKeigo Suda
 
Gocon2017:Goのロギング周りの考察
Gocon2017:Goのロギング周りの考察Gocon2017:Goのロギング周りの考察
Gocon2017:Goのロギング周りの考察貴仁 大和屋
 
GOCON Autumn (Story of our own Monitoring Agent in golang)
GOCON Autumn (Story of our own Monitoring Agent in golang)GOCON Autumn (Story of our own Monitoring Agent in golang)
GOCON Autumn (Story of our own Monitoring Agent in golang)Huy Do
 
条件式評価器の実装による管理ツールの抽象化
条件式評価器の実装による管理ツールの抽象化条件式評価器の実装による管理ツールの抽象化
条件式評価器の実装による管理ツールの抽象化Takuya Ueda
 

Viewers also liked (10)

Goでヤフーの分散オブジェクトストレージを作った話 Go Conference 2017 Spring
Goでヤフーの分散オブジェクトストレージを作った話 Go Conference 2017 SpringGoでヤフーの分散オブジェクトストレージを作った話 Go Conference 2017 Spring
Goでヤフーの分散オブジェクトストレージを作った話 Go Conference 2017 Spring
 
Go conference 2017 Lightning talk
Go conference 2017 Lightning talkGo conference 2017 Lightning talk
Go conference 2017 Lightning talk
 
go 1.8 net/http timeouts
go 1.8 net/http timeoutsgo 1.8 net/http timeouts
go 1.8 net/http timeouts
 
マイクロサービスバックエンドAPIのためのRESTとgRPC
マイクロサービスバックエンドAPIのためのRESTとgRPCマイクロサービスバックエンドAPIのためのRESTとgRPC
マイクロサービスバックエンドAPIのためのRESTとgRPC
 
Coding in the context era
Coding in the context eraCoding in the context era
Coding in the context era
 
My client wanted their apps synced, and I made it with Go
My client wanted their apps synced, and I made it with GoMy client wanted their apps synced, and I made it with Go
My client wanted their apps synced, and I made it with Go
 
20171105 go con2017_lt
20171105 go con2017_lt20171105 go con2017_lt
20171105 go con2017_lt
 
Gocon2017:Goのロギング周りの考察
Gocon2017:Goのロギング周りの考察Gocon2017:Goのロギング周りの考察
Gocon2017:Goのロギング周りの考察
 
GOCON Autumn (Story of our own Monitoring Agent in golang)
GOCON Autumn (Story of our own Monitoring Agent in golang)GOCON Autumn (Story of our own Monitoring Agent in golang)
GOCON Autumn (Story of our own Monitoring Agent in golang)
 
条件式評価器の実装による管理ツールの抽象化
条件式評価器の実装による管理ツールの抽象化条件式評価器の実装による管理ツールの抽象化
条件式評価器の実装による管理ツールの抽象化
 

Similar to Goをカンストさせる話

マスターオブゴールーチンアンドチャネル スタートGo #1
マスターオブゴールーチンアンドチャネル   スタートGo #1マスターオブゴールーチンアンドチャネル   スタートGo #1
マスターオブゴールーチンアンドチャネル スタートGo #1Takuya Ueda
 
Kompira開発者が教えるジョブフローTips7選_Kompass発表資料20240306.pptx
Kompira開発者が教えるジョブフローTips7選_Kompass発表資料20240306.pptxKompira開発者が教えるジョブフローTips7選_Kompass発表資料20240306.pptx
Kompira開発者が教えるジョブフローTips7選_Kompass発表資料20240306.pptxManamiMaeda
 
Goの文法の実例と解説
Goの文法の実例と解説Goの文法の実例と解説
Goの文法の実例と解説Ryuji Iwata
 
C++コンパイラ GCCとClangからのメッセージをお読みください
C++コンパイラ GCCとClangからのメッセージをお読みくださいC++コンパイラ GCCとClangからのメッセージをお読みください
C++コンパイラ GCCとClangからのメッセージをお読みくださいdigitalghost
 
Pythonで始めるDropboxAPI
Pythonで始めるDropboxAPIPythonで始めるDropboxAPI
Pythonで始めるDropboxAPIDaisuke Igarashi
 
PRML 1.5-1.5.5 決定理論
PRML 1.5-1.5.5 決定理論PRML 1.5-1.5.5 決定理論
PRML 1.5-1.5.5 決定理論Akihiro Nitta
 
Project Loom + Project Panama
Project Loom + Project PanamaProject Loom + Project Panama
Project Loom + Project PanamaYuichi Sakuraba
 
Rによる繰り返しの並列処理
Rによる繰り返しの並列処理Rによる繰り返しの並列処理
Rによる繰り返しの並列処理wada, kazumi
 

Similar to Goをカンストさせる話 (12)

マスターオブゴールーチンアンドチャネル スタートGo #1
マスターオブゴールーチンアンドチャネル   スタートGo #1マスターオブゴールーチンアンドチャネル   スタートGo #1
マスターオブゴールーチンアンドチャネル スタートGo #1
 
Applicative functor
Applicative functorApplicative functor
Applicative functor
 
Clojure
ClojureClojure
Clojure
 
Kompira開発者が教えるジョブフローTips7選_Kompass発表資料20240306.pptx
Kompira開発者が教えるジョブフローTips7選_Kompass発表資料20240306.pptxKompira開発者が教えるジョブフローTips7選_Kompass発表資料20240306.pptx
Kompira開発者が教えるジョブフローTips7選_Kompass発表資料20240306.pptx
 
Goの文法の実例と解説
Goの文法の実例と解説Goの文法の実例と解説
Goの文法の実例と解説
 
C++コンパイラ GCCとClangからのメッセージをお読みください
C++コンパイラ GCCとClangからのメッセージをお読みくださいC++コンパイラ GCCとClangからのメッセージをお読みください
C++コンパイラ GCCとClangからのメッセージをお読みください
 
Pythonで始めるDropboxAPI
Pythonで始めるDropboxAPIPythonで始めるDropboxAPI
Pythonで始めるDropboxAPI
 
PRML 1.5-1.5.5 決定理論
PRML 1.5-1.5.5 決定理論PRML 1.5-1.5.5 決定理論
PRML 1.5-1.5.5 決定理論
 
Project Loom + Project Panama
Project Loom + Project PanamaProject Loom + Project Panama
Project Loom + Project Panama
 
Mincs 日本語版
Mincs 日本語版Mincs 日本語版
Mincs 日本語版
 
Rによる繰り返しの並列処理
Rによる繰り返しの並列処理Rによる繰り返しの並列処理
Rによる繰り返しの並列処理
 
More C++11
More C++11More C++11
More C++11
 

More from Moriyoshi Koizumi

Authentication, Authorization, OAuth, OpenID Connect and Pyramid
Authentication, Authorization, OAuth, OpenID Connect and PyramidAuthentication, Authorization, OAuth, OpenID Connect and Pyramid
Authentication, Authorization, OAuth, OpenID Connect and PyramidMoriyoshi Koizumi
 
All I know about rsc.io/c2go
All I know about rsc.io/c2goAll I know about rsc.io/c2go
All I know about rsc.io/c2goMoriyoshi Koizumi
 
HLSについて知っていることを話します
HLSについて知っていることを話しますHLSについて知っていることを話します
HLSについて知っていることを話しますMoriyoshi Koizumi
 
Pyramidのrendererをカスタマイズする
PyramidのrendererをカスタマイズするPyramidのrendererをカスタマイズする
PyramidのrendererをカスタマイズするMoriyoshi Koizumi
 
Hacking Go Compiler Internals / GoCon 2014 Autumn
Hacking Go Compiler Internals / GoCon 2014 AutumnHacking Go Compiler Internals / GoCon 2014 Autumn
Hacking Go Compiler Internals / GoCon 2014 AutumnMoriyoshi Koizumi
 
よいことも悪いこともぜんぶPHPが教えてくれた
よいことも悪いこともぜんぶPHPが教えてくれたよいことも悪いこともぜんぶPHPが教えてくれた
よいことも悪いこともぜんぶPHPが教えてくれたMoriyoshi Koizumi
 
mod_himoteからはじめよう
mod_himoteからはじめようmod_himoteからはじめよう
mod_himoteからはじめようMoriyoshi Koizumi
 
HPHPは約束の地なのか
HPHPは約束の地なのかHPHPは約束の地なのか
HPHPは約束の地なのかMoriyoshi Koizumi
 
Phjosh(仮)プロジェクト
Phjosh(仮)プロジェクトPhjosh(仮)プロジェクト
Phjosh(仮)プロジェクトMoriyoshi Koizumi
 
LLの虎 semifinal: 殺伐Python
LLの虎 semifinal: 殺伐PythonLLの虎 semifinal: 殺伐Python
LLの虎 semifinal: 殺伐PythonMoriyoshi Koizumi
 

More from Moriyoshi Koizumi (20)

PHP7を魔改造した話
PHP7を魔改造した話PHP7を魔改造した話
PHP7を魔改造した話
 
Authentication, Authorization, OAuth, OpenID Connect and Pyramid
Authentication, Authorization, OAuth, OpenID Connect and PyramidAuthentication, Authorization, OAuth, OpenID Connect and Pyramid
Authentication, Authorization, OAuth, OpenID Connect and Pyramid
 
All I know about rsc.io/c2go
All I know about rsc.io/c2goAll I know about rsc.io/c2go
All I know about rsc.io/c2go
 
HLSについて知っていることを話します
HLSについて知っていることを話しますHLSについて知っていることを話します
HLSについて知っていることを話します
 
Pyramidのrendererをカスタマイズする
PyramidのrendererをカスタマイズするPyramidのrendererをカスタマイズする
Pyramidのrendererをカスタマイズする
 
Hacking Go Compiler Internals / GoCon 2014 Autumn
Hacking Go Compiler Internals / GoCon 2014 AutumnHacking Go Compiler Internals / GoCon 2014 Autumn
Hacking Go Compiler Internals / GoCon 2014 Autumn
 
Uguisudani
UguisudaniUguisudani
Uguisudani
 
よいことも悪いこともぜんぶPHPが教えてくれた
よいことも悪いこともぜんぶPHPが教えてくれたよいことも悪いこともぜんぶPHPが教えてくれた
よいことも悪いこともぜんぶPHPが教えてくれた
 
Ik in action
Ik in actionIk in action
Ik in action
 
Haxeについて
HaxeについてHaxeについて
Haxeについて
 
Gocon2013
Gocon2013Gocon2013
Gocon2013
 
PHP language update 201211
PHP language update 201211PHP language update 201211
PHP language update 201211
 
mod_himoteからはじめよう
mod_himoteからはじめようmod_himoteからはじめよう
mod_himoteからはじめよう
 
HPHPは約束の地なのか
HPHPは約束の地なのかHPHPは約束の地なのか
HPHPは約束の地なのか
 
Pyfes201110
Pyfes201110Pyfes201110
Pyfes201110
 
Phjosh(仮)プロジェクト
Phjosh(仮)プロジェクトPhjosh(仮)プロジェクト
Phjosh(仮)プロジェクト
 
Aaなゲームをjsで
AaなゲームをjsでAaなゲームをjsで
Aaなゲームをjsで
 
Aaなゲームをjsで
AaなゲームをjsでAaなゲームをjsで
Aaなゲームをjsで
 
ctypes拡張モジュール
ctypes拡張モジュールctypes拡張モジュール
ctypes拡張モジュール
 
LLの虎 semifinal: 殺伐Python
LLの虎 semifinal: 殺伐PythonLLの虎 semifinal: 殺伐Python
LLの虎 semifinal: 殺伐Python
 

Goをカンストさせる話

  • 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. 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 の処理に飛ぶ
  • 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. tcase uint16 // total count of scase[]
  • 10. 65535
  • 11. 敵を 65535 体倒すとデスペナルテ 所持ギルの上限は 65 ぐれメタルを 1 回の戦闘で複数体倒しても合計値が 65535 でカウンタ 率を 65535% にしたらダメー 35 ターン経過させると全滅
  • 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. 実験 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. 実験 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. 実験 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. 結果 コンパイルが終わらない CPU100% やがてメモリを食いつくして OOM Killer に殺される OOM Killer のイメージ ( オオアリク イ )
  • 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. 実行結果 ubuntu:gotorture:% go run uint16maxselect.go ready fatal error: selectrecv: too many cases goroutine 1 [running]: runtime.throw(0x521ce0, 0x1a) ...