Ruby Advantages
Unicode done right
Builtin continuation - Fiber
And...
""
.
l
e
n
g
t
h
Slide 6
Slide 6 text
Fast
Slide 7
Slide 7 text
How To Build A High Performance Server
Slide 8
Slide 8 text
How To Build An Async Server
Slide 9
Slide 9 text
How To Build An Async Server Yet Providing Good
API
Slide 10
Slide 10 text
Study The Background
Slide 11
Slide 11 text
No content
Slide 12
Slide 12 text
The Bottle Neck
Client Side Of View
IO bound - network is slow
CPU bound - complex page rendering
Server load - wait for other requests to finish
Slide 13
Slide 13 text
The Bottle Neck
Server Side Of View
IO bound - visiting database / oauth is slow
CPU bound - context switch
Slide 14
Slide 14 text
Scaling
Increase App Throughput
Reduce server side IO-waiting is the most effective way
Create less threads, to avoid context switching
Slide 15
Slide 15 text
Learn From Existing Solutions
Slide 16
Slide 16 text
Chances To Ruby
Slide 17
Slide 17 text
Limited Server Objects
Slide 18
Slide 18 text
Many Crazy Clients
Slide 19
Slide 19 text
Multiplexing
Slide 20
Slide 20 text
Single Threaded
One Client, One Process, Prefork
unicorn -- multiplex with accept
thin -- multiplex with load balancer
Slide 21
Slide 21 text
Multithreaded
One Client, One Thread, No Prefork
puma, recommended for rails4
A simple way to implement is to use POSIX functions with callbacks: aio_read(),
aio_write()
Slide 22
Slide 22 text
Single Threaded And Event Loop
One Client, One Event Context, Prefork
nginx, redis, nodejs, twisted, eventmachine
Slide 23
Slide 23 text
Thread Pool On Event Loop
One Client, One Event Context, No Prefork
erlang, golang, scala actors
Slide 24
Slide 24 text
Hello World
Slide 25
Slide 25 text
TCPSocket In 5 Minutes
client
server
receive
send
T
C
P
S
o
c
k
e
t
.
n
e
w h
o
s
t
, p
o
r
t
T
C
P
S
e
r
v
e
r
.
n
e
w h
o
s
t
, p
o
r
t
s
o
c
k
e
t
.
r
e
a
d
s
o
c
k
e
t
.
r
e
a
d
_
n
o
n
b
l
o
c
k
s
o
c
k
e
t
.
w
r
i
t
e
s
o
c
k
e
t
.
w
r
i
t
e
_
n
o
n
b
l
o
c
k
Slide 26
Slide 26 text
Hello World HTTP Server
s
e
r
v
e
r = T
C
P
S
e
r
v
e
r
.
n
e
w '
l
o
c
a
l
h
o
s
t
'
, 4
0
0
0
l
o
o
p d
o
c = s
e
r
v
e
r
.
a
c
c
e
p
t
c <
< "
H
T
T
P
/
1
.
1 2
0
0 O
K
C
o
n
t
e
n
t
-
L
e
n
g
t
h
: 1
2
H
e
l
l
o w
o
r
l
d
!
"
c
.
c
l
o
s
e
e
n
d
Slide 27
Slide 27 text
Make It Fast
Slide 28
Slide 28 text
NonBlocking Our Loop
l
o
o
p d
o
c
l
i
e
n
t = s
e
r
v
e
r
.
a
c
c
e
p
t
T
h
r
e
a
d
.
n
e
w d
o
.
.
.
e
n
d
e
n
d
Slide 29
Slide 29 text
Threads Are Outdated
Lets Use System Events
Slide 30
Slide 30 text
Multiplexing Functions
select
poll
I
O
.
s
e
l
e
c
t r
, w
, e
r
r
, t
i
m
e
o
u
t
I
O
.
p
o
l
l f
d
s
, t
i
m
e
o
u
t
Slide 31
Slide 31 text
System Events
Linux For Example
poll - iterate check all fds
epoll - is more effective and provides more options
Slide 32
Slide 32 text
Epoll In 5 Minutes
s
u
d
o a
p
t
-
g
e
t i
n
s
t
a
l
l m
a
n
p
a
g
e
s
-
d
e
v
m
a
n e
p
o
l
l
Slide 33
Slide 33 text
Epoll In 5 Minutes
register event:
retrieve event:
e
p
o
l
l
_
c
t
l
(
)
e
p
o
l
l
(
)
Slide 34
Slide 34 text
Cons
Ruby does not ship with epoll API.
You need to wrap it with C-ext.
Slide 35
Slide 35 text
Loop With Epoll
l
o
o
p d
o
e
v
e
n
t = e
p
o
l
l
(
t
i
m
e
o
u
t
)
i
f f
r
o
m
_
s
e
r
v
e
r
?
(
e
v
e
n
t
)
c
o
n
n
e
c
t
i
o
n = s
e
r
v
e
r
.
a
c
c
e
p
t
e
l
s
e
c
o
n
n
e
c
t
i
o
n = f
i
n
d
_
c
o
n
n
_
b
y
(
e
v
e
n
t
)
e
n
d
.
.
. # r
e
s
u
m
e p
r
o
c
e
s
s
i
n
g
e
n
d
Slide 36
Slide 36 text
How To Make It Resumable?
Slide 37
Slide 37 text
Eventmachine
async web server
Slide 38
Slide 38 text
clients are multiplexed to
you define callbacks for readable events:
E
M
:
:
C
o
n
n
e
c
t
i
o
n
d
e
f r
e
c
e
i
v
e
_
d
a
t
a
(
d
a
t
a
)
Slide 39
Slide 39 text
"Resume Processing"
c
o
n
n
e
c
t
i
o
n
.
r
e
c
e
i
v
e
_
d
a
t
a r
e
a
d
_
n
o
n
b
l
o
c
k
Slide 40
Slide 40 text
Make It Good
Slide 41
Slide 41 text
How EM Send_data Works
write to socket, if the socket can’t take any more, append the rest to a buffer chain
when the socket becomes writable again (IO event), try consume the buffer chain
Slide 42
Slide 42 text
Pitfalls
Callbacks Are Not Sufficient
avoid loss of chained buffers
avoid infinite recursion when registering events in callback:
c
l
o
s
e
_
c
o
n
n
e
c
t
i
o
n
_
a
f
t
e
r
_
w
r
i
t
i
n
g
E
M
.
n
e
x
t
_
t
i
c
k
{ .
.
. }
Slide 43
Slide 43 text
Resume Processing With Fiber
Fiber was the “Thread” in 1.8
Like thread, but lighter, pausable, and no need to lock
Slide 44
Slide 44 text
Example
f
i
b
e
r = F
i
b
e
r
.
n
e
w d
o
i = 0
l
o
o
p d
o
F
i
b
e
r
.
y
i
e
l
d i +
= 1
e
n
d
e
n
d
f
i
b
e
r
.
r
e
s
u
m
e #
=
> 1
f
i
b
e
r
.
r
e
s
u
m
e #
=
> 2
Slide 45
Slide 45 text
Read With Fiber
d
e
f r
e
a
d
_
w
i
t
h
_
f
i
b
e
r
r
e
s
u
l
t = '
'
w
h
i
l
e b
u
f
f
e
r = r
e
a
d
_
n
o
n
b
l
o
c
k
r
e
s
u
l
t <
< b
u
f
f
e
r
i
f n
o
t
h
i
n
g t
o r
e
a
d
F
i
b
e
r
.
y
i
e
l
d :
r
e
a
d
i
n
g
!
e
n
d
e
n
d
r
e
s
u
l
t
e
n
d
Slide 46
Slide 46 text
Write With Fiber
d
e
f w
r
i
t
e
_
w
i
t
h
_
f
i
b
e
r c
o
n
t
e
n
t
l
o
o
p d
o
w
r
i
t
e
_
n
o
n
b
l
o
c
k c
o
n
t
e
n
t
c
o
n
t
e
n
t = u
n
w
r
i
t
t
e
n p
a
r
t o
f c
o
n
t
e
n
t
b
r
e
a
k i
f c
o
n
t
e
n
t
.
e
m
p
t
y
?
F
i
b
e
r
.
y
i
e
l
d :
w
r
i
t
i
n
g
!
e
n
d
e
n
d
Slide 47
Slide 47 text
Recall Our Loop
l
o
o
p d
o
e
v
e
n
t = e
p
o
l
l
(
t
i
m
e
o
u
t
)
i
f f
r
o
m
_
s
e
r
v
e
r
?
(
e
v
e
n
t
)
c
o
n
n
e
c
t
i
o
n = s
e
r
v
e
r
.
a
c
c
e
p
t
e
l
s
e
c
o
n
n
e
c
t
i
o
n = f
i
n
d
_
c
o
n
n
_
b
y
(
e
v
e
n
t
)
e
n
d
.
.
. # r
e
s
u
m
e p
r
o
c
e
s
s
i
n
g
e
n
d
Slide 48
Slide 48 text
l
o
o
p d
o
e
v
e
n
t = e
p
o
l
l
(
t
i
m
e
o
u
t
)
i
f f
r
o
m
_
s
e
r
v
e
r
?
(
e
v
e
n
t
)
c
o
n
n
e
c
t
i
o
n = s
e
r
v
e
r
.
a
c
c
e
p
t
f
i
b
e
r = F
i
b
e
r
.
n
e
w {
.
.
. r
e
a
d
_
w
i
t
h
_
f
i
b
e
r
.
.
. w
r
i
t
e
_
w
i
t
h
_
f
i
b
e
r
}
e
l
s
e
f
i
b
e
r = f
i
n
d
_
f
i
b
e
r
_
b
y
(
e
v
e
n
t
)
e
n
d
f
i
b
e
r
.
r
e
s
u
m
e
e
n
d
Slide 49
Slide 49 text
Summary
Slide 50
Slide 50 text
Network latency and C10k leads to async solutions.
With Fiber it can be callback-free.
Slide 51
Slide 51 text
In concept it is simple.
In practice it is complex: protocols, IO exceptions, ...
Slide 52
Slide 52 text
Product
github.com/luikore/nyara
faster than sinatra/expressjs in hello world benchmarks