
Writing high-performance servers in modern C++ - adamnemecek
https://medium.com/@jamesperry/writing-high-performance-servers-in-modern-c-7cd00926828#.lcsmnff1d
======
jhartmann
A lot of people state that Python/PHP/Ruby/Javascript on the dynamic language
side and Java and other JVM languages on the statically typed side and much
quicker to develop than C++, but being a very experienced Java programmer and
a decent Javascript programmer I find that I can program just as fast with C++
as long as you use the right choices of libraries and use C++11 or greater.
With libraries like Boost, fbfolly, wangle, etc. I find it can be just as
quick to develop C++ code as with other languages. I think too many people
think C++ is a huge investment above other languages due to past experience,
but I feel that it is just not true anymore. Thanks for this post, I think it
shows just how quick it is to write performant modern C++, when you stand on
the shoulders of other libraries. Just like the other languages.

~~~
willtim
Does modern C++ have a decent story for writing nonblocking concurrent code
yet? Something that could compete with async-await in C# or monads in
functional programming?

~~~
acconsta
A networking library based on Asio has been proposed for C++17. In the
meantime, use Asio.

[http://think-async.com/](http://think-async.com/)

~~~
corysama
[http://think-async.com/Asio/AsioStandalone](http://think-
async.com/Asio/AsioStandalone)

!! I've always heard that Asio is great, but never bothered to look because I
don't like introducing Boost's 450 megs of compiler-test-suite-worthy C++ to
my >45kb programs. But, as a stand-alone library. That's interesting!

------
SeanDav
I don't understand the point of saying something like:

> _" I show how to build a modern C++ high-performance, asynchronous echo
> server that can be written with just 48 lines of code."_

The fact that it is 48 lines of code is almost meaningless. If the framework
was a different design it could be done in 1 line of C++ code or 1 line of
COBOL. Given the right library/framework, any application can be done with 1
line of code (taking a bit of poetic licence here, but hopefully you see my
point).

As a discussion about using Wangle in C++, the article has far more merit.

Perhaps I am just being overly pedantic.

~~~
hnbro
it may not be an information-dense sentence, but it is merely a single
sentence. one which you've isolated from it's context.

~~~
SeanDav
It is the direct TL;DR quote from the Author himself, given prominence with
blank line separators, italics, bold prefix and located near the very start of
the article, so hardly out of context.

------
markpapadakis
For what it's worth, the network I/O model design+implementation is rarely
what makes the difference between high performance, or not, 'servers' \-- and
that is a mostly solved problem, at least in terms of patterns and practices
that are adopted by 'modern' servers (few threads, no more than actual
hardware CPU cores, async.multiplexing, etc).

High performance is about everything else, including processing actual
incoming requests efficiently, reducing block/busy time in threads, caring a
lot about memory access/caches. They key IMO is concurrency and migrating
blocking operations to other dedicated threads, and this is where an efficient
coroutines implementation would help both with accomplishing that task, but,
perhaps more importantly, keeping the programming model simple.

C++17 will introduce support for reusmable functions (
[http://blogs.msdn.com/b/vcblog/archive/2014/11/12/resumable-...](http://blogs.msdn.com/b/vcblog/archive/2014/11/12/resumable-
functions-in-c.aspx) ). This will be a game changer. Now, you can approximate
this by e.g creating task abstractions and use lower-level(but slow)
setjmp/longjmp functions, or just design tasks/functors that hold state that
can schedule other tasks in turn, and so on. It works, but the overhead,
mental, but also n terms of processing/executing/scheduling can be too great.

------
hellofunk
>I must warn that it unfortunately doesn’t build on Max OS X as of yet so I
recommend to virtualize Ubuntu 14.04 to install it.

Important info for some folks (i.e. myself).

------
Galanwe
I stopped reading after reading the first line of code containing a virtual
function and smart pointers. Nothing is performance oriented in this post.
It's just a plain old dummy TCP server like anyone would write.

~~~
dxhdr
I half agree; it's easy to be cynical. Virtual functions can be a terrible
idea... if they are in a hot path.

Is EchoHandler::read such a path? Maybe, you really can't say without
profiling. If anything using std::string is the red flag for me.

------
signa11
no benchmarks. what gives ?

~~~
ansgri
Yeah, and no mention about boost::async, which is in Boost, ie almost
standard.

~~~
kinofcain
Folly, the library underneath wangle, is running on top of boost::asio, so
this is basically an abstraction on asio two layers up.

~~~
neomantra
Folly does not use boost::asio, but rather libevent:

    
    
      libevent is an excellent cross-platform eventing library.
      Folly's async provides C++ object wrappers for fd callbacks
      and event_base, as well as providing implementations for
      many common types of fd uses.
    

[https://github.com/facebook/folly/blob/master/folly/io/async...](https://github.com/facebook/folly/blob/master/folly/io/async/README.md)

grepping the codebase for `asio` brings up nothing.

~~~
kinofcain
Interesting. Thanks for the correction. I had seen the boost dependency and
assumed it was using asio under the hood I guess.

------
thepumpkin1979
I love to read stuff like this, "with a bit of effort I was able to build the
whole back-end for my startup using C++", then I start to think: what would it
take for me to migrate off Golang to C++?

I love to develop in Mac and deploy in Linux/Docker, so whatever stack I pick
has to be compatible with both OS's, with this in mind I made a list of
libraries I'd need to move my API to C++:

* Web Server library

* Web Framework-ish library

* JSON library for REST interface

* Database client library for my database

* Integration testing

After reading these useful blog posts I guess I'll pick:

* Web Server => Facebook's Proxygen

* Web Framework-ish library => Facebook's Wangle, but it doesn't seem to work in Mac, that's already a problem, I don't like having to have two dev environments.

* JSON library => looks like Facebook's Folly seems to have something for it, let's hope it uses modern c++ constructs and not some obscure templating magic to make it faster than other implementations.

* Database client library for RethinkDB: RethinkDB has no official driver and the only community driver public repository has only 22 starts and no CI setup on Github, I'm reluctant to trust this code, this is already a deal breaker to me.

* Integration testing => Wangle's documentation is scarce, there wiki is empty and the repo doesn't have a single code sample to take a look at. I can't go to production without testing, another deal breaker.

Yes, I agree, I don't have to pick RethinkDB. MySQL and PostgreSQL c++ drivers
are very mature to use in production apps.

Of course they are, but:

* Do these drivers use modern C++ constructs?

* Would these drivers block proxygen/wangle IO loop(in case they have one?)

* Would I have to use callbacks to make achieve full IO speed? I hate callbacks, there is a reason I abandoned Node.js a long ago.

* How do I put all these dependencies together?

As with Golang, as much as I hate it's lack of generics and proper
inheritance:

* Web server: Standard library `net/http`

* Web framework-ish: I don't really need a framework/pipeline for it, there are some neat web routers out there that just help me do the job.

* JSON library: Standard library `encoding/json`

* Database client library: gorethink and almost all the Golang database clients out there have significant adoption with over 700 stars on Github.

* Integration testing: Standard library `net/http/httptest`

Unlike D, C++ and Rust; the Golang ecosystem is unified, I know I'm able to
pick a client library and it'd work with whatever stack I have in place
because there's only one scheduler and therefore only one way to do IO, plus
it's non-blocking without callbacks. I'm not a fan of vendoring dependencies,
but it simply works.

In conclusion, I love C++ and even with all the significant progress made in
C++11 and C++14, I'm still stucked with Go because it just works.

~~~
jbandela1
I also run into this problem all the time. I hope that with the networking TS
standardizing on basically boost Asio and the incorporation of coroutines into
C++ we should start seeing some unification across all network/do client
libraries in terms on non-blocking use.

------
geocar
That's a lot of code.

------
nodivbyzero
Did you test your server with 1.000.000 connections?

~~~
dxhdr
How about input fuzzing? Did you try crashing it and see how quickly it can
recover? Unit tests? What about zero downtime upgrades? DDoS resiliency? Can
it utilize all cores on a machine? Scalable? What are the median and max
response times under load?

Oh it's just a quick demo? Nevermind.

~~~
yelnatz
Title needs to be edited to: How to quickly write a basic, modern C++ using
Wangle.

------
eva1984
The API looks a lot like Netty

------
thrownaway2424
I enjoy seeing Facebook libraries and Google libraries in the same program.

~~~
ersoft
It's nice that google are using snake case for library filenames and facebook
are using camelcase. :)

Example:

#include <proxygen/httpserver/HTTPServer.h>

#include <grpc++/server_context.h>

------
osullivj
Reminds me of Doug Schmidt's ACE Reactor...

------
MichaelTerry
Any classical logic is possible, because C++ is a Turing-complete language.

That said, of course, how much you can actually do and how fast you can do it
depends a lot on the hardware you have available. Not every computer can run
fast, high-quality graphics, no matter what language you coded in.

THAT said, C++ is considered a relatively high-performance language and is
often used for things like advanced game graphics.

