3 Feb 2017

Memory-efficient Languages for the Server

I'm an independent app developer who's planning to build a web app. I thought I'll write my server in Java and run it on App Engine, but I found that App Engine's cheapest instance class has only 128MB memory. That doesn't seem enough to run a JVM and do much.

Lest you think this is an App Engine-specific problem, other providers' cheapest instance types also have low memory, like 512MB on Amazon, Heroku and Digital Ocean [1]. That's better than 128, but still seems uncomfortably low to run a JVM and have enough headroom.

Even 512MB is tiny by modern standards. It's much less than that of a smartphone. Or even an old smartphone, like the 5-year-old Galaxy Nexus, which had 1GB!

I could, of course, use an instance type with more memory, but that costs more, in many cases significantly more. The cheapest App Engine instance costs ₹1700 for 128MB, but if I want 512MB, it will set me back ₹6700 a month. The story is similar with Heroku: the least memory I can get is 512MB, which costs ₹1900, but if I want 2.5GB, it will set me back a huge ₹19,000 every month.

Which is fine if the app generates an order of magnitude more profit than that. But there's always the risk that that won't happen. Or the app may have enough users but insufficient revenue. In either case, I'll have to pay the bill out of my own pocket every month. Which will, in turn, force me to shut my app down sooner than otherwise, depriving me of time to iterate on it and turn it around. I wouldn't like to be forced into that.

And that's for just one app. I plan to build multiple, so the hosting costs will add up. I don't want to be forced into using a single service / server to host backends for multiple unrelated apps, which is less secure and reliable.

If an alternative to Java comes along that consumes significantly less memory, thereby reducing hosting costs, but works just as well for the task at hand, I'll seriously consider it.

Swift and Go seem to fit the bill. They consume at least 40% less memory, according to the aforelinked benchmarks. Of course, it may not be 40% in your case. But whatever the exact number, I think it's clear from this benchmark and other sources that these languages consume significantly less memory than Java [2] [3].

And are perhaps no less productive to work in than Java. Swift, in fact, seems more productive a language, from the three months' experience I have with it. If my assessment is correct, it's the best of both worlds — Swift makes me more productive, and costs me less. What more could I ask for?

To be clear, I'm not saying that memory consumption is the only factor. Or even the most important factor. Availability of libraries for what you need is more important [4]. There's also the advantage you get by building your backend in the same language as your frontend.

Then there's productivity. For a web app, my first preference will be a dynamically-typed language (like Typescript or Ruby), since I've found them to be more productive to work in, even if they consume more resources.

There are other factors as well.

So, I'm not saying that you should focus on increased hosting cost from memory-inefficiency, ignoring all other factors. Rather, memory-inefficiency is a factor you should consider, along with all these factors, weighing them appropriately, when you decide which language to use. Put differently, a memory-inefficient language better have other advantages to offset its increased hosting cost. If it doesn't, there's no reason to use it.

[1] Whether PaaS or IaaS — the above list includes both types.

[2] It's interesting that garbage-collection doesn't seem to be the problem here, at least according to the above benchmark: Go is garbage-collected and consumes much less memory than Java, comparable to Swift, which isn't garbage-collected. This means it's more a question of the design of the language.

Java doesn't have structs, so an object that's a field of another object requires a separate allocation. An array of 100 objects requires 101 allocations. To store primitive types in collections, you need to box them. And so on. Java has a lot of overhead independent of garbage-collection.

[3] You could also use Rust, but I don't know if it's as productive to program in as higher-level languages like Swift or Go. If it is, then yes, it's the third contender.

[4] These could be client libraries to access cloud services you need. Or an extensive standard library that covers the tasks you do on the server. Or third-party libraries.

No comments:

Post a Comment