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
go doSomeThing()
Search
Jérémy Courtial
February 24, 2016
Programming
0
51
go doSomeThing()
Jérémy Courtial
February 24, 2016
Tweet
Share
More Decks by Jérémy Courtial
See All by Jérémy Courtial
sudo give the cloud
mrartichaut
0
25
An introduction to AppSec?
mrartichaut
0
43
Secure by design: introduction to threat modeling
mrartichaut
0
51
Taming secrets with Vault
mrartichaut
0
81
Lead Tech: Empowering the team
mrartichaut
0
45
Web Platform Security
mrartichaut
0
46
Practical Cryptography : Data Encryption
mrartichaut
0
58
Practical Cryptography : Password Hashing
mrartichaut
1
71
HTTP/2 : One connection to rule them all
mrartichaut
1
59
Other Decks in Programming
See All in Programming
ファインディLT_ポケモン対戦の定量的分析
fufufukakaka
0
490
ファインディの テックブログ爆誕までの軌跡
starfish719
2
1.1k
『GO』アプリ データ基盤のログ収集システムコスト削減
mot_techtalk
0
120
Amazon S3 TablesとAmazon S3 Metadataを触ってみた / 20250201-jawsug-tochigi-s3tables-s3metadata
kasacchiful
0
120
Kubernetes History Inspector(KHI)を触ってみた
bells17
0
220
Grafana Cloudとソラカメ
devoc
0
140
iOSエンジニアから始める visionOS アプリ開発
nao_randd
3
130
Honoをフロントエンドで使う 3つのやり方
yusukebe
7
3.1k
XStateを用いた堅牢なReact Components設計~複雑なClient Stateをシンプルに~ @React Tokyo ミートアップ #2
kfurusho
1
870
Boost Performance and Developer Productivity with Jakarta EE 11
ivargrimstad
0
120
Honoのおもしろいミドルウェアをみてみよう
yusukebe
1
200
Java Webフレームワークの現状 / java web framework at burikaigi
kishida
9
2.2k
Featured
See All Featured
RailsConf 2023
tenderlove
29
1k
StorybookのUI Testing Handbookを読んだ
zakiyama
28
5.5k
実際に使うSQLの書き方 徹底解説 / pgcon21j-tutorial
soudai
174
51k
Keith and Marios Guide to Fast Websites
keithpitt
411
22k
Building Applications with DynamoDB
mza
93
6.2k
The Art of Programming - Codeland 2020
erikaheidi
53
13k
Building Better People: How to give real-time feedback that sticks.
wjessup
366
19k
4 Signs Your Business is Dying
shpigford
182
22k
The Power of CSS Pseudo Elements
geoffreycrofte
75
5.5k
Agile that works and the tools we love
rasmusluckow
328
21k
Fight the Zombie Pattern Library - RWD Summit 2016
marcelosomers
233
17k
A Modern Web Designer's Workflow
chriscoyier
693
190k
Transcript
go doSomething() author := "Jérémy Courtial"
// Pragmatic & productive // language for efficient // softwares
type GoLang struct { … }
go.creationYear = "2007" go.authors = []Author{ "Robert Griesemer", "Rob Pike",
"Ken Thompson"}
go.users = []Company{ "Google", "Docker" "SoundCloud", "Dropbox", "Facebook", "CoreOS", "Cloudflare",
… }
go := Language{ memManagement: gc, packaging: fatBinary, crossPlatform: true
…
… paradigm: imperative, typeSystem: static-inferred, licence: openSource }
import "fmt"
import "fmt" func main() { }
import "fmt" func main() { msg := "Hello, World" }
import "fmt" func main() { msg := "Hello, World" fmt.Println(msg)
}
// Go has interface type Human interface { SayHello() }
// Struct is a class equiv. type HomoSapiens struct {
Name string Age int }
func (hs HomoSapiens) SayHello { }
func (hs HomoSapiens) SayHello { fmt.Println("Hi, i'm", hs.Name) }
// Now HomoSapiens implements Human func (hs HomoSapiens) SayHello {
fmt.Println("Hi, i'm", hs.Name) }
/* "Favor 'object composition' over 'class inheritance'." Design Patterns, GoF,
1995 */
type Robot interface { DestroyHumanity() }
type Cyborg struct { Human Robot gadgets []Gadget }
t800 := Cyborg { }
t800 := Cyborg { human: HumanImpl{}, }
t800 := Cyborg { human: HumanImpl{}, robot: RobotImpl{}, }
t800 := Cyborg { human: HumanImpl{}, robot: RobotImpl{}, gadgets: lethalGadgets,
}
t800.SayHello() t800.DestroyHumanity()
// golang.org/doc/effective_go.html
go.missings = []Feature{ }
go.missings = []Feature{ "Generics", }
go.missings = []Feature{ "Generics", "Pointer Arithmetic", }
go.missings = []Feature{ "Generics", "Pointer Arithmetic", "try/catch", }
go.missings = []Feature{ "Generics", "Pointer Arithmetic", "try/catch", "Implicit Conversions"}
go.tools = []Tool{ "go build", "go fmt", "go get", "go
vet", … }
go.stdLib = []Package{ "net/http", "crypto/aes", "encoding/json", "sort", "bytes", "compress/gzip", "image/png",
"net/html", … }
func NewCipher(key []byte) (cipher.Block, error) type Block interface {
BlockSize() int Encrypt(dst, src []byte) Decrypt(dst, src []byte) }
func main() { http.HandleFunc("/hi", func(w http.ResponseWriter, r *http.Request ) {
msg := map[string]string {"msg": "Hello, World!"} j, _ := json.Marshal(msg) w.Write(j) }) http.ListenAndServe(":8080", nil) }
go.concurrency = LigthAndFastImpl{}
go doSomthingForAWhile()
/* Don't communicate by sharing, share by communicating. */
// Instanciates a channel of strings c := make(chan string)
go work(c)
func work(c chan string) { }
func work(c chan string) { for { } }
func work(c chan string) { for { msg := <-
c } }
func work(c chan string) { for { msg := <-
c fmt.Println(msg) } }
c <- "Hello World!" time.Sleep(5) c <- "Have a nice
day!" time.Sleep(5) c <- "Bye bye!"
func work(quit, c chan int) { }
func work(quit, c chan int) { select { } }
func work(quit, c chan int) { select { case n
:= <- c : } }
func work(quit, c chan int) { select { case n
:= <- c : process(n) } }
func work(quit, c chan int) { select { case n
:= <- c : process(n) case <- quit : } }
func work(quit, c chan int) { select { case n
:= <- c : process(n) case <- quit : return } }
// Why Go's concurrency is special ?
define("C10k problem")
// Most evident tool type Thread struct { … }
/* Be naive : One thread per connection */
for { }
for { conn := tcp.accept() }
for { conn := tcp.accept() newThread() }
for { conn := tcp.accept() newThread().run( func() { }) }
for { conn := tcp.accept() newThread().run( func() { handleConnection(conn) })
}
#BEGIN JAVA #END JAVA // Quick & dirty POC
#BEGIN JAVA #END JAVA while (true) { } // Quick
& dirty POC
#BEGIN JAVA #END JAVA while (true) { new Thread(() ->
{ }); } // Quick & dirty POC
#BEGIN JAVA #END JAVA while (true) { new Thread(() ->
{ sleep(Long.MAX_VALUE); }); } // Quick & dirty POC
#BEGIN JAVA #END JAVA while (true) { new Thread(() ->
{ sleep(Long.MAX_VALUE); }); } // What will happen ?
Exception in thread "main" java.lang.OutOfMemoryError: unable to create new native
thread at java.lang.Thread.start0(Native Method) at java.lang.Thread.start(Thread.java:714) at Test.main(Test.java:19) $ javac Test.java && java Test
/* - Each thread has is own stack - Stack's
size is hard to predict => alloc ~1 Mo per thread */
|- — — — — — — - - -
- -| | Thread Stack 1 | |- - - - - - - - - - - -| | . | | . | | . | | . | | . | | . | | . | | . | | . | |_ _ _ _ _ _ _ _ _ _ _ _|
|- — — — — — — - - -
- -| | Thread Stack 1 | |- - - - - - - - - - - -| | Guard Page | | — — — — — — — - - - - | | . | | . | | . | | . | | . | | . | | . | |_ _ _ _ _ _ _ _ _ _ _ _|
|- — — — — — — - - -
- -| | Thread Stack 1 | |- - - - - - - - - - - -| | Guard Page | | — — — — — — — - - - - | | Thread Stack 2 | |- - - - - - - - - - - -| | . | | . | | . | | . | | . | |_ _ _ _ _ _ _ _ _ _ _ _|
|- — — — — — — - - -
- -| | Thread Stack 1 | |- - - - - - - - - - - -| | Guard Page | | — — — — — — — - - - - | | Thread Stack 2 | |- - - - - - - - - - - -| | Guard Page | |- - - - - - - - - - - -| | . | | . | | . | |_ _ _ _ _ _ _ _ _ _ _ _|
// Let's try something else … pool := NewThreadPool(n)
pool.submit(work)
work := func() { // Blocks until done … readFromNetwork()
}
if pool.hasAvailableThread == false { gameOver() }
// We need different tools IO.asynchronous = true
/* The Hollywood Principle : "Don't call us, we'll call
you" */
b := readFromNetwork() //Block here /* With synchronous I/O */
readFromNetwork(func(b []byte) { //Call when data are available }) /*
With asynchronous I/O */
// Let's try something else … type EventDriven struct {
… }
// Event Driven // Always use async I/O // Considers
I/O as events producers // Events are gathered by a loop
const ( NewConnectionEvent = 1 DataAvailableEvent = 2 DataSentEvent =
3 … )
type Event struct { type EventType callback func() result []byte
}
loop := NewEventLoop() thread.run(loop)
func (l loop) run() { }
func (l loop) run() { for { } }
func (l loop) run() { for { events := os.GatherEvents()
} }
func (l loop) run() { for { events := os.GatherEvents()
l.dispatch(events) } }
func (l loop) dispatch(e []Event) { }
func (l loop) dispatch(e []Event) { for event := range
e { } }
func (l loop) dispatch(e []Event) { for event := range
e { event.callback(e.result) } }
// Drawbacks
// Callbacks hells
s.onNewConnection(func(…){ … }).onDataAvailable(func(…){ … }) s.sendData(data, func(…){ … })
// Singled threaded // Bad for vertical scaling thread.run(loop)
// We need different tools
|- — — — — — — - - -
- -| | | | | | | | | | | |- - - - - - - - - - - -| | | | | | | | | | | |_ _ _ _ _ _ _ _ _ _ _ _| // User space // Kernel Space
|- — — — — — — - - -
- -| | | | | | | | | | | |- - - - - - - - - - - -| | | | | | | | | | Process/Mem management| |_ _ _ _ _ _ _ _ _ _ _ _| // User space // Kernel Space
|- — — — — — — - - -
- -| | | | | | | | | | | |- - - - - - - - - - - -| | | | | | Drivers | | | | Process/Mem management| |_ _ _ _ _ _ _ _ _ _ _ _| // User space // Kernel Space
|- — — — — — — - - -
- -| | | | | | | | | | | |- - - - - - - - - - - -| | SysCall Interface | | | | Drivers | | | | Process/Mem management| |_ _ _ _ _ _ _ _ _ _ _ _| // User space // Kernel Space
|- — — — — — — - - -
- -| | Applications | | | | | | | | | |- - - - - - - - - - - -| | SysCall Interface | | | | Drivers | | | | Process/Mem management| |_ _ _ _ _ _ _ _ _ _ _ _| // User space // Kernel Space
|- — — — — — — - - -
- -| | Applications | | | | Daemons | | | | | |- - - - - - - - - - - -| | SysCall Interface | | | | Drivers | | | | Process/Mem management| |_ _ _ _ _ _ _ _ _ _ _ _| // User space // Kernel Space
|- — — — — — — - - -
- -| | Applications | | | | Daemons | | | | Librairies | |- - - - - - - - - - - -| | SysCall Interface | | | | Drivers | | | | Process/Mem management| |_ _ _ _ _ _ _ _ _ _ _ _| // User space // Kernel Space
|- — — — — — — - - -
- -| | | | | | NewOSThread() | | | | | |- — — — — — — - - - - -| | | | | | | | | | | |_ _ _ _ _ _ _ _ _ _ _ _| // Kernel threads
|- — — — — — — - - -
- -| | | | | | NewOSThread() | | | | | | |- - - - - | - - - - - -| | ∨ | | | | kernel_thread(…) | | | | | |_ _ _ _ _ _ _ _ _ _ _ _| // Kernel threads
|- — — — — — — - - -
- -| | | | User Thread 1 | | | | | | | |- — — — — — — - - - - -| | | | | | | | | | | |_ _ _ _ _ _ _ _ _ _ _ _| /* Users threads */
|- — — — — — — - - -
- -| | | | User Thread 1 | | User Thread 2 | | | | | |- — — — — — — - - - - -| | | | | | | | | | | |_ _ _ _ _ _ _ _ _ _ _ _| /* Users threads */
|- — — — — — — - - -
- -| | | | User Thread 1 | | User Thread 2 | | User Thread 3 | | | |- — — — — — — - - - - -| | | | | | | | | | | |_ _ _ _ _ _ _ _ _ _ _ _| /* Users threads */
|- — — — — — — - - -
- -| | — — — — — — — — | | | User Thread 1 | | | | User Thread 2 | | | | User Thread 3 | | | - - - - - - - - | |- — — — — — — - - - - -| | | | | | | | | | | |_ _ _ _ _ _ _ _ _ _ _ _| /* Users threads */
|- — — — — — — - - -
- -| | — — — — — — — — | | | User Thread 1 | | | | User Thread 2 | | | | User Thread 3 | | | - - - | - - - - | |- - - - - | - - - - - -| | ∨ | | | | kernel_thread(…) | | | | | |_ _ _ _ _ _ _ _ _ _ _ _| /* Users threads N:M */
// User Threads // Cheaper than kernel threads // Backed
by one or more K threads // App is responsible for scheduling
goroutines == User threads
// Goroutines are // Cheap in memory : 2 Ko
only // Cheap to create/destroy // Cheap to switch
for { }
for { conn := tcp.accept() }
for { conn := tcp.accept() go handleConnection(conn) }
func handleConnection(c net.Conn){ }
func handleConnection(c net.Conn){ data := c.Read(4096) }
func handleConnection(c net.Conn){ data := c.Read(4096) response := process(data) }
func handleConnection(c net.Conn){ data := c.Read(4096) response := process(data) c.Write(response)
}
data := c.Read(4096)
data := c.Read(4096) // Blocks the goroutine until // data
are available
data := c.Read(4096) // But don't block the thread //
and other goroutines
// Goroutines scheduling // Scheduling is cooperative // Blocking IOs
used as switch point // When a gorountine blocks another // is wake up
/* Now you can be naive : One thread per
connection */ goroutine
/* The gopher way : Focus on what you want
to do */
// Let's go ?
// October 10, 2016 · PARIS
/* Bibliography golang.org tour.golang.org talks.golang.org */
/* Bibliography The Go scheduler How Goroutines work Performance Without
The Event Loop */
// Thanks // Questions ?