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
GitHub Actions × RAGでコードレビューの検証の結果
sho_000
0
240
WebDriver BiDiとは何なのか
yotahada3
1
140
社内フレームワークとその依存性解決 / in-house framework and its dependency management
vvakame
1
550
時計仕掛けのCompose
mkeeda
1
280
DevinとCursorから学ぶAIエージェントメモリーの設計とMoatの考え方
itarutomy
1
640
Grafana Loki によるサーバログのコスト削減
mot_techtalk
1
110
How mixi2 Uses TiDB for SNS Scalability and Performance
kanmo
30
11k
DROBEの生成AI活用事例 with AWS
ippey
0
130
CloudNativePGがCNCF Sandboxプロジェクトになったぞ! 〜CloudNativePGの仕組みの紹介〜
nnaka2992
0
220
技術を根付かせる / How to make technology take root
kubode
1
240
一休.com のログイン体験を支える技術 〜Web Components x Vue.js 活用事例と最適化について〜
atsumim
0
110
『品質』という言葉が嫌いな理由
korimu
0
160
Featured
See All Featured
A Modern Web Designer's Workflow
chriscoyier
693
190k
Practical Orchestrator
shlominoach
186
10k
Embracing the Ebb and Flow
colly
84
4.6k
Put a Button on it: Removing Barriers to Going Fast.
kastner
60
3.7k
How to Ace a Technical Interview
jacobian
276
23k
Speed Design
sergeychernyshev
25
780
Understanding Cognitive Biases in Performance Measurement
bluesmoon
27
1.5k
Site-Speed That Sticks
csswizardry
3
370
Building an army of robots
kneath
302
45k
Save Time (by Creating Custom Rails Generators)
garrettdimon
PRO
29
1k
Building Better People: How to give real-time feedback that sticks.
wjessup
366
19k
Java REST API Framework Comparison - PWX 2021
mraible
28
8.4k
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 ?