shishini

shishini

Elixir vs Go Performance (Anton Putra)

I think this twitter post and youtube video didn’t get as much attention as I hoped
I am still new to Elixir, so can’t really judge

https://x.com/antonvputra/status/1865845828192977341

Its generally understandable that a compile statically typed language like go will be faster than Elixir (being dynamic and running on a vm) but I a bit surprised the availability performance

First Post!

ruslandoga

ruslandoga

:wave:

Some ideas:

  • setting +sbwt none to avoid busy wait consuming the allocated CPU slice (might be irrelevant in this benchmark if there is no wait under load) it was already set
  • ensuring System.onilne_schedulers is equivalent to the available CPUs inside the container should be done automatically already: OTP 23 Highlights - Erlang/OTP
  • ensuring TCP socket options (recbuf (rcvbuf), sndbuf, backlog, reuseport, etc.) are the same for Go and Elixir
  • switching to :json
  • (possibly) disabling Logger or increasing the log level (is Go logging?)
  • separating the Web and DB benchmarks to see where the slowdown is coming from
  • (possibly) spawning processes handling the requests / connections with larger heaps to avoid reallocs
  • (possibly) switching from Bandit to an alternative web server, I remember playing with an Elli-like HTTP/1.1 server and it was outperforming both Bandit and Cowboy in benchmarks with wrk
  • (possibly) switching from Postgrex to an alternative PostgreSQL client and/or connection pool
  • (possibly) running multiple Postgrex pools

However, all of these steps are not common among Elixir developers, so I think the benchmarked app is about as representative (of what we typically write) as it gets. And the benchmark itself highlights some areas for possible improvement :slight_smile:

Most Liked

josevalim

josevalim

Creator of Elixir

Here is a pull request that makes the Elixir code closer to the code in Go and uses better defaults (for example, what Phoenix would have used): Make benchmarks with Elixir fairer by josevalim · Pull Request #370 · antonputra/tutorials · GitHub

josevalim

josevalim

Creator of Elixir

The issue is not Postgrex, but rather the fact it is comparing Ecto (which would be akin to a ORM):

https://github.com/antonputra/tutorials/blob/59d29deeb57b1a81fe9c2c5e4dcb44e96c6bedb8/lessons/230/elixir-app/lib/app/router.ex#L62-L73

With something that directly sends INSERT commands over the connection:

https://github.com/antonputra/tutorials/blob/main/lessons/230/go-app/device.go#L30-L33

And if you are going to set up 500 database connections, I would at least split over a few connection pools (by setting pool_count). Otherwise you are likely making the pool the bottleneck.

Overall, I’d expect the Go to have better throughput, but there is definitely a bit of apples to oranges going on. I honestly don’t understand why benchmark authors do not ask for some community vetting before publishing.

21
Post #7
josevalim

josevalim

Creator of Elixir

Thanks for sharing. I am a bit surprised indeed the new round did not see any improvement, given my pull request yielded a 20-30% improvement locally. I cannot reproduce the failures from the first benchmark on my machine either, I even used a separate machine to push traffic locally and I get 80k req/s for Elixir vs 110k req/s in Go.

However, it is worth saying that it is 100% expected for Go to be faster than Elixir. After all, we are comparing a static imperative compiled language to a dynamic functional language running on a VM, so a reasonable difference (within the same order of magnitude) is expected. For example, TechEmpower main branch puts Go around 5x faster than Phoenix for single-query runs. I am mostly curious about the failure rate, which is not expected, but as far as I know, there is no way to reproduce the benchmarks and the production logs were not shared with us. So there isn’t much we can do at the moment.

Last Post!

outlog

outlog

  1. Only p90 is being tested/shown - way to low.
  2. A custom simple thrown together client is being used - most likely doing CO(Coordinated Omission) - eg. results are incorrect/misleading
  3. One system is mostly tested in overload >100% cpu (due to 1&2 nothing is really measured before overload occurs eg. latency 0?! ), the test is quickly stopped once the Go test reaches overload.
  4. The tests are out of sync, one test gets ahead of the other, for a given time.

Remedy:

  1. Use p99, or better measure the distribution.
  2. Use a proper client like Gatling (it even has an easy to use/install javascript tool these days: https://docs.gatling.io/tutorials/test-as-code/javascript/running-your-first-simulation/)
  3. Keep going into overload, for both systems.
  4. Solved by 2 - using a proper client.

So it’s all about using a proper load testing tool/client.

Where Next?

Popular in Discussions Top

ben-pr-p
In general I’ve been sticking to this community style guide GitHub - christopheradams/elixir_style_guide: A community driven style guide ...
New
pillaiindu
In django there is a cache framework backed by memcached. Rails also puts a lot of emphasis on caching, and even the idea of russian-doll...
New
jer
I’ve been using umbrellas for a while, and generally started off (on greenfield projects at least) by isolating subapps based on clearly ...
New
AstonJ
If so I (and hopefully others!) might have some tips for you :slight_smile: But first, please say which area you’re finding most challen...
New
gausby
I asked this very same question on twitter and got some interesting feedback, but I thought it would be a good question to ask here as we...
1207 40165 209
New
Fl4m3Ph03n1x
Background A few days ago I was listening to The future of Elixir from Elixir Talks, with Dave Thomas (@pragdave ) and Brian Mitchell. I...
New
RudManusachi
What configs will make sense to put to runtime.exs? – A bit of how I configure apps: I have generic configs in config/config.exs, dev...
New

Other popular topics Top

Brian
What is the proper way to load a module from a file in to IEX? In the python world, doing something like this pretty standard: from ....
New
gshaw
What is the idiomatic way of matching for not nil in Elixir? E.g., First way: defp halt_if_not_signed_in(conn, signed_in_account) when...
New
gausby
I asked this very same question on twitter and got some interesting feedback, but I thought it would be a good question to ask here as we...
1207 40165 209
New
AstonJ
Seen any cool LiveView demos, sample apps or examples? Please post them here! :003:
New
alice
Hey, Just curious what are the main benefits of Elixir compared to Clojure? When is Elixir more useful than Clojure and vice versa? Th...
New
dblack
I’ve got an issue with an app and I’ve no idea of how to troubleshoot it. I’m hoping someone here might have seen something similar. I p...
New

We're in Beta

About us Mission Statement