
Using Go to improve your Ruby application's performance - vinnyglennon
https://antoine.finkelstein.fr/go-in-ruby/
======
thinkingkong
It might make sense to put some compute intensive tasks in Go, or any other
compiled language thats more efficient, but exec'ing and returning JSON isnt
really a great idea.

If you were going to consider this seriously, then you should have the target
app start once, listen for comands on some channel like a socket, and have it
return information. JSON is probably a little too verbose for this kind of
use-case as well, but it depends how efficient Ruby would be at unpacking
alternative serialization formats.

~~~
3pt14159
Why couldn't the coder use Extconf and just include the Go program into its
scope like C?

~~~
jamescun
With regards to Go, it is currently not possible as the Go compiler only
supports building static binary executables. For it to work with extconf, Go
would need the ability to build dynamic libraries.

There has been talk of incorporating this ability and slim executables go (I
think it might even be in the roadmap now).

------
oinksoft

      > Ruby uses green threads (meaning only one CPU will get
      > used) and they are no easy equivalent to Go channels.
    

Restriction to a single core is a consequence of the GIL. Also Ruby uses
native threads, not green threads, since 1.9.

The author's `execute` method is dangerous because it doesn't escape its
arguments.

------
issaria
You could replace `Go` with `erlang`, `haskell`, `rust`, `nodejs`, `c`,
`whatever language faster than ruby` and remain true here, amazing!

~~~
thescrewdriver
Almost anything with "Go" in the title gets upvotes on HN.

~~~
briandear
Similar to the way Bitcoin was HN upvote bait for a long time.

------
JonnieCache
If you want to extract parts of your ruby app to go in a simple way, may I
suggest a look at [http://www.goworker.org](http://www.goworker.org) instead
of following this articles advice.

(It's basically a golang port of Resque::Worker)

------
andrewvc
I don't really know why this is an article. So, uh, the author has discovered
that you can fork/exec a process? I'm not sure what is novel or interesting
that is presented here.

This article could have been written in 1998, titled "Using C to improve your
Perl application's performance".

I'll say this about this strategy. For most web apps (and ruby is mostly used
in webapps), it's usually more robust to just write a go background worker
listening over RabbitMQ or the like and just shove messages around as a
service.

------
obeattie

        JSON.parse(`go run json.go`)
    

No.

~~~
VeejayRampay
While I can sympathize with your critique, I wish it were a bit more elaborate
so that the author has an idea about what should have been done better. What
is bad about that? What are the alternative solutions, etc.

~~~
Svip
I think s/he objects to the idea of asking Go to compile and then run the
program each time, rather than running the resulting binary:

    
    
        JSON.parse(`./json`)

------
nkozyra
Grabbing the data from the exec response is a super clunky way of
communicating between two applications, particularly since Go is really good
at keeping long-lived TCP connections.

Even without connecting directly (which is just as trivial as reading a
response from exec), you should be looking at a formal message passing system.
This also allows you to easily distribute these dissonant applications, which
is a good idea when you're talking about "utilizing all the CPUs available"
and potentially high network usage.

~~~
Zikes
I think you're talking about a microservice, and I would agree. Go is well
suited for that sort of thing.

~~~
nkozyra
Well it's a microservice as described in the OP, I'm just talking about
formalizing a communication method. Reading CLI responses isn't a very smart
way to do it. REST APIs aren't really ideal for slow processes, either, which
is why my first thought would be something like RabbitMQ or just a simple TCP
connection.

------
dkarapetyan
So instead of using a unix domain socket and amortizing the cost of startup he
forks a process every time. This is ok for prototyping but definitely not ok
for any kind of production use.

------
scosman
Anyone wanting to do this at scale should look at posix_spawn to avoid forking
the process (ruby gem here: [https://github.com/rtomayko/posix-
spawn](https://github.com/rtomayko/posix-spawn)). Also probably ruby's
ShellWords for escaping.

~~~
VeejayRampay
Can this be used as a replacement for backticks or system calls? Would it
result in a lower memory cost?

~~~
scosman
A small savings for memory, but much faster. The link has benchmarks.

------
chuhnk
Why would you do this?! Please tell me this is some form of elaborate
trolling?

~~~
im_dario
I guess that is a simple way to delegate heavy processing tasks to Go.
Communication through stdout in JSON is an easy way to communicate between
Ruby and anything else faster than Ruby (C, Rust, Nim, Go, etc.) in specific
tasks.

------
joshcrowder
I agree there are some pretty big issues with this tutorial. However it's
still a pretty good article the "ideas" here are useful, I started thinking
about how I could use Go in my ruby stack.

~~~
danieldk
How so? The idea is not novel, in fact he links to a proper implementation
(having a Go process listen on a UNIX domain socket) and the only contribution
is to introduce a huge security vulnerability

------
glasnoster
In our startup, we've taken this a few steps further. Here's our CTO's
RubyConf talk about our approach:

[http://www.confreaks.com/videos/5076-RubyConf2014-harnessing...](http://www.confreaks.com/videos/5076-RubyConf2014-harnessing-
other-languages-to-make-ruby-better)

And my PyConZA talk slides:

[https://speakerdeck.com/pyconza/pyconza-2014-inspired-by-
lis...](https://speakerdeck.com/pyconza/pyconza-2014-inspired-by-lisp-to-get-
ruby-to-talk-python-by-martin-pretorius)

------
MoOmer
Using an RPC is a much more performant way to do this. Unless having ruby run
the Go program is a negligible performance cost.

------
reledi
I wish this article talked about some of the reasons you may _not_ want to do
this instead of just selling the strategy.

For example, this doesn't look appealing to me because it adds complexity and
makes your codebase harder to work with.

It's a neat hack, but I think in reality there would be very few cases where
this would be a good idea.

------
al2o3cr
Neat article. BUT:

Please, for the love of all that is holy, read up on `Shellwords.escape`. NOW.

Or at least do the rest of us a solid and post where you're setting up these
gigantic security holes-waiting-to-happen in production, so we know where NOT
to put personal data...

------
_mikz
For the ones that do not know, the escaping issues could be handled either by
Shellwords.shellescape or passing them as individual arguments to IO.popen &
friends (Kernel.system, Kernel.spawn ...)

------
Exuma
Very cool, I've actually been doing this lately in a slightly different way
and the performance differences are just monumental.

------
pjmlp
Others would use RubyMotion or similar.

~~~
evilduck
The article is about speeding up a Rails app. Unless you're planning on
hosting that web server on OS X, iOS or an Android device, RubyMotion is not
going to be of much use.

~~~
pjmlp
I said "or similar". Is RubyMotion the only Ruby compiler?

Personally I always favor solutions that don't require changing language.

As for RubyMotion, I thought it already supported any UNIX system.

~~~
evilduck
Are there any other Ruby compilers? I'm not aware of any that would be
comparable to RubyMotion (i.e. actually linking a binary that becomes more
performant and not just bundling a interpreter with your script).

And no, RubyMotion does not act as a general purpose Ruby, it only targets
iOS, OS X, and Android.

------
andyl
Another alternative using Rust...

[http://blog.skylight.io/bending-the-curve-writing-safe-
fast-...](http://blog.skylight.io/bending-the-curve-writing-safe-fast-native-
gems-with-rust/)

~~~
kibwen
It says something sad about the state of HN when a well-written blog post that
is relevant to the topic gets downvoted merely for not being written in Go.

------
mitkok
And the point of this is what exactly ? The author advertises Goss "Easy and
cheap concurrency", "Low memory overhead" and "Easy deployment", but the
example does not show how Go will help in this particular case.

