Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
go doSomeThing()
Search
Sponsored
·
Your Podcast. Everywhere. Effortlessly.
Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
→
Jérémy Courtial
February 24, 2016
Programming
59
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
go doSomeThing()
Jérémy Courtial
February 24, 2016
More Decks by Jérémy Courtial
See All by Jérémy Courtial
sudo give the cloud
mrartichaut
0
31
An introduction to AppSec?
mrartichaut
0
55
Secure by design: introduction to threat modeling
mrartichaut
0
63
Taming secrets with Vault
mrartichaut
0
100
Lead Tech: Empowering the team
mrartichaut
0
54
Web Platform Security
mrartichaut
0
55
Practical Cryptography : Data Encryption
mrartichaut
0
73
Practical Cryptography : Password Hashing
mrartichaut
1
81
HTTP/2 : One connection to rule them all
mrartichaut
1
74
Other Decks in Programming
See All in Programming
WebMCP Challenge に星空観察アプリで参加した話
okajun35
0
120
The Good Stuff, Not the Slop: Engineering High-Quality Android Apps with Modern AI Tooling
danybony
1
230
Gmail/Google DriveをトリガーにAIエージェントを動かそう! / Run AI agents with Gmail/Google Drive as triggers!
har1101
3
490
初心者DevRelとして参加者だった私が、DevRel Talks!#2に登壇するまでにしてきたこと
sokohirai
0
360
【DroidKaigi 2026】「アクセシビリティを利用するとき、 アクセシビリティもまたこちらを利用している」 〜マルウェアによる攻撃と防衛について〜
halunoyo
0
430
typoなんかねぇよ
raspython3
0
680
Claude Codeを組織的に動かして月400PRを実現した話
happy_ryo
0
260
AIは賢い。でも実行環境は? CLIおじさんがAI時代に伝えたいこと ~ CLIおじさんがAI時代に伝えたいこと ~
curekoshimizu
1
220
AI Agent時代のリアーキテクチャ戦略と実践
hokaccha
6
3.4k
世界の中心で、AI(App Intents)をさけぶ ー App Intents中心設計の実践ガイド
touyou
0
310
新人はどこまで自力でやり、どこからAIに頼るべきか/エンジニア育成に向き合う_先輩たちの悩みと知見共有会
toppan_digital_dev
1
590
Hello, Hiroshima Geospatial Data! — Exploring DoboX with Python
ra0kley
0
180
Featured
See All Featured
Navigating the moral maze — ethical principles for Al-driven product design
skipperchong
2
520
Learning to Love Humans: Emotional Interface Design
aarron
275
41k
Why You Should Never Use an ORM
jnunemaker
PRO
61
10k
Public Speaking Without Barfing On Your Shoes - THAT 2023
reverentgeek
1
560
Redefining SEO in the New Era of Traffic Generation
szymonslowik
1
410
jQuery: Nuts, Bolts and Bling
dougneiner
66
8.6k
Tips & Tricks on How to Get Your First Job In Tech
honzajavorek
1
730
So, you think you're a good person
axbom
PRO
2
2.1k
Future Trends and Review - Lecture 12 - Web Technologies (1019888BNR)
signer
PRO
0
3.7k
Bash Introduction
62gerente
615
220k
個人開発の失敗を避けるイケてる考え方 / tips for indie hackers
panda_program
123
22k
The Psychology of Web Performance [Beyond Tellerrand 2023]
tammyeverts
49
3.5k
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 ?