Writing high-performance servers in modern C++
medium.com
medium.com
What I mean by physical design is, if a particular function is prone to be edited constantly, keep that function definition in it's own .cpp file.
of course I'll agree that in this day and age, we shouldn't worry about those sorts of things.
This has been a problem on every C++ project I've worked on over the past 15 years, and it only seems to be getting worse. And scaled up by increasing team size, that makes it even more of a serious problem.
I hope your parting shot was intended to be that we shouldn't have to worry about this today, i.e., that we should be able to expect more from our tools, and that the current tools are shit. Because we absolutely should worry about it! This is people's time we're talking about. That isn't any less valuable than it used to be.
I have seen optimized builds run faster than debug builds simply because many symbols where being removed during optimization speeding up the link step.
Modern C++ style generally requires making a whole bunch of little functions and classes and counting on them to be inlined and SROA'd away. This works remarkably well for runtime, but it exacts a big compilation performance hit simply because you're optimizing so much code.
The actual ray-tracing code wasn't that long at all, but if you turned max_max_bounces up (say, 100+) "code-gen" time in visual studio blew up to over one minute. That was the moment when I appreciated what everyone was saying about C++ compile times being quite slow if you (mis)use templates.
The Definitive C++ Book Guide and List : http://stackoverflow.com/questions/388242/the-definitive-c-b...
I like the breakdown of books by their goals in this FAQ : https://isocpp.org/wiki/faq/how-to-learn-cpp
I would say 'C++ Primer 5th Edition' and 'The C++ Programming Language 4th Edition' are good.
And of course, Effective Modern C++, although the other Effective series books from Meyers are a must read.
http://www.informit.com/store/c-plus-plus-primer-97803217141...
http://shop.oreilly.com/product/0636920033707.do
http://www.informit.com/store/c-plus-plus-programming-langua...
http://www.informit.com/store/effective-c-plus-plus-55-speci...
After sitting down and getting everything actually working between 2000-2010, C++ now seems to be on a steady path of improvement with major releases every three years with no plans to stop.
So, it's not a matter of waiting for things to finalize. It just deciding to go ahead and climb on board the moving train.
These books discuss performant (and sometimes complex) C++ code - in the domain of computer graphics.
http://www.amazon.com/Physically-Based-Rendering-Second-Edit...
http://www.amazon.com/Real-Time-Collision-Detection-Interact...
About how to use the new threading standard: https://www.manning.com/books/c-plus-plus-concurrency-in-act...
Also, the rest of the book is well written and worth reading for completeness, if not rather lengthy.
You highlight the daunting prospect of moving to C++. You need to pick half a dozen separate libraries and glue them together. Sure, once you've done that a few times it's pretty quick, but it's a scary prospect for a Django dev who can program in C.
That said I've found nodejs slightly nicer for distr
If you can bundle all your dependencies into a static file you're right, C/C++ is actually better as you have no install requirements.
However in terms of maintaining your dependencies, nodejs can be pretty great with package management coming with the npm tool. When you want to share your code with the world, and for someone else to actually use it, nodejs is easier.
In C/C++ you can use CMake to have external dependencies on git projects which is the best I've seen that you can do. If you know of any other tools that help with these problems please tell!
https://www.manning.com/books/c-plus-plus-concurrency-in-act...
Promises are already there.
This will also only be fixed in C++17. Boost future already implements more of this, but afaik it's still flagged as experimental, so it could change again. And afaik there were also some pending discussions about how futures should interact with schedulers/executors.
!! 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!
Briefly: "Seastar is event-driven and supports writing non-blocking, asynchronous server code in a straightforward manner that facilitates debugging and reasoning about performance." -- http://www.scylladb.com/2015/02/20/seastar/
Concurrency model: "Seastar futures/promises/continuations (f-p-c) are a subset of reactive programming.
Seastar performance derives from the sharded, cooperative, non-blocking, micro-task scheduled design, and f-p-c are a friendlier way of feeding tasks to the scheduler.
Seastar’s f-p-c do have some optimizations relative to other f-p-c designs. They trade off thread safety, which is unneeded due to the sharded design, for scheduling efficiency, and have a very low memory footprint." -- http://www.seastar-project.org/faq/
If you'd like to find out more, here are a few links with more information (including examples and tutorials):
- https://github.com/scylladb/seastar/wiki
- https://github.com/scylladb/seastar/blob/master/doc/tutorial...
- http://www.seastar-project.org/futures-promises/
- http://blog.cloudius-systems.com/2015/04/29/seastar-tutorial...
- http://www.slideshare.net/TzachLivyatan/seastar-sayeret-lamb...
In terms of practical applications, ScyllaDB (fully compatible--and significantly faster--drop-in replacement of Apache Cassandra) relies on Seastar: http://www.scylladb.com/
ScyllaDB has been discussed here before: https://news.ycombinator.com/item?id=10262719
<?php
$data = json_decode(file_get_contents('data.json'));
foreach ($data as $obj) {
echo $obj->x . ',' . $obj->y . "\n";
}
That's the entire script.Perhaps this example (benchmark, actually) is close enough: https://github.com/nlohmann/json/blob/master/benchmarks/benc...
Note that the above also performs mini-benchmark with multiple iterations, dumping parsed data to another file, and finishes with a clean-up of the aforementioned dump target file.
The core (read, parse, write) can be simplified to:
std::ifstream input_file("data.json");
nlohmann::json data;
data << input_file;
std::cout << data;If we were talking about language constructs/semantics or flow-control abilities, I'd have a very different opinion - but not having a json decoder builtin, is no reason to use or not use a language.
#include <fstream>
#include <json.hpp>
int main()
{
std::ifstream input_file("data.json");
nlohmann::json data;
data << input_file;
for (auto obj : data)
std::cout << obj["x"] << ',' << obj["y"] << '\n';
}I'm sort of surprised it doesn't come up more in this environment, but modern C++, Lua, and LuaJIT .. these things appear, to me, far more valuable than given by the hoipolloi ..
The point is, an investment in C++ does not mean you can't 'have all the fun toys too', because .. you can. And boy do they kick ass.
> "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.
I think it's fine to state that; are you ever going to write C++ code with zero included libraries? Probably not. If you write some string manipulation code and you boast that you did it in 10 lines are you going to count it against them that they included std::string?
I think saying how many lines of code it took, using the Wrangle framework, shows that it can be powerful and easy to use versus many of the libraries you end up seeing in C++.
Imagine building an overpass out of 3 prefabricated concrete pieces; two columns that serve as the base pedestals and 1 beam that spans them. The 48 lines of glue code to me are the nuts and bolts used to tie the pieces together. If the nuts and bolts are structurally sound then I would say our overpass has merit..?
However the TITLE OF THE ARTICLE is "Writing modern C++ servers using Wangle." Furthermore, the author states that he's using that framework almost immediately after the statement you quoted, so I really see nothing to complain about. It would be more of an issue if the author led with a huge introductory paragraph or click-baity title that failed to mention the library she or he is using.
Knowing how many lines it took for the author to implement the server in the Wangle framework is very relevant to the reader.
Offtopic, but this would be quite a challenge.
Yes, you can optimize it to whatever, but the point of mentioning that it is only a small number lines, it informs the reader they aren't going to get lost in a tone of code.
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-... ). 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.
Important info for some folks (i.e. myself).
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.
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...grepping the codebase for `asio` brings up nothing.
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.
Oh it's just a quick demo? Nevermind.
Example:
#include <proxygen/httpserver/HTTPServer.h>
#include <grpc++/server_context.h>
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.