Crystal – A Ruby-esque programing language
Crystal Clear
Crystal is an open source project that seeks to combine the best of two worlds: the simplicity of a language syntax similar to Ruby and the speed and capabilities of the LLVM platform.
In the fall of 2012, Argentinian Ary Borenszweig implemented his Crystal project [1] as a "programming language for people and computers." This sentence probably best expresses what this language sets out to combine: the simplicity and elegance of a Ruby-esque language syntax with the efficiency and speed benefits of compiled languages such as C.
The driving force behind the development of Crystal in recent years has been the Argentine software consulting company Manas [2], which is where Borenszweig works. As of this writing, some 100 volunteers are pushing forward with the project on GitHub [3]. You can look up all of the language's functions in a GitBook [4]. Newcomers can take their first steps without installing anything by entering code into a simple web-based Crystal editor and compiler [5].
Benchmark
The script in Figure 1 runs the Ruby code from Listing 1 as a simple benchmark. It includes a loop containing a multiplication. From the time measured at the start and end of the program, a simple subtraction gives you the execution time. Ruby 1.9.3 takes around six seconds, or around four seconds for JRuby. On the website [5], the same script takes only around 0.3 seconds (Figure 2).
Listing 1
Benchmark
§§nonumuber 01 time1 = Time.now 02 (0..100000000).each do |i| 03 i*16 04 end 05 time2 = Time.now - time1 06 puts time2.to_f
After installing Crystal on your computer (see the "Installation" box), you will find the crystal
command-line tool. To execute the Ruby script from Listing 1, all you need to do is enter:
Installation
Right now, Crystal is not found in the official repositories of major distributions.You can add the repository and install Crystal on your system, then install a number of additional libraries needed by Crystal at run time [6] as follows:
Debian and Ubuntu:
curl http://dist.crystal-lang.org/apt/ setup.sh | sudo bash sudo apt-get install crystal sudo apt-get install libbsd-dev libedit-dev libevent-core-2.0-5 \ libevent-dev libevent-extra-2.0-5 libevent-openssl-2.0-5 \ libevent-pthreads-2.0-5 libgc-dev libgmp-dev libgmpxx4ldbl \ libpcl1-dev libssl-dev libxml2-dev libyaml-dev libreadline-dev
Red Hat and CentOS:
curl http://dist.crystal-lang.org/rpm/setup.sh | sudo bash sudo yum install crystal sudo dnf -y install gc-devel gmp-devel libbsd-devel \ libedit-devel libevent-devel libxml2-devel libyaml-devel \ llvm-static openssl-devel pcl-devel pcllib-devel readline-devel
Some packages automatically resolve dependencies against other packages.
$ crystal bench1.rb
On the test system, the benchmark program only took 0.23 seconds to run the program code; thus, it ran 30 times faster than the plain vanilla Ruby version.
Crystal does not interpret the Ruby script; first, it compiles the script using the LLVM infrastructure (see the box "Victory for LLVM Compiler Infrastructures") to create native code. Crystal generates pure C code, which is strictly typecast – in contrast to Ruby code.
Victory for LLVM Compiler Infrastructures
At the University of Illinois, developers Vikram Adve and Chris Lattner, launched a study project in 2000 to implement a new compiler infrastructure. Their Low-Level Virtual Machine project (LLVM) [7] was intended to take all state-of-the-art principles for building compilers into account. In contrast to the legacy structure of the compiler, comprising a front end, optimizer, and back end, LLVM was created from the outset to fulfill the aim of developers to compile and optimize more than one language. For this reason, they created an internal version of the program code after the compilation process that is known as LLVM Intermediate Representation (IR).
The now very popular Clang compiler [8], which compiles C, C++, Objective C, and Objective C++, also stems from this project. With the help of Clang, LLVM generates executable code, not only on known desktop systems from the x86 processor family, but also on ARM systems, as used by most mobile devices.
A Ruby interpreter decides at program run time the variable type based on its situation. Dave Thomas, the author of the first language reference for Ruby [9], called this Duck Typing. The term goes back to the poem "Little Orphant Annie" by US poet James Whitcomb Riley, which says: "See a bird that walks like a duck and swims like a duck and quacks like a duck, I call that bird a duck." In Listing 2, Ruby determines the type of variable a
at run time.
Listing 2
Ruby Type Determination
In contrast to Ruby, Crystal identifies the type of a
at compilation time. It comes as little surprise then that Listing 2 causes totally different error messages in Ruby and Crystal. Ruby runs the first puts
command (line 3) but refuses to add the string to an integer (Figure 3).
The Crystal compiler also stumbles across this problem, but – in contrast to Ruby – does not even run the program up to the line with the first puts
(Figure 4). Crystal not only detects the right types for simple literals such as nil
, false
, 1, 3.14159265, 'a'
, :crystal
, and "crystal"
but also correctly typecasts assignments such as a = 1
and function arguments.
As an example, Ruby's language syntax lets you define a simple subtraction function as follows:
def sub(a,b) a - b end
The application can use this function in different ways:
c = sub(2,1) c = sub(2.5,1.6)
Crystal also supports this argument typecasting through alternative functions (for Int32 on the one hand, and for Float64 on the other).
However, Crystal can do more. Using the build
command, it influences the production of code in multiple ways. For example, the call
$ crystal build --release bench1.cr
creates a size-optimized executable that can run without Crystal. The tool
option, on the other hand, displays the source code of a Crystal file, so the developer can troubleshoot it. The command
$ crystal tool types bench1.cr
shows the different variable types that Crystal assigns to the program during the compilation process.
Language Functionality
Crystal solves some problems differently from Ruby. Unions are an important language construct that makes the code more flexible with static typecasting. A call to
alias Int32OrString = Int32 | String
generates the type Int32OrString
, which can optionally be an integer or a string.
Another interesting case has Crystal using Procs, function pointers with optional contexts, to create anonymous functions of the following type:
a = ->(x : Int32, y : Int32) { x - y } a.call(42, 23) #=> 19
If you want to manage multiple processes in Crystal programs, you can resort to fiber and channel constructs, which are known from the Go and Erlang languages. Listing 3 shows a socket server that creates 10 processes to serve a corresponding number of clients.
Listing 3
Channel, Spawn
Integrating C libraries also makes sense. For example, you can use the declaration in Listing 4 to include the mathematical functions of the standard C library. Using the structs known from C, you can also implement declarations like the one in Listing 5.
Listing 4
Math with Libc
Listing 5
Structs
Speed Benefits
To evaluate the speed benefits that Crystal seems to have, you need applications that can do more than just optimize loops. Table 1 shows a speed comparison between Ruby, JRuby, and Crystal for the multiplication of two 100x100 matrixes [10].
Table 1
Computing 100 x 100 Matrixes
Language | Time (s) |
---|---|
Crystal |
0.005 |
Ruby |
0.136 |
JRuby |
3.874 |
|
5,207 |
To keep this comparison fair, the program simply measures the execution time; it does not include the time that Crystal requires for compilation. Two values were determined for JRuby: direct execution time and a Java class file, which was created with the JRuby compiler (jrubyc
), so it could run on the Java Virtual Machine. The results for computing a Fibonacci sequence are similar (Table 2).
Table 2
Fibonacci Sequence
Language | Time (s) |
---|---|
Crystal |
0.206 |
Ruby |
0.250 |
JRuby |
3.849 |
|
5,311 |
Buy this article as PDF
(incl. VAT)
Buy Linux Magazine
Subscribe to our Linux Newsletters
Find Linux and Open Source Jobs
Subscribe to our ADMIN Newsletters
Support Our Work
Linux Magazine content is made possible with support from readers like you. Please consider contributing when you’ve found an article to be beneficial.
News
-
Halcyon Creates Anti-Ransomware Protection for Linux
As more Linux systems are targeted by ransomware, Halcyon is stepping up its protection.
-
Valve and Arch Linux Announce Collaboration
Valve and Arch have come together for two projects that will have a serious impact on the Linux distribution.
-
Hacker Successfully Runs Linux on a CPU from the Early ‘70s
From the office of "Look what I can do," Dmitry Grinberg was able to get Linux running on a processor that was created in 1971.
-
OSI and LPI Form Strategic Alliance
With a goal of strengthening Linux and open source communities, this new alliance aims to nurture the growth of more highly skilled professionals.
-
Fedora 41 Beta Available with Some Interesting Additions
If you're a Fedora fan, you'll be excited to hear the beta version of the latest release is now available for testing and includes plenty of updates.
-
AlmaLinux Unveils New Hardware Certification Process
The AlmaLinux Hardware Certification Program run by the Certification Special Interest Group (SIG) aims to ensure seamless compatibility between AlmaLinux and a wide range of hardware configurations.
-
Wind River Introduces eLxr Pro Linux Solution
eLxr Pro offers an end-to-end Linux solution backed by expert commercial support.
-
Juno Tab 3 Launches with Ubuntu 24.04
Anyone looking for a full-blown Linux tablet need look no further. Juno has released the Tab 3.
-
New KDE Slimbook Plasma Available for Preorder
Powered by an AMD Ryzen CPU, the latest KDE Slimbook laptop is powerful enough for local AI tasks.
-
Rhino Linux Announces Latest "Quick Update"
If you prefer your Linux distribution to be of the rolling type, Rhino Linux delivers a beautiful and reliable experience.