woo: writing a fast web server
TRANSCRIPT
Woo: Writing a fast web server
Lisp Meetup #25 Eitaro Fukamachi
Thank you for coming.
I’m Eitaro Fukamachi @nitro_idiot fukamachi
Looking for a Common Lisp job? We’re hiring!
https://www.wantedly.com/projects/15144
(and 'web-application-engineer 'common-lisper)
(and 'web-application-engineer 'common-lisper)
(and 'web-application-engineer 'common-lisper)
server :(
Woo
Woo = Ultra Monster??
http://ultra.wikia.com/wiki/Woo_(kaiju)
Woo = Ultra Monster??
Woo = Ultra Monster??
• Web server for Clack applications
• HTTP/1.x
• Built on top of fast-http, QURI, libev
• Similar to Wookie, but even faster
Woo
Woo
(woo:run (lambda (env) ‘(200 (:content-type “text/plain”) (“Hello, World”))))
(clack:clackup (lambda (env) ‘(200 (:content-type “text/plain”) (“Hello, World”))) :server :woo)
Run with Clack
Let me tell why I could make it so fast.
3 difficult things in web servers
3 difficult things
• Network I/O is the largest bottleneck
• Need to handle a vast amount of requests at once
• Need to handle various HTTP clients (fast / slow / unstable)
Why fast?
1. Better architecture
2. The libev event library
3. Fast HTTP & URI parsing
Reason 1: Better architecture
2 architectures: Prefork vs Event-driven
Prefork
Worker thread
Worker thread
Worker thread
master thread
Requests
accept connections
Responses
• Simple
• Fast for little simultaneous connections
• ex) Hunchentoot, Unicorn, Apache
Prefork
Worker thread
Worker thread
Worker thread
master thread
Requests
accept connections
Responses • Slow client can cause performance issue.
• like Mobile users
• Slowloris attack
blocking!
・・・
Problem
Event-driven• Handle many
clients at the same time
• Asnyc ACCEPT/READ/WRITE
• ex) Woo, Wookie, Tornado, nginxServer process
(single-threaded)
Event loop
Event-driven
• Single-threaded
Problem
Server process (single-threaded)
Event loop
Woo took another way: Multithreaded event-driven
Multithreaded event-driven
Server process
Event loop
listen on the same file descriptor
Server process
Event loop
Server process
Event loop
Reason 2: The libev event library
libev
• Wrapper of epoll, kqueue, POSIX select, poll
• Thin
• Fast
• Poor Windows support
• I don’t think people run a web server on Windows
First choice: cl-async
• Wookie built on top of cl-async
• cl-async was used to use libevent2
• Node.js uses libuv
• libevent2 might be the bottleneck
• cl-async has moved to libuv now
Reason 3: Fast HTTP & URI parsing
HTTP parsing can be a bottleneck
• Wookie's largest bottleneck is HTTP parsing
• http-parse (uses regular expression)
• fast-http (byte to byte parser)
• 135 times faster than http-parse
• http://slideshare.net/fukamachi/writing-a-fast-http-parser
URI parsing can be a bottleneck
• Wookie & Woo parses URI for dispatching
• PURI is *not really* fast
• QURI
• 6 times faster than PURI
Goal
Goal: What is fast enough?
• The initial goal was “Beating Node.js”
• Done
• Being the fastest web server in Common Lisp
• Done
Got a great Pull Request
Future tasks
Future tasks
• Multithread performance
• SSL support
• HTTP/2 support
Multithread performance
Status
Photo by Robert Couse-Baker licensed under the CC BY 2.0
Photo by Robert Couse-Baker licensed under the CC BY 2.0
Status
• Still alpha version
• Use at your own risk
• Tested with SBCL on Linux/Mac OS
• The latest bug:
• Cannot run in Americas (TZ problem)
Thanks.
EITARO FUKAMACHI 8arrow.org @nitro_idiot fukamachi