LLRT: A low-latency JavaScript runtime from AWS
github.com
github.com
In a nutshell: LLRT aims to have incredibly fast startup times compared to Node, Bun or Deno (which is critical in Lambda environments).
LLRT is built using Rust, Tokio and QuickJS under the hood. Here's their compatibility with Node.js APIs [1]
We (at Wasmer), have been working on a very similar approach: WinterJS, which is using SpiderMonkey instead (but also built on top of Rust and Tokio) [2]. HN announcement was just three months ago [3]
Really excited to see how the ecosystem is evolving!
[1] https://github.com/awslabs/llrt?tab=readme-ov-file#compatibi...
curl https://github.com/wasmerio/winterjs | grep -i license # :-(Edit: MIT license added! We had it on the Cargo.toml and wasmer.toml, but forgot to add the LICENSE file to the repo https://github.com/wasmerio/winterjs/blob/main/LICENSE
Not bad!
But I was already blown away by Bun's improvements over Node.
Edit: particularly curious about comparison with Deno deploy.
but then you realize you can achieve the same thing at 98% discount with traditional "monolith" setups with a load balancer soaking up all the requests
Serverless is a major failure
1. Scale to zero, which allows me to do things like automatically deploy a full environment for each branch in a project, with a full infra, frontend, backend, database, etc.
2. Good integration with IaC tools, so that I can define my infra and my runners in a single language/tool, be it terraform/cdk or something else. Most "monolithic" setups split configuring the infra and what runs in it into two tools/steps (please let me know of ones that don't!).
But if I actually run a application for a long time with somewhat consistent load there are always cheaper, more performant and flexible solutions than a serverless setup.
I’m actually working on a product to make that architecture more approachable (and cheaper yet). I’d be happy to hear from folks running network services on VMs and wishing there was a better way.
One huge advantage of FaaS infrastructure like Lambda is when your workload doesn't need to process >1 rps. Lambda, for example, has tight and unique integration with foundational AWS services like S3, SNS, SQS, and EventBridge.
Lambda is awesome when you need small scale reliability. I shouldn't have to run a VM 24x7 if I don't need to!
Running 1000's of EC2's at scale? Want to handle instance health notifications?
My favorite use of Lambda is S3 object event notifications, it makes it very easy to handle a variety of odd jobs by decoupling storage and compute and managing each independently. S3 Events are exactly the right use case for LLRT.
Sure, if you try to shove everything into that mold it is, but there are absolutely times where it's the best tool for the job. I run my entire, personal, company on top of it and it saves time, money, and energy.
It’s event software, like for a food festival. Most of the months there is almost 0 traffic, for 1-3 months there is lower traffic as pre-sales start with random spikes when the event organizers advertise, then for 1-5 days there is high traffic peaking on a single day or two during the event.
Because the load is incredibly spiky it’s nice to let Lambda scale automatically for me. Trying to scale a server, even bare metal, manually would be a pain in the ass. Even as I run this software for multiple events it’s cheaper than $5/mo and a $5 instance wouldn’t be able to handle the load at peak.
If my lambda bill ever got higher than an average of $20/mo I might consider a bare metal or VM server but honestly I prefer not thinking about it. And the profit dwarfs the server costs, like it’s not even close. The lambda server costs, even if they were 50x, would still be minor.
If you are writing an I/O bound JS service that doesn't do a lot of thinking, but does a lot of "moving stuff around", this will probably be a win.
A surprisingly high percentage of downloaded JS code is never run at all. (I can speculate: event handlers, unshaken trees, shaken trees with paths that happen to not be taken, ...) Of the rest, the vast majority is run once or a handful of times. That means startup time is a high percentage of total time, and therefore engines will JIT very little of that code, and the little that is JITted will use a baseline JIT that pretty much just translates opcodes to unoptimized machine code. The fancy optimization engineering that requires much cleverness and effort is actually applied to a very small percentage of incoming code. It will need to run something like 1000x before it is seen worth bothering with. Latency is more important than throughput for almost all of the JS that the engine sees. (Note that throughput-sensitivity can easily dominate most of the runtime, but that varies widely depending on workload.)
So browser-embedded engines already work hard at optimizing latency. We're not talking Python or Ruby here.
That still leaves a lot of potential for improvement by stripping the engine down and prioritizing latency above all else, though. There's definitely a niche for things like LLRT. And WinterJS, too.
(Source: I work on SpiderMonkey)
But the benchmark appears to be a very small program that imports the AWS SDK.
Later on in the readme, it's mentioned that LLRT embeds the AWS SDK into the binary.
So... How much of what the benchmark is showing here is just the fact that the embedded SDK loads much faster than application code?
I mean, it's certainly a valid optimization for Lambdas that are primarily making AWS API calls. But it'd also be interesting to know how much faster LLRT is at loading arbitrary code. As well as interesting to know if the embedding mechanism could be made directly available to applications to make their own code load faster.
(Disclosure: I work on Cloudflare Workers, a competitor. But, honestly interested in this.)
This is what hermes is currently doing.
It feels wild, people have been calling UI-libs from JS as well: https://twitter.com/tmikov/status/1720103356738474060
I can imagine someone making a libuv binding and then just recreating Node.JS with the FFI
I'm told this library is multiple megabytes of JavaScript. (That's why Node takes so long to load it...)
The SDKs are "bundled" in all lambda runtimes but normally not into the binary, what additional performance would that bring?
I haven't looked at LLRT's internals, but if I were them, and I were bundling some JavaScript code into a binary and seeking to really optimize startup time, I would probably pre-parse the JavaScript text to produce QuickJS bytecode (or whatever data structures QuickJS actually interprets at runtime; no modern interpreter is actually processing raw text as it goes). In the best case, embedding something like that into the binary could mean that startup processing of the embedded code is O(1) (just like how startup time for a native-code binary is independent of its size, as long as it doesn't have global constructors).
i've been burned by Amazon with these type of claims can we get confirmation this is backed up actual real world testing from a non-amazon affiliated source?
> LLRT offers up to over 10x faster startup and up to 2x overall lower cost compared to other JavaScript runtimes running on AWS Lambda
I read this to mean that AWS only cares about performance on AWS Lambda, and it's probably not this much faster outside of the Lambda contxt
With WASM GC landed, and WASI preview 3 taking on async / event loops, it seems like this should be possible soon, except for the very large task of actually writing the compiler.
If you restrict yourself to a subset or are willing to risk incompatiblities then it will work.
There's some TypeScript to Wasm compilers that should work reasonably well (If you're breaking TS rules you've got yourself to blame a bit more than with JS).
Ref: My thesis was on JS AOT and even if I had the idea of making it commercial I didn't pursue it in the end.
Is it available online?
Most relevant for my above comment re AOT vs JIT is that JS semantics (I think I touched upon it in the thesis) will have the same issues that made JIT's win out with BigInts in the Agesen&Hölzle paper (whilst the paper is on AOT's my goal was to find a solution for game developers so numerical performance was a non-moving goal for me).
My thesis http://kth.diva-portal.org/smash/record.jsf?pid=diva2%3A8232...
Agesen & Hölze on JIT vs AOT https://citeseerx.ist.psu.edu/document?repid=rep1&type=pdf&d...
WASM itself is often JIT'ed so a JS-to-WASM compiler that functions like the common JS baseline compilers would still get some benefit of JIT'ing even though the types available to the ICs in WASM may not be as useful as in JS.
https://cfallin.org/blog/2023/10/11/spidermonkey-pbl/#future... has some interesting ideas on enabling the SpiderMonkey baseline compiler for WASM and possibly using partial evaluation to see better types.
I plan open source it later this year - have improve build and remove some client's code.
https://shopify.engineering/javascript-in-webassembly-for-sh...
And Bun of course :)
I can definitely see aws' lambda operations gaining quite a bit from this.
Only faster for code that runs under 5 ms. But a lot of code runs under 5 ms.
(I hope the quote is right, I'm not on twitter.)
I think it makes Lambda better, but not more attractable to use cases that are better served by scale-to-zero managed containers runtimes like Fargate.
I can certainly see how that would substantially reduce cpu and memory cost but the code would execute 50-250x slower.
https://bellard.org/quickjs/bench.html
If startup time is relevant to you then you are probably not doing much computation in the first place.
This wraps QuickJS and there is not a single mention on their front page. At least a hello or shout-out to Fabrice Bellard would have been nice.
But I guess it's AWS and they do this with other projects, so not too surprising.
Mentioned in the third-party file: https://github.com/awslabs/llrt/blob/630ec79/THIRD_PARTY_LIC... / https://archive.is/0NUAa
> AWS and they do this with other projects
Remember similar concerns raised viz Firecracker (which is a hard fork of Google crosvm: https://news.ycombinator.com/item?id=22360232), but don't recall it being a pattern.
Probably a nod to the ElasticSearch licensing debacle.
Agree with you there should be credit where credit is due - I have been using QuickJS for some time and its awesome. For the cost of about 1MB you can get entire modern JS in your C/C++ binary.
I also had to double check but we do indeed list it on our website, albeit in a sea of others.
> LLRT is built in Rust, utilizing QuickJS as JavaScript engine, ensuring efficient memory usage and swift startup.
[0]: https://github.com/awslabs/llrt/commit/054aefc4d8486f738ed3a...
https://github.com/awslabs/llrt/commit/054aefc4d8486f738ed3a...
Props to them on the quick fix!
In fact our trust in AWS and the team has plummeted that we ultimately ditched serverless and went str8 to VPS
The days of zero interest rate series B buying up reserved EC2 instances in the millions are gone. As capital gets expensive we see more reluctance to moving to cloud.
AWS claims of "10x faster startup @ half the cost" is confirmation that the Serverless movement is DOA