Lithium ranked the highest performance web application platform
techempower.com
techempower.com
We execute runs like this continuously to allow maintainers of test implementations to observe the results of their contributions. Given the performance seen here, it is very likely that Lithium will be well ranked in the next official round. But we feel the ranking seen in a continuous run such as this should be taken with a grain of salt until that next official round is available.
[1] https://tfb-status.techempower.com/results/57b25c85-082a-401...
The industry grade server ecosystem that is the JVM use the jdbc which sadly has a blocking socket thus not allowing asynchronicty. But when loom arrive every jdbc existing code will magically, automatically become truly asynchronous such spring should come on the top 4 place.
There is also a wrapper of the jdbc through kotlin coroutines and there are reactive jdbc implementations such as R2DBC. It is unclear as of today if such solution enable postrgresql async queries and batch processing. It seems that nobody has tried those on TechEmpowerUp which is sad. Finally one could use libpq over JNI. Edit: I have read that the next release of pgjdbc (43) will switch from std socket to the NIO non blocking socket.
What should be heuristically the fastest HTTP framework (H2O, in C) has refused to use the old libpq fork because the api is not stable and thus not production grade.
FYI lithium is not using a libpq fork from 2016, it has been rebased on master 1 month ago. but yes Lithium (the sql-pipeline branch) is using it. (I mailed the drogon maintainer to update it aswell).
About H2O, the non batched version of lithium is as fast (slighly faster on some tests, slighly slower on others), while being much simpler to use (implementation of TFB of H20 is 4400 lines vs 250 lines for lithium...)
What would to you the other major optimizations?
Other big optimizations are - non blocking communications between the database and the framework - non blocking communication between the http client and the framework
This is for C++, for other slower interpreted languages: calling C bindings is a big optimization aswell (and this is how some php frameworks get good performances for example).
I know less than zero about Java and Loom, but if I understand correctly loom enables first class continuation and seamless M:N threading.
But I do not see how that will help jdbc, (unless you have tens of thousands of db sessions); I understand that the power of the new libpq is the ability to pipeline queries and that won't magically appear without development effort.
Assuming connection pooling, can't you just use another Thread to do your queries?
I can think of several metrics that would come first - even for sites with fairly high performance requirements.
How often is the web framework genuinely the bottleneck (at least in a way that's not easily fixable with caching or any other similar sledgehammer)?
Personally, it helped me realize that my mistaken belief that nodejs was hella fast and that old Java based frameworks are slow. It also introduced me to Kotlin (I started on it to try Kooby) and overall love that I can at a glance see that for my chosen set of languages, which farmeworks-dbs are a good bet.
Which surely are common but long(er) running database requests or delegation to another service aren't super rare either.
Similar some of the frameworks might have major reliability problems which can randomly "crop up" due to thread pinning and similar.
I believe it should have some form of "chaos" test where instead of interacting with the DB it interacts with a another test server on both ends and the front and back connected server run through long random "chaos" simulation (and another version where a pre-recorded run is used for reproducibility).
While the benchmark focus on more req/s, we can also see it the other way around: for the same req/s, you can use smaller hardware, i.e. save money and energy.
It has lead me to treat these benchmarks with a grain of salt.
There are very few circumstances that I can imagine that would send me running for C++ for a web project. I'm much more concerned about balancing efficiency of the developer environment with performance, security and maintainability, than pure performance. At the point that I'm not, my priorities are out of whack (aside from very niche situations). The side effect of these benchmarks, while we all love benchmarks, is the idea that any of these faster frameworks are actually a better choice because of a benchmark result.
OK yes, it a literal sense you can see things that happen in less than 100ms. What I mean is that you can't tell whether the nominal amount of flicker on page load is from the time it takes to paint the DOM or from the network request. Unless you were asking a professional front end developer, I don't think most people would even have any intuition about what was happening.
Unless it is super tuned, running on a specialise VM, I seriously have doubt about that. It is already pretty damn good if PHP/Python Django and Ruby Rails could do 10ms request excluding the Database on a moderately large App. Generally they are 20ms+.
And recently shopify even have their performance matrix allowing for 300ms per request.
And web servers are generally the least expensive component of hosting costs.
Given I already knew both frameworks from fulltime jobs, it's a great net benefit.
It also means that whoever wants to use self-hosted open-source alternatives of user-tracking services (notes, calendars, emails, etc), they can do it cheaper or even for free.
A web search for "lithium web framework" gave https://li3.me as the first result, which is a PHP framework.
Why did you pick such a name if already taken by a similar product?
Is it the use of some Linux only kernel API that enables it to be slightly faster than the other frameworks?
How widely do you use it? Everywhere? A few spots?
Why did you create lithium?
To see how much C++ can get closer to dynamic langagues typically used for web programming and at the same time make absolutely no compromise on performances.
How long have you been working on it?
8 months on lithium, but I already wrote another framework (silicon, which I rewrote from scratch because of slow compilation time).
What do you do professionally?
I worked for several company, doing different things including, real time image processing, neural nets for photography, web programming, robotics
What are your plans for it?
No big plans yet, just having fun for now, but I'd like to keep implementing the features if the users ask for it, improve the doc. In the more long term, building websockets would be nice too, and other services on top of it.
Besides your experience from writing Silicon [2], what other frameworks do you like the design of? What C++ codebases do you like or find interesting from a design perspective?
[1] https://github.com/matt-42/iod (merged into Lithium)
Just to be short, here is my phylosophy:
- don't think too much when you write it the first time, just do it quick. Do all the mistakes and ugly code first and then rething/rewrite things when it can actually simplify the codebase. Big refactors are much more productive and successful than big premature design thinking.
- Only expose the complexity that the user need. Simple things should stay simple even if we can do more complex stuff. Look for simplicity everywhere.
- Profile before optimizing, the bottleneck is never where you think it is.
For you question about metaprogramming, it is used yes. The core of the framework is build around a compile time key/value map that unroll json and get/post parameter de/serialization at compile time [1] so no dynamic dictionary involving costly malloc is needed.[1] https://github.com/matt-42/lithium/tree/master/libraries/met...
- a mainstream package/dependency manager is missing in C++ so rust is clearly better on this point. This is a big problem for the C++ community where code is much less shared than in the javascript community for example.
- The other big problem I have with C++ is compile time, I heard that Rust is slow too but I never compared the two.
And what robotics stuff have you worked on?I'm building a offline programming tool for industrial robots: http://stara-robotics.com/
I thought there were no zero cost abstractions in C++?
Still, it isn’t RoR or anything JS so it has that going for it.
Edit: Comment lower down suggests: https://github.com/matt-42/lithium is the correct one.
"Lies, Damn Lies, and Benchmarks" is somewhat true in this like any benchmark, but as others have pointed out, important techniques gain exposure using this benchmark over the years that trickle into mainstream use.
It would be nice if a summary of what techniques were used by new "frameworks" to gain leadership. All too often discussions of this benchmark turn into pissing matches by language zealots.
Actix's turn at the top was very interesting for the, uh, discussion, it prompted in the rust community about unsafe, although it was stressful for the original author.
In javaland, Vert.X has been high on the list for quite a while, but as I understand it, it uses "arena" allocation of buffers to avoid GC and other tricks to get the JVM up to par with non-GC languages, but isn't really typical of JVM development.
I would also like to know if HTTP protocol "hacks" are used, or networking tricks like userland network stacks.
But alas, it's just a huge wall of github projects and not a lot of use to a run of the mill developer like me.
But anyway, I'm pretty sure all framework maintainers will rush to provide all the info Techempower need to add a link to their website..
[0] https://github.com/TechEmpower/FrameworkBenchmarks/tree/mast...
ASP.NET Core is the newer (complete rewrite, inc runtime), leaner cross-platform (Win,Linux,macOS) Web Framework that's built on top of the performance focused .NET Core runtime released in 2016 https://dotnet.microsoft.com/learn/aspnet/what-is-aspnet-cor... They're only the same by name which is unfortunate, because it's completely new. It's the future runtime/platform for .NET and will be renamed to .NET 5 whilst the older .NET Framework will stay at v4.x (currently at v4.8).
I certainly wouldn't say that. Full Framework .Net and .Net Core are _far_ more similar than they are different - they share a very large common base class library API surface in Net Standard.
A huge percentage of .Net MVC 3-5 (full framework) applications could be migrated to .Net Core MVC in a matter of hours to days.
You don't even have to specifically target .Net Core in a lot of cases - v2 included a compatibility shim so that libraries targeting full framework just work as long as they don't call any of the API's that were in full framework but are not in the Core runtime.
The main differences are in startup configuration of your web app and how you go about implementing cross-cutting concerns that might inspect or intercept every request - but even for a lot of common things like authentication there are similar extension points to what existed previously.
There are some particular technologies - like WCF Server or Linq2Sql - that are hard blockers if you were relying on them - but by and large moving from older full framework .Net to .Net Core is not that difficult and certainly doesn't require learning much new, especially fundamentals - it's mostly just some details of the web app framework.
> The main differences are in startup configuration
It's definitely not the main difference, it may be what's immediately visible as a dev using it, but the entire Web Framework your App depends on is new. It's not a fork of an existing code base, it's a completely different one with the goal to retain the same development MVC & Web API model to preserve knowledge reuse & ease porting efforts.
The compatibility layers are just that, retrofitted to preserve compatibility & ease porting which is able to work through impl-free Reference assemblies with APIs they both share. Of course none of ASP.NET Framework System.Web is in .NET Standard, because it was rewritten.
The OSS code base for ASP.NET Core is at https://github.com/aspnet whilst you can view source code of .NET Framework (which isn't OSS) is at: http://sourceof.net
I always check any lesser known framework to see which ballpark it falls into. I'm always surprised to see that so many of the popular frameworks are ~10x worse than the best--although many of those 'best' don't do as much processing. I'm much more likely to pay attention to the error counts, max latency, or SD (σ).
I just took some small peak at atix (because I happen to know it) and while first all looked fine it wasn't quite that realistic.
Mainly:
- It uses a fork of tokio-postgres specific for the test (which differs in that Client is no longer send and it has a Unsafely soundness hole by wrongly using Unsafe Cell, and no Issue tracking enabled on, through replacing that cell with RefCell probably yield very similar performance)
- Instead of using the default web::Json responder it uses simd-json (EDIT: explicitly encoding the data into a buffer instead of returning it wrapped in web::Json)
- Uses snmalloc instead of the default allocator (https://github.com/microsoft/snmalloc)
Just to be clear besides the first point all of this is not unrealistic for a context where you want to highly optimize your server. But not how actix is used most of the time.
---
Edit: Also just to be clear I didn't nit pick intentional on actix, it just happen to be the framework I'm more familiar with and especially using snmalloc for actix seems to be quite a reasonable idea.
EDIT2: The Unsefety unsoundness isn't triggered given the way this library is used, it's still there and would prevent this change from ever been merged upstream.
Optimize your webapp before hunting for the fastest frameworks.
In web applications, apart from glaring mistakes such as N+1 queries, pretty much every bottleneck I had in production was due to slow serialisation, slow database abstraction or excessive CPU/memory usage due to language/framework. Also had issues caused by initialisation time. Saving 200ms or 300ms on each request can give you better user experience.
For growing startups, having a fast web framework gives you the choice to postpone doing complex horizontal-scaling for months, or even years. This saves money on the sort term and allows you to keep growing their products without having to worry about other things. The database can scale vertically in the meantime.
As for large tech companies: at my previous workplace there were two migrations in the span of two years because of performance issues. Hundreds of developers collectively agreed on changing the tech twice because of framework bottlenecks.
Of course you shouldn't go straight into a C++ framework when Rails becomes too slow for you, but people should know the tradeoffs of the framework they're using.
Believe me (or not) when I say that Amazon, among all FAANGs, could be the most data-driven, at least in the teams I knew, almost to an excess.
Once your app stops being trivial, those things start adding up and people start talking about migrating to something else, breaking the app into microservices, or developing in-house tooling. All those things cost money. It might take a few months but it happens. And I've seen over and over.
Also, having horizontal scaling is definitely not easy for non-trivial apps. It costs money to the company, might require extra employees, and might put a hold on new features. And horizontal scaling doesn't help you with performance time or developer velocity.
Also please keep in mind that performance and developer velocity are not at odds. Most of today's "fast" frameworks are quite good when it comes to developer velocity: ASP.NET Core for instance is #6 on the Techempower framework and is incredibly productive.
Horizontal scaling of course isn't binary and using a remote state store, preferably with CRDTs or strong consistency will allow _most_ applications to remove a spof and single node perf from dominating.
Everything you said is spot on, except for your dismissal that horizontal scaling should be first class. It might have been hard before, but we no longer have an excuse. Store your state in a modern distributed store.
> Developer velocity matters way more than the framework as long as the framework allows for horizontal scaling
I disagree with that. Both because developer velocity is not unrelated to framework performance, and because horizontal scaling is not a silver bullet that will magically solve the performance issues related to framework code.
"Only cases where the structure of the object is known at compile time are covered."
Numbers are impressive, but there are some big trade-offs that come with.
My personal criticism is that C++ is usually (not always, though) the wrong language for implementing web-facing applications or APIs. There is a considerable advantage in terms of speed (when using the right framework) but there are so many things that can subtly go wrong in terms of safety and security that you need to be very, very careful when picking C++.
And I write this as a C++ developer.
not obvious from a google search
Only the profiler will tell you if there is a hidden malloc that is slowing down all the rest, or a inefficient datastructure, or ...
There is probably lot of non optimized code in lithium, it just has no impact (or if it has I still has to find it).
That said, for other kind of software (usually more CPU bound), going down to assembly or using SIMD can be the only way to get good perfs.
From https://www.techempower.com/blog/2018/06/06/framework-benchm...:
We have already seen tremendous social adoption of the continuous benchmarking results. For selfish reasons, we want to continue creating and posting official rounds such as today's Round 16 periodically. (Mostly so that we can use the opportunity to write a blog entry and generate hype!) We ask that you humor us and treat official rounds as the super interesting and meaningful events that they are. Jokes aside, the continuous results are intended for contributors to the project. The official rounds are less-frequent snapshots suitable for everyone else who may find the data interesting.
"Rapid Web Application Server (in Assembler)":
Discussed on hn a few times as I recall:
https://news.ycombinator.com/item?id=9948749
(see also sshtalk):
Rust, C++ just said “hi” to you again, it’s on. Time to make Actix fast.
Seriously why is this reaching the front page, who really care about such benchmark ?
Some of the ideas developed in these frameworks percolate down to the PLs that use them and to the libraries they use, which benefits everyone. These frameworks also test new language features.