Hacker News new | ask | show | jobs
by chrisseaton 4033 days ago
People talk about how Crystal's performance is better because it's statically compiled and removes Ruby's dynamic features, but I'm not sure static compilation is the best way to achieve performance, and I don't think the dynamic features need to damage performance.

For example, JRuby+Truffle runs Crystal's own sample programs around twice as fast as Crystal does, without static compilation, and while still supporting all the metaprogramming and dynamic features of Ruby such as monkey patching, send, method_missing, set_trace_func, ObjectSpace etc.

https://gist.github.com/chrisseaton/91c7cbf8f6f4f6ea44bb

However Crystal does start faster, and I'm sure it has lower overhead.

2 comments

Did you compile the Crystal program with the --release flag? That turns on optimizations. On our machines we see Crystal is faster in this benchmark, it always takes about 1.6s while JRuby+Truffle reaches 2.38 at most.
No, I didn't, sorry!

I don't see that option documented anywhere except the changelog, and one passing reference in the docs that says it sets the release flag, but neither say it has any effect on optimisation.

Yeah, we need to document this better, sorry!
Get used to this, watching people run benchmarks after having forgotten to compile with optimizations is basically a meme in the Rust community. :)
I don't think it's a big deal, benchmarks are just toy programs. Once you learn about the `--release` flag you never forget it for production-ready code.

C has -O3, why isn't it the default? Because it takes a lot more time to compile. So I think no optimizations by default is the best choice. And I think Rust should do the same, you will be compiling more things in non-release mode than in release mode.

Compiling without optimizations is indeed the default in Rust, but we have seen such an unbelievably large number of people not realize that a `--release` option exists that there have been several debates regarding whether or not this should be changed. Instead we've stepped up our documentation, we've made the package manager tell you which mode it's compiling in, and we've made Cargo put the finished binaries in either a clearly-named `debug` or `release` directory... and yet still they crash upon our walls, waving benchmarks where Rust is seemingly three times slower than Ruby.

It may seem obvious to you and I that compilers have optimization levels, but consider how many people for whom Java, with no optimization level flags, is their only exposure to a manually-invoked compiler.

Right, but if you want the static checks for safety, then even if you run on something like Truffle, you will lose a lot of dynamic behavior. Either that or your static checks won't be able to check as much, and will give you weaker guarantees.