22
Scalable Network I/O with C++ Arindam Mukherjee Pune C++ and Boost Meetup

C++ scalable network_io

Embed Size (px)

Citation preview

Page 1: C++ scalable network_io

Scalable Network I/O with C++

Arindam MukherjeePune C++ and Boost Meetup

Page 2: C++ scalable network_io

Content

• Sockets• Boost Asio programming model• Synchronous model• Key challenges to scaling• Asynchronous model• Asio coroutines

Page 3: C++ scalable network_io

Objectives

• Get a feel of the subject• Know where to look, what to look for

Page 4: C++ scalable network_io

Sockets

• Applications bind to an IP address and a numeric port to start communicating.

• Port: an unsigned integer identifying the point of attachment of the app to the protocol.

• Endpoint: The treble of an IP address, port and protocol (TCP, UDP, etc.).

• Socket: an unsigned integer identifying an endpoint in use.

Page 5: C++ scalable network_io

Socket API

• Berkeley Sockets API, part of POSIX standard.• System calls– socket: get a socket– bind: bind to an endpoint (usually passive)– listen: wait for incoming connections (passive)– accept: establish the TCP connection (passive)– connect: connect to a remote endpoint (active)– close: tear down the connection

Page 6: C++ scalable network_io

Boost Asio Programming Model

• asio::io_service as a bridge to the OS, and as a task queue.

• IO objects like asio::ip::tcp::socket, likewise for udp, etc.

• I/O functions both sync and async, like asio::read/write/asycn_read.

• Helper classes for name resolution, IP address manipulation.

Page 7: C++ scalable network_io

Name resolution

• asio::ip::tcp::resolver provides the resolve method.– Takes asio::ip::tcp::resolver::query

object.– Returns iterator of type asio::ip::tcp::resolver::iterator.

– Dereferencing the iterator return asio::ip::tcp::endpoint objects.

Page 8: C++ scalable network_io

Vectored I/O

• Gather data from disparate areas in memory and write it to a connection as a single stream.

• Read data from a single connection and partition the stream across a set of memory areas.

• Provided by readv / writev system calls – requires lesser context switches or processing overheads.

Page 9: C++ scalable network_io

Asio Buffers for vectored I/O

• Wrappers around memory buffers, initialized with buffer base address and length in bytes.

• asio::const_buffer – source, asio::mutable_buffer – sink.

• Sequence of buffers can be vectors, lists, etc.

Page 10: C++ scalable network_io

Sync I/O with TCP (server)

• Create a TCP listener socket.• Bind to a local endpoint.• Listen for and accept incoming connections.• Perform I/O and handle events on each

connection, using a per-connection socket.

Page 11: C++ scalable network_io

Sync I/O with TCP (client)

• Create a TCP socket (and optionally bind to an endpoint).

• Connect to a remote endpoint (server).• Perform communication and handle events on

the connection.

Page 12: C++ scalable network_io

TCP sync I/O interaction model

Page 13: C++ scalable network_io

Key challenges to scaling

• Sync APIs block waiting for completion.• One thread per connection is for toy

programs: scalability anti-pattern.• Use a thread-pool and leverage the io_service

task queue: only limits threads, not waiting.• Go async: wait-free.• Async + thread-pool: wait-free, limited

threads.

Page 14: C++ scalable network_io

io_service as a task queue

• Put a handler with signature void() on the queue, using post or dispatch.

• Handlers associated with tasks, could be ready or pending.

• Call run or run_one from threads to process tasks.• Call poll or poll_one to process ready tasks.• Create object of asio::io_service::work to make

run wait.• Serialize handlers using asio::io_service::strand.

Page 15: C++ scalable network_io

Async I/O

• Submit tasks to the OS via the io_service, and be notified by callbacks.

• Wait-free, but difficult to code.• Maintaining context / state across callback

invocations presents challenges.

Page 16: C++ scalable network_io

Async I/O model

Page 17: C++ scalable network_io

Coroutines

• A coroutine can be called, suspended and resumed.

• Suspension through cooperative yielding.• On suspension, control goes back to counterpart

(caller).• On resumption, coroutine does not restart but

continues from where it left off. Stack preserved.• Boost.Coroutine provides implementation.

Page 18: C++ scalable network_io

Async I/O with coroutines

• Enqueue a coroutine using asio::spawn.• Coroutine runs, but instead of blocking,

registers the yield context as a handler, and then yields.

• Control goes to caller (loop in run function).• The run function handles other I/O requests.• On I/O events, handler is invoked which

resumes coroutine.

Page 19: C++ scalable network_io

Coroutine Sequence diagram

• We’ll make this during the presentation.

Page 20: C++ scalable network_io

Q & A

• Books:Learning Boost C++ Libraries (Packt), Chapter 11.

• References:http://www.gamedev.net/blog/950/entry-2249317-a-guide-to-getting-started-with-boostasio/

• Collaboration diagrams from here:http://think-async.com/Asio/asio-1.4.1/doc/asio/overview/core/basics.html

Page 21: C++ scalable network_io

Howto lambda

• Syntax for generating function objects inline:[] { std::cout << "Hello, world!\n"; }

• Can take args:[](std::string name) { std::cout << "Hello, " + name + "!\n"; }

• Can access vars from surrounding scope:[&var1, var2](…) { std::cout << var2 << '\n'; var1 = 10;}

Page 22: C++ scalable network_io

Howto bind

• Syntax for adapting function arity (signature).void foo(int n, std::string name); // binaryauto f = boost::bind(foo, ::_1, "hello"); // unary

• Binding references:void foo(const std::string& name); // unarystd::string str;auto f = boost::bind(foo, boost::ref(str)); // nullary

• Placeholders for unbound params: ::_1, ::_2.