Modern web applications are typically database wrapping APIs with growing number of conditions to be met before accessing the raw database entry. Each of these conditions bring additional complexity meaning more object allocations and calculations. In popular dynamic languages interpreters (i.e. MRI for Ruby), allocations and method calls are quite resource-intensive. That’s in contrary to compiled languages, where all types are known before the program is run.

Ruby 3x3 goal confirms that the community is aware of the performance issue, but still, even x3 speed increase wouldn’t make Ruby fast.

One of the main performance gains achieved with type-safe languages is that methods are called immediately because their argument types are already known. In dynamic languages these arguments must be checked in runtime.

For example,

Sorbet allows to declare a method’s arguments’ and return types. Indeed, if you try to call this function with a String, it would raise upon calling srb tc:

As I’ve mentioned above, Sorbet doesn’t change the way an interpreter views your program, therefore a and b would still be checked in runtime by MRI. That’s in addition to the runtime overhead Sorbet adds by itself!

Ruby is a dynamic programming language. Its line-by-line interpretators will never be fast enough to compare with compiled languages. JIT is a nice attempt to do so, but usually its performance gain is neglected by the amount of CPU load and RAM it needs to perform its just-in-time compilations.

Premature optimization is bad, you would say. However, sooner or later a business understands that Ruby became a bottleneck and even caching doesn’t help enough. Usually such a business hires a number of Go or Scala or another compiled language developers to rewrite critical parts of the codebase for increased performance. This requires resources to communicate between Ruby and another-language engineering teams, support multiple codebases and also multiple tool sets, which means additional expenses.

Even with Sorbet, the performance bottleneck is inevitable and it’s just postponing what’s to come. It’s not a silver bullet by any means. Despite of a number of Ruby developers you have — even with type-safety — you cannot outcome fundamental dynamic language flaws. The most basic operations like object allocations and calculations would still be slow and sequential in Ruby (remember, MRI has GIL).

But what if there was a language with syntax similar to Ruby, but statically-typed and incredibly fast? This would restrain technical debt and make the codebase sustainable for long-term development, still keeping the expressiveness. Imagine having C-like speeds but preserving the development joy and great shipping confidence. This would make it perfect choice both for new and existing applications.

There is such a language.