Ruby + Go: How To Make Them Work Together

Ruby programming language is developing extremely fast. Why? Its main advantage consists in the speed of development, which in average is 30–40% higher in comparison to other languages and frameworks based on them.
It becomes possible thanks to a wide set of ready-to-use default tools. Besides that, there are many solutions and ruby gems created within programmers community, what makes development stages simpler.
Although afterwards, some rails services were re-written with the help of other languages and technologies — Twitter was re-written in Scala, iron.io — in Go. But is it necessarily to rewrite all applications? In fact, it is not always the speed of development which is a bottleneck — it can be the database or something else as well.
We start thinking whether it is possible to define bottlenecks in the application when the speed of development is limited by the performance of Ruby and rewrite only these parts using highly performed language Go. Herewith the changes should apply only to selected areas of the application, and at the same time, the rest of code should remain in original view.
Use of the method on a real example
To show the advantages of using Go in separate resource intensive areas of Ruby code on a real example we will build “nested keywords”. This method allows creating logical connections from a single set of high-frequency words (and thus more competitive) to verbose low-frequency requests, which are much easier to promote in search engines.
Below you can see an example of building “nested keywords”:
And that is the result we get after adding Go code:
- 7000 words: Ruby — 60 ms, Go — 150 ms;
- 17000 words: Ruby — 6 min, Go — 3 min 43 sec;
- 64000 words: Ruby — 15 min, G — 7 min.
It is obvious that huge performance gain becomes noticeable with a large volume of data. But when looking at the first example, we can see that transformation of input and output data using Go, on the contrary, took more time. Besides that, we should take into account that the current task is not subjected for parallelization. If the data could be processed in parallel there will be a little difference between languages. That’s why applying of chosen method depends on a specific task which has to be solved.
Technical side of the question
It took little efforts to link RoR and Go with a help of quartz, which is set as a gem in Ruby and as a plugin in Go. For data exchange, they use UNIX sockets which are transferred in JSON formatting.
Now we will go on with the technical side of described method:
Setting up Go:
go get github.com/DavidHuie/quartz/go/quartz
Add it to requested script:
import (“github.com/DavidHuie/quartz/go/quartz”)
Setting up Ruby:
gem install quartz
require ‘quartz’
The implementation of RPC-server in Go
As Go is called from Ruby, we need a way to exchange data. Quartz allows embodying RPC-server to process messages from Ruby.
For this purpose we have to define the following objects:
- resolver — an object which contains methods that are performed from outside;
- arguments — describes incoming arguments;
- response — describes result.
Program written in Go will look as following:
Call remote procedures from Ruby
An example of our code in Go for building “nested keywords”:
The code in Ruby — it is commented out code, implementation of Go-algorithm.
In conclusion, we should say that the current method can significantly improve application performance which in its turn will increase the speed of data processing without the need of complete rewriting of an existing project.