SlideShare ist ein Scribd-Unternehmen logo
1 von 38
Downloaden Sie, um offline zu lesen
LIBUV, NODEJS
AND EVERYTHING
IN BETWEEN
Saúl Ibarra Corretgé
@saghul
LIBUV, NODE AND EVERYTHING IN BETWEEN
HIYA!
▸ @saghul
▸ Bilbao — Amsterdam — Liverpool
▸ libuv core janitor
▸ Nodejs collaborator
▸ Recently obsessed with 3D printing
▸ AMA!
ASYNC I/O 101
LIBUV, NODE AND EVERYTHING IN BETWEEN
ASYNC I/O 101
from __future__ import print_function
import socket
server = socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM)
server.bind(('127.0.0.1', 1234))
server.listen(10)
print("Server listening on: {}".format(server.getsockname()))
client, addr = server.accept()
print("Client connected: {}".format(addr))
while True:
data = client.recv(4096)
if not data:
print("Client has disconnected")
break
client.send(data.upper())
server.close()
LIBUV, NODE AND EVERYTHING IN BETWEEN
CRAP, IT BLOCKS!
▸ Only one client at a time!
▸ Scaling up
▸ Threads
▸ I/O multiplexing
▸ http://www.kegel.com/c10k.html
▸ http://www.slideshare.net/saghul/how-do-eventloops-
work-in-python
LIBUV, NODE AND EVERYTHING IN BETWEEN
THREADS?
▸ Overhead: stack size, scheduling
▸ Synchronisation
▸ It’s still a good solution in some cases
LIBUV, NODE AND EVERYTHING IN BETWEEN
I/O MULTIPLEXING TO THE RESCUE
▸ Single thread
▸ Examine and wait for i/o in multiple sockets at once
▸ When a socket is ready the operation won’t block
▸ Good for i/o bound tasks, bad for CPU intensive tasks
LIBUV, NODE AND EVERYTHING IN BETWEEN
I/O MULTIPLEXING 101
1. Put the fd in non-blocking mode
2. Add the fd to the i/o multiplexor
3. Wait for some time
4. Perform read / writes on the fd, it won’t block!
5. Profit?
LIBUV, NODE AND EVERYTHING IN BETWEEN
I/O MULTIPLEXING APIS
▸ Different APIs: select, poll, epoll, kqueue, …
▸ Unix shares a common model: readiness
▸ Windows uses a completion model
▸ IOCP is The Good Stuff
LIBUV
LIBUV, NODE AND EVERYTHING IN BETWEEN
LIBUV
▸ Small (relatively) C library: ~30K LOC (without tests)
▸ Extensive test suite
▸ Designed for C programs that miss the joy of JavaScript
callback hell
▸ Used by Node and many other projects:

https://github.com/libuv/libuv/wiki/Projects-that-use-libuv
LIBUV, NODE AND EVERYTHING IN BETWEEN
LIBUV: FEATURES
▸ Event loop backed by epoll,
kqueue, IOCP, event ports,
etc.
▸ Timers
▸ Async TCP / UDP sockets
▸ Async named pipes
▸ Async filesystem operations
▸ Async signal handling
▸ Child processes
▸ ANSI escaped TTY
▸ Threading utilities
▸ Coolest logo ever
LIBUV, NODE AND EVERYTHING IN BETWEEN
LIBUV: ARCHITECTURE
LIBUV, NODE AND EVERYTHING IN BETWEEN
LIBUV: THE EVENT LOOP
LIBUV, NODE AND EVERYTHING IN BETWEEN
LIBUV: FILESYSTEM APIS
▸ Follow the Unix style
▸ Executed in a thread pool
▸ http://blog.libtorrent.org/2012/10/asynchronous-disk-io/
LIBUV, NODE AND EVERYTHING IN BETWEEN
LIBUV: A WORD ON THREADS
▸ We only use threads for file i/o and getaddrinfo
▸ Default thread pool size is 4

(runtime env var: UV_THREADPOOL_SIZE)
▸ NOT FOR NETWORK I/O
▸ NOT FOR NETWORK I/O
▸ NOT FOR NETWORK I/O
▸ NOT FOR NETWORK I/O
THE LIBUV EVENT LOOP IS
SINGLE THREADED. THE THREAD
POOL IS ONLY USED FOR FILE I/O.
The libuv police
LIBUV, NODE AND EVERYTHING IN BETWEEN
A CHAT APP,

OF COURSE
LIBUV, NODE AND EVERYTHING IN BETWEEN
A LIBUV CHAT APPLICATION
▸ Simple TCP server application
▸ A twist on libuv-chat by Ben Noordhuis in 2011
▸ Multiple users, single “chat room”
▸ Pokemon, because why not?
▸ https://github.com/saghul/libuv-chat
THE MAKEFILE
all: build
deps/libuv:
git clone --depth 1 https://github.com/libuv/libuv deps/libuv
build/gyp:
git clone --depth 1 https://chromium.googlesource.com/external/gyp build/gyp
out/Makefile: deps/libuv build/gyp
build/gyp/gyp -Duv_library=static_library --depth=$(PWD) --generator-output=$(PWD)/out -Goutput_dir=$(PWD)/out -f make build.gyp
build: out/Makefile
$(MAKE) -C out
clean:
rm -rf out
distclean:
rm -rf build deps out
.PHONY: clean distclean
THE GYP BUILD FILE
# Copyright (c) 2016, Saúl Ibarra Corretgé <saghul@gmail.com>
# Copyright (c) 2012, Ben Noordhuis <info@bnoordhuis.nl>
#
# Permission to use, copy, modify, and/or distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
# gyp -Duv_library=static_library --depth=$PWD --generator-output=$PWD/out -Goutput_dir=$PWD/out -f make build.gyp
{
'targets': [
{
'target_name': 'chat-server',
'type': 'executable',
'dependencies': ['deps/libuv/uv.gyp:libuv'],
'sources': ['src/main.c', 'src/queue.h', 'src/pokemon_names.h'],
}
]
}
INITIALISE AND RUN SERVER
struct user
{
QUEUE queue;
uv_tcp_t handle;
char id[32];
};
static QUEUE users;
int main(void)
{
QUEUE_INIT(&users);
srand(1234);
int r;
uv_tcp_t server_handle;
uv_tcp_init(uv_default_loop(), &server_handle);
struct sockaddr_in addr;
uv_ip4_addr(SERVER_ADDR, SERVER_PORT, &addr);
r = uv_tcp_bind(&server_handle, (const struct sockaddr*) &addr, 0);
if (r < 0)
fatal("uv_tcp_bind", r);
const int backlog = 128;
r = uv_listen((uv_stream_t*) &server_handle, backlog, on_connection);
if (r < 0)
fatal("uv_listen", r);
printf("Listening at %s:%dn", SERVER_ADDR, SERVER_PORT);
uv_run(uv_default_loop(), UV_RUN_DEFAULT);
return 0;
}
HANDLE INCOMING CONNECTIONS
static void on_connection(uv_stream_t* server_handle, int status)
{
assert(status == 0);
int r;
// hurray, a new user!
struct user *user = xmalloc(sizeof(*user));
uv_tcp_init(uv_default_loop(), &user->handle);
r = uv_accept(server_handle, (uv_stream_t*) &user->handle);
if (r < 0)
fatal("uv_accept", r);
// add him to the list of users
QUEUE_INSERT_TAIL(&users, &user->queue);
make_user_id(user);
// now tell everyone, including yourself (to know your name!)
broadcast(NULL, "* A wild %s appeared from %sn", user->id, addr_and_port(user));
// start accepting messages from the user
uv_read_start((uv_stream_t*) &user->handle, on_alloc, on_read);
}
READ INCOMING DATA
static void on_alloc(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf)
{
buf->base = xmalloc(suggested_size);
buf->len = suggested_size;
}
static void on_read(uv_stream_t* handle, ssize_t nread, const uv_buf_t* buf)
{
struct user *user = QUEUE_DATA(handle, struct user, handle);
if (nread == UV_EOF) {
// user disconnected
QUEUE_REMOVE(&user->queue);
uv_close((uv_handle_t*) &user->handle, on_close);
broadcast(NULL, "* %s fled!n", user->id);
} else if (nread > 0) {
// broadcast message
broadcast(user, "%s said: %.*s", user->id, (int) nread, buf->base);
} else {
fprintf(stderr, "on_read: %sn", uv_strerror(nread));
}
free(buf->base);
}
BROADCAST DATA
static void broadcast(const struct user* sender, const char *fmt, ...)
{
QUEUE *q;
char msg[512];
va_list ap;
va_start(ap, fmt);
vsnprintf(msg, sizeof(msg), fmt, ap);
va_end(ap);
QUEUE_FOREACH(q, &users) {
struct user *user = QUEUE_DATA(q, struct user, queue);
if (user != sender) {
unicast(user, msg);
}
}
}
static void unicast(struct user *user, const char *msg)
{
size_t len = strlen(msg);
uv_write_t *req = xmalloc(sizeof(*req) + len);
void *addr = req + 1;
memcpy(addr, msg, len);
uv_buf_t buf = uv_buf_init(addr, len);
uv_write(req, (uv_stream_t*) &user->handle, &buf, 1, on_write);
}
static void on_write(uv_write_t *req, int status)
{
free(req);
}
MISCELLANEOUS FUNCTIONS
static void on_close(uv_handle_t* handle)
{
struct user *user = QUEUE_DATA(handle, struct user, handle);
free(user);
}
static void make_user_id(struct user *user)
{
snprintf(user->id, sizeof(user->id), "%s", pokemon_names[rand() % ARRAY_SIZE(pokemon_names)]);
}
NODE
LIBUV, NODE AND EVERYTHING IN BETWEEN
NODEJS
▸ Server side JavaScript
▸ V8 JavaScript engine
▸ Web inspired async model
▸ Auxiliary libraries: libuv, OpenSSL, c-ares, http_parser, …
LIBUV, NODE AND EVERYTHING IN BETWEEN
PLATFORM LAYER REQUIREMENTS
▸ ASYNC ALL THE THINGS
▸ Completion based (callbacks)
▸ Consistent API for asynchronous network i/o
▸ Filesystem operations
▸ Basic name resolution (getaddrinfo / getnameinfo)
LIBUV, NODE AND EVERYTHING IN BETWEEN
ARCHITECTURE IN NODE 0.4
BINDINGS / WRAPS
JS STANDARD LIBRARY
USER APPLICATIONS
V8 OPENSSL LIBEV LIBEIO …
LIBUV, NODE AND EVERYTHING IN BETWEEN
ARCHITECTURE IN NODE 0.6
BINDINGS / WRAPS
JS STANDARD LIBRARY
USER APPLICATIONS
V8 OPENSSL LIBUV …
LIBEV LIBEIO
LIBUV, NODE AND EVERYTHING IN BETWEEN
ARCHITECTURE IN NODE 0.10 AND ONWARDS
BINDINGS / WRAPS
JS STANDARD LIBRARY
USER APPLICATIONS
V8 OPENSSL LIBUV …
LIBUV IN NODE
LIBUV, NODE AND EVERYTHING IN BETWEEN
LIBUV: THE EVENT LOOP
REMEMBER?
LIBUV, NODE AND EVERYTHING IN BETWEEN
NODE EVENT LOOP
COALESCED, 1 NODE
TIMER != 1 LIBUV
TIMER
RUN
ON A CHECK + IDLE
HANDLE
NEXT TICK CALLBACKS RUN FROM
NODE::MAKECALLBACK
LIBUV, NODE AND EVERYTHING IN BETWEEN
ONION ARCHITECTURE (TM)
net.Socket
TCPWrap
uv_tcp_t
Socket._handle
TCPWrap.handle_
fd / HANDLE
QUESTIONS?
libuv.org
docs.libuv.org
#libuv on IRC
libuv Google Group
#libuv on StackOverflow
QUESTIONS?
@saghul
bettercallsaghul.com

Weitere ähnliche Inhalte

Was ist angesagt?

The linux file system structure
The linux file system structureThe linux file system structure
The linux file system structure
Teja Bheemanapally
 

Was ist angesagt? (20)

show コマンド結果をパースする方法あれこれ #npstudy
show コマンド結果をパースする方法あれこれ #npstudyshow コマンド結果をパースする方法あれこれ #npstudy
show コマンド結果をパースする方法あれこれ #npstudy
 
【続編】その ionice、ほんとに効いてますか?
【続編】その ionice、ほんとに効いてますか?【続編】その ionice、ほんとに効いてますか?
【続編】その ionice、ほんとに効いてますか?
 
Using Kamailio for Scalability and Security
Using Kamailio for Scalability and SecurityUsing Kamailio for Scalability and Security
Using Kamailio for Scalability and Security
 
Docker管理もHinemosで! ~監視・ジョブ機能を併せ持つ唯一のOSS「Hinemos」のご紹介~
Docker管理もHinemosで! ~監視・ジョブ機能を併せ持つ唯一のOSS「Hinemos」のご紹介~Docker管理もHinemosで! ~監視・ジョブ機能を併せ持つ唯一のOSS「Hinemos」のご紹介~
Docker管理もHinemosで! ~監視・ジョブ機能を併せ持つ唯一のOSS「Hinemos」のご紹介~
 
BPF - in-kernel virtual machine
BPF - in-kernel virtual machineBPF - in-kernel virtual machine
BPF - in-kernel virtual machine
 
nftables: the Next Generation Firewall in Linux
nftables: the Next Generation Firewall in Linuxnftables: the Next Generation Firewall in Linux
nftables: the Next Generation Firewall in Linux
 
その ionice、ほんとに効いてますか?
その ionice、ほんとに効いてますか?その ionice、ほんとに効いてますか?
その ionice、ほんとに効いてますか?
 
Dev confus.2020 compliance operator
Dev confus.2020 compliance operatorDev confus.2020 compliance operator
Dev confus.2020 compliance operator
 
きつねさんでもわかるLlvm読書会 第2回
きつねさんでもわかるLlvm読書会 第2回きつねさんでもわかるLlvm読書会 第2回
きつねさんでもわかるLlvm読書会 第2回
 
64ビット対応Dllインジェクション
64ビット対応Dllインジェクション64ビット対応Dllインジェクション
64ビット対応Dllインジェクション
 
C++ マルチスレッド 入門
C++ マルチスレッド 入門C++ マルチスレッド 入門
C++ マルチスレッド 入門
 
QEMU Disk IO Which performs Better: Native or threads?
QEMU Disk IO Which performs Better: Native or threads?QEMU Disk IO Which performs Better: Native or threads?
QEMU Disk IO Which performs Better: Native or threads?
 
Node.js Native ESM への道 〜最終章: Babel / TypeScript Modules との闘い〜
Node.js Native ESM への道  〜最終章: Babel / TypeScript Modules との闘い〜Node.js Native ESM への道  〜最終章: Babel / TypeScript Modules との闘い〜
Node.js Native ESM への道 〜最終章: Babel / TypeScript Modules との闘い〜
 
Uuidはどこまでuuidか試してみた
Uuidはどこまでuuidか試してみたUuidはどこまでuuidか試してみた
Uuidはどこまでuuidか試してみた
 
OpenStack検証環境構築・トラブルシューティング入門 - OpenStack最新情報セミナー 2014年8月
OpenStack検証環境構築・トラブルシューティング入門 - OpenStack最新情報セミナー 2014年8月OpenStack検証環境構築・トラブルシューティング入門 - OpenStack最新情報セミナー 2014年8月
OpenStack検証環境構築・トラブルシューティング入門 - OpenStack最新情報セミナー 2014年8月
 
MySQL 8.0で憶えておいてほしいこと
MySQL 8.0で憶えておいてほしいことMySQL 8.0で憶えておいてほしいこと
MySQL 8.0で憶えておいてほしいこと
 
実環境にTerraform導入したら驚いた
実環境にTerraform導入したら驚いた実環境にTerraform導入したら驚いた
実環境にTerraform導入したら驚いた
 
ネットワーク自動化ツール紹介(Ansible・NAPALM編)
ネットワーク自動化ツール紹介(Ansible・NAPALM編)ネットワーク自動化ツール紹介(Ansible・NAPALM編)
ネットワーク自動化ツール紹介(Ansible・NAPALM編)
 
The linux file system structure
The linux file system structureThe linux file system structure
The linux file system structure
 
DRBD/Heartbeat/Pacemakerで作るKVM仮想化クラスタ
DRBD/Heartbeat/Pacemakerで作るKVM仮想化クラスタDRBD/Heartbeat/Pacemakerで作るKVM仮想化クラスタ
DRBD/Heartbeat/Pacemakerで作るKVM仮想化クラスタ
 

Andere mochten auch

Andere mochten auch (20)

A deep dive into libuv
A deep dive into libuvA deep dive into libuv
A deep dive into libuv
 
libuv: cross platform asynchronous i/o
libuv: cross platform asynchronous i/olibuv: cross platform asynchronous i/o
libuv: cross platform asynchronous i/o
 
Planning libuv v2
Planning libuv v2Planning libuv v2
Planning libuv v2
 
From SIP to WebRTC and vice versa
From SIP to WebRTC and vice versaFrom SIP to WebRTC and vice versa
From SIP to WebRTC and vice versa
 
Jitsi: State of the Union
Jitsi: State of the UnionJitsi: State of the Union
Jitsi: State of the Union
 
Trust No One
Trust No OneTrust No One
Trust No One
 
CDRTool: CDR mediation and rating engine for OpenSIPS
CDRTool: CDR mediation and rating engine for OpenSIPSCDRTool: CDR mediation and rating engine for OpenSIPS
CDRTool: CDR mediation and rating engine for OpenSIPS
 
The Future of the PBX
The Future of the PBXThe Future of the PBX
The Future of the PBX
 
Python, WebRTC and You (v2)
Python, WebRTC and You (v2)Python, WebRTC and You (v2)
Python, WebRTC and You (v2)
 
Building an Open Source VoIP Hardware Phone
Building an Open Source VoIP Hardware PhoneBuilding an Open Source VoIP Hardware Phone
Building an Open Source VoIP Hardware Phone
 
WebRTC enabling your OpenSIPS infrastructure
WebRTC enabling your OpenSIPS infrastructureWebRTC enabling your OpenSIPS infrastructure
WebRTC enabling your OpenSIPS infrastructure
 
Proyecto Open Pi Phone
Proyecto Open Pi PhoneProyecto Open Pi Phone
Proyecto Open Pi Phone
 
Escalabilidad horizontal desde las trincheras
Escalabilidad horizontal desde las trincherasEscalabilidad horizontal desde las trincheras
Escalabilidad horizontal desde las trincheras
 
SylkServer: State of the art RTC application server
SylkServer: State of the art RTC application serverSylkServer: State of the art RTC application server
SylkServer: State of the art RTC application server
 
Videoconferencias: el santo grial de WebRTC
Videoconferencias: el santo grial de WebRTCVideoconferencias: el santo grial de WebRTC
Videoconferencias: el santo grial de WebRTC
 
Python, WebRTC and You
Python, WebRTC and YouPython, WebRTC and You
Python, WebRTC and You
 
Node.js/io.js Native C++ Addons
Node.js/io.js Native C++ AddonsNode.js/io.js Native C++ Addons
Node.js/io.js Native C++ Addons
 
Ninja Build: Simple Guide for Beginners
Ninja Build: Simple Guide for BeginnersNinja Build: Simple Guide for Beginners
Ninja Build: Simple Guide for Beginners
 
Asyncio
AsyncioAsyncio
Asyncio
 
Introduction to asyncio
Introduction to asyncioIntroduction to asyncio
Introduction to asyncio
 

Ähnlich wie libuv, NodeJS and everything in between

Intravert Server side processing for Cassandra
Intravert Server side processing for CassandraIntravert Server side processing for Cassandra
Intravert Server side processing for Cassandra
Edward Capriolo
 
fog or: How I Learned to Stop Worrying and Love the Cloud (OpenStack Edition)
fog or: How I Learned to Stop Worrying and Love the Cloud (OpenStack Edition)fog or: How I Learned to Stop Worrying and Love the Cloud (OpenStack Edition)
fog or: How I Learned to Stop Worrying and Love the Cloud (OpenStack Edition)
Wesley Beary
 
服务框架: Thrift & PasteScript
服务框架: Thrift & PasteScript服务框架: Thrift & PasteScript
服务框架: Thrift & PasteScript
Qiangning Hong
 
Writing robust Node.js applications
Writing robust Node.js applicationsWriting robust Node.js applications
Writing robust Node.js applications
Tom Croucher
 
[JAM 1.2] Design & Multitasking (Andrew Solovey)
[JAM 1.2] Design & Multitasking (Andrew Solovey)[JAM 1.2] Design & Multitasking (Andrew Solovey)
[JAM 1.2] Design & Multitasking (Andrew Solovey)
Evgeny Kaziak
 

Ähnlich wie libuv, NodeJS and everything in between (20)

Intravert Server side processing for Cassandra
Intravert Server side processing for CassandraIntravert Server side processing for Cassandra
Intravert Server side processing for Cassandra
 
NYC* 2013 - "Advanced Data Processing: Beyond Queries and Slices"
NYC* 2013 - "Advanced Data Processing: Beyond Queries and Slices"NYC* 2013 - "Advanced Data Processing: Beyond Queries and Slices"
NYC* 2013 - "Advanced Data Processing: Beyond Queries and Slices"
 
fog or: How I Learned to Stop Worrying and Love the Cloud
fog or: How I Learned to Stop Worrying and Love the Cloudfog or: How I Learned to Stop Worrying and Love the Cloud
fog or: How I Learned to Stop Worrying and Love the Cloud
 
fog or: How I Learned to Stop Worrying and Love the Cloud (OpenStack Edition)
fog or: How I Learned to Stop Worrying and Love the Cloud (OpenStack Edition)fog or: How I Learned to Stop Worrying and Love the Cloud (OpenStack Edition)
fog or: How I Learned to Stop Worrying and Love the Cloud (OpenStack Edition)
 
Practical pig
Practical pigPractical pig
Practical pig
 
服务框架: Thrift & PasteScript
服务框架: Thrift & PasteScript服务框架: Thrift & PasteScript
服务框架: Thrift & PasteScript
 
Book
BookBook
Book
 
OpenSSL Basic Function Call Flow
OpenSSL Basic Function Call FlowOpenSSL Basic Function Call Flow
OpenSSL Basic Function Call Flow
 
Writing robust Node.js applications
Writing robust Node.js applicationsWriting robust Node.js applications
Writing robust Node.js applications
 
nuclio Overview October 2017
nuclio Overview October 2017nuclio Overview October 2017
nuclio Overview October 2017
 
Python, do you even async?
Python, do you even async?Python, do you even async?
Python, do you even async?
 
NodeJS for Beginner
NodeJS for BeginnerNodeJS for Beginner
NodeJS for Beginner
 
iguazio - nuclio overview to CNCF (Sep 25th 2017)
iguazio - nuclio overview to CNCF (Sep 25th 2017)iguazio - nuclio overview to CNCF (Sep 25th 2017)
iguazio - nuclio overview to CNCF (Sep 25th 2017)
 
How I Built a Power Debugger Out of the Standard Library and Things I Found o...
How I Built a Power Debugger Out of the Standard Library and Things I Found o...How I Built a Power Debugger Out of the Standard Library and Things I Found o...
How I Built a Power Debugger Out of the Standard Library and Things I Found o...
 
[JAM 1.2] Design & Multitasking (Andrew Solovey)
[JAM 1.2] Design & Multitasking (Andrew Solovey)[JAM 1.2] Design & Multitasking (Andrew Solovey)
[JAM 1.2] Design & Multitasking (Andrew Solovey)
 
Ansible - Swiss Army Knife Orchestration
Ansible - Swiss Army Knife OrchestrationAnsible - Swiss Army Knife Orchestration
Ansible - Swiss Army Knife Orchestration
 
Original slides from Ryan Dahl's NodeJs intro talk
Original slides from Ryan Dahl's NodeJs intro talkOriginal slides from Ryan Dahl's NodeJs intro talk
Original slides from Ryan Dahl's NodeJs intro talk
 
Node.js - async for the rest of us.
Node.js - async for the rest of us.Node.js - async for the rest of us.
Node.js - async for the rest of us.
 
node.js: Javascript's in your backend
node.js: Javascript's in your backendnode.js: Javascript's in your backend
node.js: Javascript's in your backend
 
Writing Redis in Python with asyncio
Writing Redis in Python with asyncioWriting Redis in Python with asyncio
Writing Redis in Python with asyncio
 

Mehr von Saúl Ibarra Corretgé

Mehr von Saúl Ibarra Corretgé (16)

JanusCon 2024: Mom there are robots in my meeting
JanusCon 2024: Mom there are robots in my meetingJanusCon 2024: Mom there are robots in my meeting
JanusCon 2024: Mom there are robots in my meeting
 
Challenges running Jitsi Meet at scale during the pandemic
Challenges running Jitsi Meet at scale during the pandemicChallenges running Jitsi Meet at scale during the pandemic
Challenges running Jitsi Meet at scale during the pandemic
 
The Road to End-to-End Encryption in Jitsi Meet
The Road to End-to-End Encryption in Jitsi MeetThe Road to End-to-End Encryption in Jitsi Meet
The Road to End-to-End Encryption in Jitsi Meet
 
Jitsi: State of the Union 2020
Jitsi: State of the Union 2020Jitsi: State of the Union 2020
Jitsi: State of the Union 2020
 
Jitsi Meet: our tale of blood, sweat, tears and love
Jitsi Meet: our tale of blood, sweat, tears and loveJitsi Meet: our tale of blood, sweat, tears and love
Jitsi Meet: our tale of blood, sweat, tears and love
 
Jitsi Meet: Video conferencing for the privacy minded
Jitsi Meet: Video conferencing for the privacy mindedJitsi Meet: Video conferencing for the privacy minded
Jitsi Meet: Video conferencing for the privacy minded
 
Jitsi - Estado de la unión 2019
Jitsi - Estado de la unión 2019Jitsi - Estado de la unión 2019
Jitsi - Estado de la unión 2019
 
Get a room! Spot: the ultimate physical meeting room experience
Get a room! Spot: the ultimate physical meeting room experienceGet a room! Spot: the ultimate physical meeting room experience
Get a room! Spot: the ultimate physical meeting room experience
 
Going Mobile with React Native and WebRTC
Going Mobile with React Native and WebRTCGoing Mobile with React Native and WebRTC
Going Mobile with React Native and WebRTC
 
Going Mobile with React Native and WebRTC
Going Mobile with React Native and WebRTCGoing Mobile with React Native and WebRTC
Going Mobile with React Native and WebRTC
 
Jitsi: Estado de la Unión (2018)
Jitsi: Estado de la Unión (2018)Jitsi: Estado de la Unión (2018)
Jitsi: Estado de la Unión (2018)
 
Jitsi: state-of-the-art video conferencing you can self-host
Jitsi: state-of-the-art video conferencing you can self-hostJitsi: state-of-the-art video conferencing you can self-host
Jitsi: state-of-the-art video conferencing you can self-host
 
WebRTC: El epicentro de la videoconferencia y IoT
WebRTC: El epicentro de la videoconferencia y IoTWebRTC: El epicentro de la videoconferencia y IoT
WebRTC: El epicentro de la videoconferencia y IoT
 
Jitsi: Open Source Video Conferencing
Jitsi: Open Source Video ConferencingJitsi: Open Source Video Conferencing
Jitsi: Open Source Video Conferencing
 
Extendiendo SIP con WebRTC
Extendiendo SIP con WebRTCExtendiendo SIP con WebRTC
Extendiendo SIP con WebRTC
 
De SIP a WebRTC y vice versa
De SIP a WebRTC y vice versaDe SIP a WebRTC y vice versa
De SIP a WebRTC y vice versa
 

Kürzlich hochgeladen

Why Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businessWhy Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire business
panagenda
 

Kürzlich hochgeladen (20)

presentation ICT roal in 21st century education
presentation ICT roal in 21st century educationpresentation ICT roal in 21st century education
presentation ICT roal in 21st century education
 
MS Copilot expands with MS Graph connectors
MS Copilot expands with MS Graph connectorsMS Copilot expands with MS Graph connectors
MS Copilot expands with MS Graph connectors
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
 
Corporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptxCorporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptx
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdf
 
AXA XL - Insurer Innovation Award Americas 2024
AXA XL - Insurer Innovation Award Americas 2024AXA XL - Insurer Innovation Award Americas 2024
AXA XL - Insurer Innovation Award Americas 2024
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
 
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
 
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
 
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost SavingRepurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
 
FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024
 
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt Robison
 
A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?
 
Why Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businessWhy Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire business
 
Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
 

libuv, NodeJS and everything in between

  • 1. LIBUV, NODEJS AND EVERYTHING IN BETWEEN Saúl Ibarra Corretgé @saghul
  • 2. LIBUV, NODE AND EVERYTHING IN BETWEEN HIYA! ▸ @saghul ▸ Bilbao — Amsterdam — Liverpool ▸ libuv core janitor ▸ Nodejs collaborator ▸ Recently obsessed with 3D printing ▸ AMA!
  • 4. LIBUV, NODE AND EVERYTHING IN BETWEEN ASYNC I/O 101 from __future__ import print_function import socket server = socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM) server.bind(('127.0.0.1', 1234)) server.listen(10) print("Server listening on: {}".format(server.getsockname())) client, addr = server.accept() print("Client connected: {}".format(addr)) while True: data = client.recv(4096) if not data: print("Client has disconnected") break client.send(data.upper()) server.close()
  • 5. LIBUV, NODE AND EVERYTHING IN BETWEEN CRAP, IT BLOCKS! ▸ Only one client at a time! ▸ Scaling up ▸ Threads ▸ I/O multiplexing ▸ http://www.kegel.com/c10k.html ▸ http://www.slideshare.net/saghul/how-do-eventloops- work-in-python
  • 6. LIBUV, NODE AND EVERYTHING IN BETWEEN THREADS? ▸ Overhead: stack size, scheduling ▸ Synchronisation ▸ It’s still a good solution in some cases
  • 7. LIBUV, NODE AND EVERYTHING IN BETWEEN I/O MULTIPLEXING TO THE RESCUE ▸ Single thread ▸ Examine and wait for i/o in multiple sockets at once ▸ When a socket is ready the operation won’t block ▸ Good for i/o bound tasks, bad for CPU intensive tasks
  • 8. LIBUV, NODE AND EVERYTHING IN BETWEEN I/O MULTIPLEXING 101 1. Put the fd in non-blocking mode 2. Add the fd to the i/o multiplexor 3. Wait for some time 4. Perform read / writes on the fd, it won’t block! 5. Profit?
  • 9. LIBUV, NODE AND EVERYTHING IN BETWEEN I/O MULTIPLEXING APIS ▸ Different APIs: select, poll, epoll, kqueue, … ▸ Unix shares a common model: readiness ▸ Windows uses a completion model ▸ IOCP is The Good Stuff
  • 10. LIBUV
  • 11. LIBUV, NODE AND EVERYTHING IN BETWEEN LIBUV ▸ Small (relatively) C library: ~30K LOC (without tests) ▸ Extensive test suite ▸ Designed for C programs that miss the joy of JavaScript callback hell ▸ Used by Node and many other projects:
 https://github.com/libuv/libuv/wiki/Projects-that-use-libuv
  • 12. LIBUV, NODE AND EVERYTHING IN BETWEEN LIBUV: FEATURES ▸ Event loop backed by epoll, kqueue, IOCP, event ports, etc. ▸ Timers ▸ Async TCP / UDP sockets ▸ Async named pipes ▸ Async filesystem operations ▸ Async signal handling ▸ Child processes ▸ ANSI escaped TTY ▸ Threading utilities ▸ Coolest logo ever
  • 13. LIBUV, NODE AND EVERYTHING IN BETWEEN LIBUV: ARCHITECTURE
  • 14. LIBUV, NODE AND EVERYTHING IN BETWEEN LIBUV: THE EVENT LOOP
  • 15. LIBUV, NODE AND EVERYTHING IN BETWEEN LIBUV: FILESYSTEM APIS ▸ Follow the Unix style ▸ Executed in a thread pool ▸ http://blog.libtorrent.org/2012/10/asynchronous-disk-io/
  • 16. LIBUV, NODE AND EVERYTHING IN BETWEEN LIBUV: A WORD ON THREADS ▸ We only use threads for file i/o and getaddrinfo ▸ Default thread pool size is 4
 (runtime env var: UV_THREADPOOL_SIZE) ▸ NOT FOR NETWORK I/O ▸ NOT FOR NETWORK I/O ▸ NOT FOR NETWORK I/O ▸ NOT FOR NETWORK I/O
  • 17. THE LIBUV EVENT LOOP IS SINGLE THREADED. THE THREAD POOL IS ONLY USED FOR FILE I/O. The libuv police LIBUV, NODE AND EVERYTHING IN BETWEEN
  • 19. LIBUV, NODE AND EVERYTHING IN BETWEEN A LIBUV CHAT APPLICATION ▸ Simple TCP server application ▸ A twist on libuv-chat by Ben Noordhuis in 2011 ▸ Multiple users, single “chat room” ▸ Pokemon, because why not? ▸ https://github.com/saghul/libuv-chat
  • 20. THE MAKEFILE all: build deps/libuv: git clone --depth 1 https://github.com/libuv/libuv deps/libuv build/gyp: git clone --depth 1 https://chromium.googlesource.com/external/gyp build/gyp out/Makefile: deps/libuv build/gyp build/gyp/gyp -Duv_library=static_library --depth=$(PWD) --generator-output=$(PWD)/out -Goutput_dir=$(PWD)/out -f make build.gyp build: out/Makefile $(MAKE) -C out clean: rm -rf out distclean: rm -rf build deps out .PHONY: clean distclean
  • 21. THE GYP BUILD FILE # Copyright (c) 2016, Saúl Ibarra Corretgé <saghul@gmail.com> # Copyright (c) 2012, Ben Noordhuis <info@bnoordhuis.nl> # # Permission to use, copy, modify, and/or distribute this software for any # purpose with or without fee is hereby granted, provided that the above # copyright notice and this permission notice appear in all copies. # # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. # gyp -Duv_library=static_library --depth=$PWD --generator-output=$PWD/out -Goutput_dir=$PWD/out -f make build.gyp { 'targets': [ { 'target_name': 'chat-server', 'type': 'executable', 'dependencies': ['deps/libuv/uv.gyp:libuv'], 'sources': ['src/main.c', 'src/queue.h', 'src/pokemon_names.h'], } ] }
  • 22. INITIALISE AND RUN SERVER struct user { QUEUE queue; uv_tcp_t handle; char id[32]; }; static QUEUE users; int main(void) { QUEUE_INIT(&users); srand(1234); int r; uv_tcp_t server_handle; uv_tcp_init(uv_default_loop(), &server_handle); struct sockaddr_in addr; uv_ip4_addr(SERVER_ADDR, SERVER_PORT, &addr); r = uv_tcp_bind(&server_handle, (const struct sockaddr*) &addr, 0); if (r < 0) fatal("uv_tcp_bind", r); const int backlog = 128; r = uv_listen((uv_stream_t*) &server_handle, backlog, on_connection); if (r < 0) fatal("uv_listen", r); printf("Listening at %s:%dn", SERVER_ADDR, SERVER_PORT); uv_run(uv_default_loop(), UV_RUN_DEFAULT); return 0; }
  • 23. HANDLE INCOMING CONNECTIONS static void on_connection(uv_stream_t* server_handle, int status) { assert(status == 0); int r; // hurray, a new user! struct user *user = xmalloc(sizeof(*user)); uv_tcp_init(uv_default_loop(), &user->handle); r = uv_accept(server_handle, (uv_stream_t*) &user->handle); if (r < 0) fatal("uv_accept", r); // add him to the list of users QUEUE_INSERT_TAIL(&users, &user->queue); make_user_id(user); // now tell everyone, including yourself (to know your name!) broadcast(NULL, "* A wild %s appeared from %sn", user->id, addr_and_port(user)); // start accepting messages from the user uv_read_start((uv_stream_t*) &user->handle, on_alloc, on_read); }
  • 24. READ INCOMING DATA static void on_alloc(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf) { buf->base = xmalloc(suggested_size); buf->len = suggested_size; } static void on_read(uv_stream_t* handle, ssize_t nread, const uv_buf_t* buf) { struct user *user = QUEUE_DATA(handle, struct user, handle); if (nread == UV_EOF) { // user disconnected QUEUE_REMOVE(&user->queue); uv_close((uv_handle_t*) &user->handle, on_close); broadcast(NULL, "* %s fled!n", user->id); } else if (nread > 0) { // broadcast message broadcast(user, "%s said: %.*s", user->id, (int) nread, buf->base); } else { fprintf(stderr, "on_read: %sn", uv_strerror(nread)); } free(buf->base); }
  • 25. BROADCAST DATA static void broadcast(const struct user* sender, const char *fmt, ...) { QUEUE *q; char msg[512]; va_list ap; va_start(ap, fmt); vsnprintf(msg, sizeof(msg), fmt, ap); va_end(ap); QUEUE_FOREACH(q, &users) { struct user *user = QUEUE_DATA(q, struct user, queue); if (user != sender) { unicast(user, msg); } } } static void unicast(struct user *user, const char *msg) { size_t len = strlen(msg); uv_write_t *req = xmalloc(sizeof(*req) + len); void *addr = req + 1; memcpy(addr, msg, len); uv_buf_t buf = uv_buf_init(addr, len); uv_write(req, (uv_stream_t*) &user->handle, &buf, 1, on_write); } static void on_write(uv_write_t *req, int status) { free(req); }
  • 26. MISCELLANEOUS FUNCTIONS static void on_close(uv_handle_t* handle) { struct user *user = QUEUE_DATA(handle, struct user, handle); free(user); } static void make_user_id(struct user *user) { snprintf(user->id, sizeof(user->id), "%s", pokemon_names[rand() % ARRAY_SIZE(pokemon_names)]); }
  • 27. NODE
  • 28. LIBUV, NODE AND EVERYTHING IN BETWEEN NODEJS ▸ Server side JavaScript ▸ V8 JavaScript engine ▸ Web inspired async model ▸ Auxiliary libraries: libuv, OpenSSL, c-ares, http_parser, …
  • 29. LIBUV, NODE AND EVERYTHING IN BETWEEN PLATFORM LAYER REQUIREMENTS ▸ ASYNC ALL THE THINGS ▸ Completion based (callbacks) ▸ Consistent API for asynchronous network i/o ▸ Filesystem operations ▸ Basic name resolution (getaddrinfo / getnameinfo)
  • 30. LIBUV, NODE AND EVERYTHING IN BETWEEN ARCHITECTURE IN NODE 0.4 BINDINGS / WRAPS JS STANDARD LIBRARY USER APPLICATIONS V8 OPENSSL LIBEV LIBEIO …
  • 31. LIBUV, NODE AND EVERYTHING IN BETWEEN ARCHITECTURE IN NODE 0.6 BINDINGS / WRAPS JS STANDARD LIBRARY USER APPLICATIONS V8 OPENSSL LIBUV … LIBEV LIBEIO
  • 32. LIBUV, NODE AND EVERYTHING IN BETWEEN ARCHITECTURE IN NODE 0.10 AND ONWARDS BINDINGS / WRAPS JS STANDARD LIBRARY USER APPLICATIONS V8 OPENSSL LIBUV …
  • 34. LIBUV, NODE AND EVERYTHING IN BETWEEN LIBUV: THE EVENT LOOP REMEMBER?
  • 35. LIBUV, NODE AND EVERYTHING IN BETWEEN NODE EVENT LOOP COALESCED, 1 NODE TIMER != 1 LIBUV TIMER RUN ON A CHECK + IDLE HANDLE NEXT TICK CALLBACKS RUN FROM NODE::MAKECALLBACK
  • 36. LIBUV, NODE AND EVERYTHING IN BETWEEN ONION ARCHITECTURE (TM) net.Socket TCPWrap uv_tcp_t Socket._handle TCPWrap.handle_ fd / HANDLE
  • 37. QUESTIONS? libuv.org docs.libuv.org #libuv on IRC libuv Google Group #libuv on StackOverflow