Crystal – Lets Call it Ruby Plus Plus

Crystal

In the world of thousands of languages, added one more to the list is Crystal, which is General Purpose Object Oriented Programming language. It is a compiled language, and compiles to an ultra optimized native code using Low Level Virtual Machine or LLVM as the backend.

But what’s so special about it you ask?

Well, if you have heard about Ruby, and how every person who has used it, loves the language. Crystal looks almost like Ruby, but it goes one step further and fixes its shortcomings, some of which are:

  •  Concurrency
  •  Speed

Though a Statically Typed language, we don’t always have to specify the Type of a variable, Crystal infers the type from the data assigned. More about this below.

Oh, and did I tell you, its a compiled language. Crystal code compiles to effective native code, which helps it with the Speed part.

Also, Crystal allows you to use C libraries, without writing a single line of C code. Cool, isn’t it!!

Now, lets jump in to the necessary things, The Hello World program.

 # The customary Hello World program

puts "Hello World!"

Yup, thats it. And this is how you run a program. You first compile it using:

crystal build hello.cr

Which gives you a binary named hello, and, then you just run it, which prints ‘Hello World’ on the terminal:

○ → ./hello
Hello World!

That looked pretty easy, and the syntax is eerily similar to Ruby, which is certainly not a bad thing :).

Now that out of the way,  lets do something meaningful. How about writing an HTTP Server in Crystal? Well, had it been Java,  I wouldn’t dare jump to writing an HTTP server after a Hello World program.

But with Crystal, its really simple. It provides an http library out of the box, using which you can create an HTTP Server in minutes. Here’s the code:

require "http/server"

server = HTTP::Server.new(8080) do |context|
  context.response.content_type = "text/plain"
  context.response.print "Hello world at #{Time.now}"
end

puts "Listening on http://0.0.0.0:8080"
server.listen

Yeah, that’s it. This is what we see if we go to  http://localhost:8080

Server Output

Programming in Crystal is pretty concise, you don’t have to write 20 lines for a Hello World program, if you know what I mean !! 😉

If you have worked with languages like Python or Ruby,  you’ll feel right at home with the syntax, and if you have worked with Java, C#, you would be amazed how much can be done by writing so little.

Now lets jump into what’s special about Crystal.

Type Inference

Lets consider a class in Crystal

class User
  def initialize(@email)
    @password = "temp_pass"
  end

  def role
    @role = "customer"
  end
end

The above will work, even though Crystal being a Statically Typed language. The compiler will infer the type of the variable by checking what value is assigned to it in all the usages of User, but this does make the code a bit non-performant, as some compiler optimizations cannot be applied.

When types for variables are not defined, Crystal has some rules that it applies, and tries to guess the kind of variable, according to how the variable is being used. If it has been assigned multiple values, Crystal maintains a Set of Types, that the variable can be of. If a variable is not being initialized in the constructor, it adds the Nil Type to the Set as well.

In the above example, @role would be inferred as String | Nil : String, because customer was assigned to it & Nil as the constructor didn’t initialize @role

Below is the same class, with explicitly defined types:

class User
  @email : String
  @password : String
  @role: String

  def initialize(@email)
    @password = "temp_pass"
  end

  def role
    @role = "customer"
  end
end

You can read more about how Types are Inferred here https://crystal-lang.org/docs/syntax_and_semantics/type_inference.html

Concurrency

Crystal uses fibers to achieve concurrency, which communicate with each other using Channels like in Go. Fiber is like an Operating System Thread, but ultra lightweight. A program can spawn multiple fibers and Crystal with execute them.

Channels, which are based on Communicating Sequential Processes are used. They allow communication between fibers without sharing any memory or worrying about locks.

You create a Fiber using the spawn keyword, which work in the background.

Lets create a concurrent Hello World program which uses Channels and Fibers:

channel = Channel(String).new
10.times do
  spawn {
    channel.send "Hello Concurrent World!!"
  }
  puts channel.receive
end

This won’t do much though, just print Hello Concurrent World!! 10 times. The spawn block creates a background Fiber. The Channel.new creates a channel, which is a medium between the sender & receiver to communicate with each other.

In the above code, we are sending a message to our channel inside spawn using channel.send, and receive it back with channel.receive.

Crystal supports Concurrency,  as well as Parallelism.

Speed

So, lets compare, how fast Crystal really is compared to Ruby and say Java. Lets run the Base64 benchmark for all of them.

Its a simple benchmark, which tries to encode & decode a huge string 100 times using the Base64 algorithm. You can find the code used for each language here.

Language          Time(in Seconds)          Memory(in MB)

Crystal           2.30                      113.8
Java              9.06                      971.2
jRuby             12.65                     514.9

The results are astonishing. Crystal for this particular case, is 4 times faster than Java & almost 6 times faster than Ruby and uses much less memory as well.

You can checkout more benchmarks here: https://github.com/kostya/benchmarks

If you check the benchmarks in the above URL, you will see, that Crystal is faster than both Java and Ruby in all cases.

Finally

So, we can clearly see that Crystal has potential, its got the speed of Lower level languages and syntactic sugar of Higher level languages. Its yet to release a production ready Version 1.0, the latest version released being 0.21.0.

You can go here https://github.com/veelenga/awesome-crystal and checkout all the libraries/projects that exist and are being worked upon. There are multiple Web Frameworks, with Amethyst being the most popular and Rails like.

You can check more here: https://crystal-lang.org

Leave a Reply

Your email address will not be published. Required fields are marked *