Hacker News new | ask | show | jobs
by manv1 1145 days ago
TL; DR: "It's better to design a fast system from the get-go instead of trying to fix a slow system later."

That's basically true. I worked on a system that was Java/scala/spring/hibernate and it was just slow. It was slow when it was servicing an empty request, and it just went downhill from there. They just built it wrong...and they went ahead and built it wrong again.

Today, I could replace it was a few hundred lines of node in AWS/Lambda and get multiple orders of magnitude of performance.

2 comments

We once rewrote an internal system because it was hard to maintain and the original developer had left the company. It was written in Java/Spring, and Kafka, but Kafka was being used like a database. It was just bad architecture.

We re-implemented it as a small Flask app with a PostgreSQL backend. We got rid of multiple servers, it was at least a magnitude more performant, and much easier to maintain and deploy as there were very little moving parts.

> Today, I could replace it was a few hundred lines of node in AWS/Lambda and get multiple orders of magnitude of performance.

I had a fun bake-off a few years back. I was in more of a devOPS role (i.e. mostly Ops but writing code here and there when needed) and we needed something akin to an API Gateway but with some very domain-specific routing logic. One of the developers and I talked it through, he wanted to do Node, I suggested it would be a perfect place for Go. We decided to do two parallel (~500 LOC) implementations over a weekend and run them head-to-head on Monday.

The code, logically, ended up coming out quite similar, which made us both pretty happy. Then... we started the benchmarking. They were neck and neck! For a fixed level of throughput, Go was only winning by maybe 5% on latency. That stayed true up until about 10krps, at which point Node flatlined because it was saturating a single CPU and Go just kept going and going and going until it saturated all of the cores on the VM we were testing on.

Could we have scaled out the Node version to multiple nodes in the cluster? Sure. At 10krps though, it was already using 2-3x the RAM that the Go version was using at 80krps, and replicating 8 copies of it vs the 2x we did with the Go version (just for redundancy) starts to have non-trivial resource costs.

And don't get me wrong, we had a bunch of the exact same Java/scala/spring/hibernate type stuff in the system as well, and it was dog-ass slow in comparison while also eating RAM like it was candy.

What you hit there is that Node's HTTP server is written in C. This is not "cheating", as you saw in that cookoff, the performance is real. But as you go back into the JavaScript engine, you'll return to JavaScript levels of performance, which aren't dozens of times slower than Go, but definitely generally slower in a noticable way even on one core.

This isn't criticism, just something engineers should know. If you've just got a little tiny task, and it fits on one core (and one well-used core does a lot nowadays), a Node solution can be effectively near C. It does have a sharp rise in costs after that, relatively speaking, but that's still a nice little performance curve for a lot of use cases.

Oh definitely! Yeah, as reasonably performance glue between native modules I'd have no hesitation using Node. I've mentioned elsewhere in this thread about my day job processing 500MB/s worth of live imaging data... I wouldn't be considering Node for that :). In "normal operation" it saturates about 6 of the 12 cores we've got available on the "embedded" system (is it really "embedded" if it has 12 beefy ARM cores and 32GB of RAM?).
Yeah, the one time I used go it was pretty good. The big question is always whether your stuff spends more time waiting or more time processing. For the former, it's node. For the latter, it's go.