Performance wise, I don't think I need to repeat half the internet here, but I'll just say you'll be blown away by how little RAM a Rust app/container uses for the number of users hitting it. YMMV of course ;)
I thought that's only for syncronous libraries/frameworks? With async it blows out quite a bit. Everyone except rocket has got async functionality now too.
To illustrate this, consider the cost of spawning a new thread. The stack of a thread is usually a few MB, but lets use 1 MB for simplicity. Then 1000 concurrent connections is 1 GB of memory just for stack space.
With async/await, you don't pay a megabyte per connection because async uses perfectly sized stacks that are typically much much smaller than a megabyte.
Of course you can cap the number of connections, but IO speed puts an upper limit on how fast you can serve a connection, which means that the cap limits the number of connections you can serve per second.
Additionally, I doubt that the overhead at a few connections is large. There's a reason people call async/await a zero-cost abstraction, even if using a runtime such as Tokio introduces some amount of cost.
https://old.reddit.com/r/rust/comments/cych6a/async_performa...
The language is awesome and the performances too.
BUT, there is too many things that will distract you from being productive (compared to Node.js + TS or Go): unstable libraries, compile time is atrocious, cognitive load required to read Rust is high (break your flow), toolchain (RLS auto-completion) is weak, CI/CD costs are too high. You will spend most of your time solving Rust's problems instead of your project's problems.
In my opinion Rust is good on a 10-15 years timescale. But your project need to survive 10-15 years...
You can read the details here: https://gitlab.com/bloom42/wiki/-/wikis/engineering/language...
Based on your link, it looks like you are specifically referring to RLS. With the newer contender rust-analyzer[0] auto-completion is very good. In combination with TabNine[1] (for Rust the Pro version is free), auto-completion is pretty amazing by now.
I've added a little disclaimer because my experience was last year. The ecosystem is moving fast so some details may have changed (which is a cons for me, too unstable).
Totally unlike Node, right. ;)
With 5 years in PHP, 9 years in node, a few projects in Haskell and sporadic rust usage in the last couple of years: - PHP was great until they added autoloading and everyone started using a half assed package manager - node was great until everyone started using babel and they broke requires / import - python was ok until they split the ecosystem in 2 vs 3 - Haskell keeps getting better (stack, solved record name clashes) because things are rarely broken. It's too bad adoption is limited and there's not much commercial interest - Rust is my new favourite technology, it learned package management from node and functional programming from haskell. New features have been painless and easy upgrades
Rust offers perfomance improvements in CPU and memory usage of the core application logic, and it's almost never the bottleneck for the typical web apps. Almost always, they're limited by IO, and I don't see any reasons why it would be better on Rust that on Node. Also, Rust offers security of safe access to memory, but that's a problem that exists in C and C++, not in GC-based languages. Finally, Rust offers a great type system, but Typescript has a very good one as well, and offers a much easier transition for Javascript Node developers, as well as a much more machure NPM ecosystem.
Overall, I just don't see how Rust would make much of an improvement over existing state of affairs.
However the big caveat is the documentation and libraries are still quite lacking
And the mismatch between TS and JS is a pain, but that's why I'm looking forward to Deno.
Has anyone actually managed to find that this is the case? Just because your app is stalling on db queries doesn't mean it's "IO bound". Even the most trivial service that's just routing messages between two other services is likely to be radically faster when implemented in Rust vs JS.
OK, "IO bound" may not be the best description in this case. Because you're bound not by your ethernet card or operating system drivers, but literally by the work that's happening on a separate, database server's CPU. I should work on my terminology, thanks for the correction.
In my experience, it is usually waiting for DB. Regardless of whether your web app is well or badly written, it would get, at my estimate, would get no more than 5-10% request time improvement even if you made the app CPU infinitely fast, as 90-95% of the time is taken waiting for that database query.
But if you spend the same developer time rewriting all your ORM-generated n + 1 select statements to a single SQL query, you would still spend the same proportion of time waiting for the database, but your overall latency would get 10 times less. I've had some situations where I could get 10-20 time performance improvements by not touching application code at all, just tweaking the database indexes.
So, rewriting it all in a new language where you can, at most, 10% improvement, while you probably have areas where you can get 200-500% improvements seems unwise.
> Almost every web app.
No? My point is exactly that almost every web app is not io bound. They're just... slow. They write bad queries, they make bad usage of resources and block on requests, etc.
> Even WhatsApp scale runs on a “slow” dynamic language.
But that has nothing to do with being IO bound. Whatsapp, via Erlang, works by having tons of connections on a single box. And you can watch plenty of talks by them about how they've had to work with BEAM to get Erlang to actually be IO bound.
"IO bound" is a meme. Most people just mean "my queries are slow". Unless you're saturating your NIC, you're not io bound with regards to throughput, and unless your queries execute in ~<100ns you probably aren't IO bound on latency either.
However the important point is that they aren't CPU bound either. Most are "user acquisition bound" (like tens of requests per second peak). Some are more like "developer time bound" (cutting the server farm in half is not worth the cost in dev time).
Either way, using a slow development framework (including language, DB, etc.) that the developers like is a reasonable choice for what they're trying to do. (I personally wish most software was faster, but they have no reason to care what I think.)
Maybe the terminology around this could be developed some more.
4G latency 50ms
AWS inter AZ latency 1ms
Thread context switch 2us
The response times from things like search APIs even at FANG companies with vast resources and highly skilled engineers are often in the hundreds of milliseconds.
Rust can make app performance easier to reason about, improve performance, bring a real type system and all of this with a language which is just marginally harder to learn.
> oh wait, maybe someone is using this as any somewhere
There's a single option to disable any in all of your codebase. I've also found `unknown` type very useful for situations where you just don't care about what type you have, but would've had to use `any` before.
Rust has a pretty strict type system, and there's a lot of focus on correctness and reliability. Rust's enums with data are great for handling application state. This helps security, since the language stops you from doing entire classes of silly mistakes.
I've written some sites in Actix and it didn't feel too different from using express.js (with a caveat that I am experienced in Rust, so the language itself isn't an issue for to me).
"The Actix benchmarks which are winning are written at an extremely low level, with manual parsing, hardcoding header values as 'static string literals, ignoring HTTP methods, and basically being fast by skipping all of the work a real-world HTTP server would need to do to be effective"
The quote is 9 months old, but I doubt it changed since.
[0] https://www.reddit.com/r/rust/comments/e7xwma/rust_actix_is_...
[1] https://github.com/TechEmpower/FrameworkBenchmarks/blob/mast...
v8, is a JavaScript engine. An oversimplified way to describe it, is that it has an interpreter and a JIT compiler. Compiled code is faster, but not all code is elegible for that. If you write code that can be optimized by v8, it can run very, very fast. Most of the time v8 will give you decent performance but if you want to maximize performance by minimizing deoptimizations (e.g.: tracing compiler behavior using --trace-opt --trace-deopt CLI arguments)... you will be consuming more time than using Rust.
libuv is a crossplatform library written in C that handles all the heavy lifting for node. Using libuv, node creates an event loop and a thread pool, where asynchronous operations can be scheduled and executed concurrently. It also takes care of file I/O and networking.
node gives you a decent level of performance when you can delegate most of the work to libuv, or built-in JavaScript functions. But when running user-defined code that is CPU bound, node is not the right tool for the job. CPU bound tasks tend to block the event loop, or make ticks long enough so that it becomes a problem.
Blocking or slowing down the event loop causes time sensitive tasks scheduled for future event loop ticks, such as processing events from sockets, to timeout. This can be prevented using worker threads, which are a recent addition to node... but almost all of node and its package ecosystem has been built around the absence of user-facing threads.
node can be used to build robust, highly available, performant and secure systems, but you need to know what you are doing and what the limits are. I think node is not the right tool for every job, but when it is, it can be highly productive and save time.
Security-wise, node is hard to audit. Packages tend to have many dependencies, and many packages are not built with security in mind. JavaScript itself is a languge that has been built with browser security in mind, but also, JavaScript is a language where almost everything is mutable, including built-in types. Prototype pollution is a big problem.
Rust is more flexible, doesn't impose you a threading model, you have access to many concurrency primitives, and all your code will be compiled in a much predictable way. I am not familiar with the security aspects of Rust. At least it seems much safer than C, where it is not hard to create unsafe code.
I don't think Rust can or will ever choose that, Loom works because Java already has a runtime. It'd be a much bigger step for Rust.
https://github.com/getsentry/sentry-rust/issues/187
I did build a nice rust boilerplate tho if any one is interested
NodeJS has build it concurrency model on callbacks which make non-trivial application difficult to debug and evolve.
Since then new paradigms have emerged such as promises and structured concurrency (https://vorpus.org/blog/notes-on-structured-concurrency-or-g...).
Rust has build it concurrency model with those new paradigms in mind, mixing them with it awesome ownership model. In the end Rust brings to the table much stronger guarantees on your code consistency compared to NodeJS, which can save you a lot of time and energy on complex concurrent system ;-)
JavaScript has had async/await for four years (and promises for even longer than that).
JS has its issues but it's not at all helpful when criticism is badly outdated either.
Also, I'm not sure, but I think Scala had Futures before bluebirdjs existed, which was the defacto Promise for JS, AFAIK.
Bluebird wasn't the first JS Promise library. It became the defacto library because it was faster than everything else.
Edit: https://en.wikipedia.org/wiki/Futures_and_promises has a history
I do know that promises existed a LONG time ago, I was just referencing languages that still are popular-ish. I thought the Scala implementation was pretty old, but it looks like Java actually has everyone beat.