
Why I switched from Ruby back to C++ - chrismdp
http://chrismdp.github.com/2012/01/why-i-switched-from-ruby-back-to-c-plus-plus/
======
frankPants
This post should be titled, "Why I fucked up by choosing Ruby to write a
game." - Or "What the fuck was I thinking"

I love Ruby, I spend a lot of time writing it. I also write kids games for
iOS. I would never consider Ruby(in it's current state) a good language to
write a game in. Anyone who would has clearly; never written a game before; or
never used Ruby for anything serious before.

I agree with the other posters, you should investigate ObjectiveC though. You
can get ObjectiveC packaged and running on Windows BTW, don't worry about
that.

~~~
kenjackson
While what you say may be 100% true you might be shocked by the number of Ruby
and Python devs I talk to who tell me that Ruby can do anything that C++ does
if you're even a half-decent Ruby or Python dev. I've literally asked people,
"What about something like Gran Turismo 7?" And I've literally been in rooms
where every dev there (none game devs, all web devs) basically said if _they_
were writing it in Ruby it could be done, but they wouldn't trust Sony devs to
be able to do it.

This may not be the case for all Ruby devs, but I think having these stories
out there is still useful.

~~~
mileszs
For what it's worth, I help to organize a fairly active Ruby group, and I am
certain that, if not zero, nearly zero of us would make this proclamation. In
fact -- and I mean not to attack you, but just to illustrate how incredulous I
am -- I tried to think of a reason there might be for you to fabricate or
exaggerate that story. I don't really think you did, but my mind went there.

~~~
kenjackson
Didn't make it up. No reason to do so, although I suspect if I spent some time
on HN I could find some posts about Ruby perf that don't jive with reality.

But I will say this, do you think this guy made up his post about using Ruby
to try to write this game? If you don't think it fabricated, do you think he's
alone?

I do think there is a fundamental problem, especially with respect to perf,
that a lot of people have never looked at what code actually runs on their
box. Never looked at the emitted or generated asm. Don't know the cost of
calling a method, much less invoking some framework routine to do something.
And then you couple this with a lot of devs think their the cats meow because
they got x trans/sec and hear horror stories about the ceremony and
inefficiency of C++.

And it doesn't help with the blogs and articles that constantly come out
saying that Java or Ruby or Lisp is faster than C/C++ (the answer is never
pleasingly straightfroward).

While I appreciate that none in your Ruby group would think this, I'd also ask
why do they believe this? It's no more reassuring if they don't have a clear
understanding of why C++ might be better for the job.

Lastly, I should add that the conversation was a heated discussion where I was
playing devil's advocate that I thought they were going to switch off of Ruby
like Twitter. I don't think they really appreciated it, although I wasn't
actually being all that serious at the time.

~~~
mileszs
> But I will say this, do you think this guy made up his post about using Ruby
> to try to write this game? If you don't think it fabricated, do you think
> he's alone?

I neither think his story is fabricated, nor do I think he's alone. (I didn't
say I really thought your story was fabricated, either.)

> While I appreciate that none in your Ruby group would think this, I'd also
> ask why do they believe this?

I don't know that we would all choose C++, were we building a game, but the
performance of Ruby is frequently a topic of discussion. We are lucky enough
to have several members that have significant experience working with/around
Ruby performance, and they share their knowledge. In other words, were you to
choose one of us at random, we would more likely be able to tell you why Ruby
is not a good idea, as opposed to why C++ is.

------
jrockway
I think the author's problem is not choice of language, but rather choice of
architecture. He notes that he was passing a lot of float objects between Ruby
and C, eating up valuable garbage collection time. The problem here is not the
bridging of Ruby to C, but rather the wrong choice of data structure and
design. Ruby should pass high level requests to the (C-based) rendering
backend; instead of passing "push a vertex at (1,2,3)", the requests should be
like "draw a spaceship at (1,2,3) flying forward with velocity vector
(1,1,0)". The means you're going to be writing the core of your game in C, but
things like AI and level design will all be handled in Ruby. (I think pretty
much every commercial game works like this.)

Another thought is to treat simulation and drawing as separate concerns. Every
1/60th of a second, interrupt the simulation and draw the current state to the
screen. This means that you can do things that take more than one frame to
calculate without reducing the framerate. (Does Ruby have a good coroutine
library?)

Rewriting your entire game because your design is bad is silly. Switching to
C++ just makes your mistakes less obvious. (And now you'll be debugging memory
leaks and segfaults instead of slow frames. If only there was One Perfect
Tool...)

~~~
atomicdog
>(I think pretty much every commercial game works like this.)

Is it common for commercial games to write AI in Ruby now?

~~~
AndrewDucker
Lua is the most common language, I believe. But the pattern still holds.

------
nevinera
"Why I switched from screwdrivers back to the hammer."

Because, while pounding in a few hundred nails with my trusty flathead, I
noticed that it was taking really a great deal of work.

------
ansgri
After working 1.5 years on soft-realtime video processing systems (and game
development fits this category), I feel like there's no real alternatives to
C++. Because (1) when you have performance problems you can inspect the code
in the disassembler and get full control of what's going on, and (2) compilers
now are really smart (think msvc11 and gcc 4.6), so it just rarely make sense
to sacrifice 10x speed for 3x increase in code brevity.

Of course, sometimes you have to dive even deeper, into asm or SSE intrinsics
or OpenCL.

~~~
lelele
What about using an higher level language for game logic, and optimizing
critical section of code with C/C++?

------
boneheadmed
Nice write up. I wrote my own 2d game engine in C++ a while back. Switching to
Ruby was great, but I never made any games. I did make a couple of JavaScript
HTML 5 games. But here again speed is a limitation, and so am looking into C
(and eventually Objective C) to eventually do some iPhone game making. As
great as it would be to make games soley with scripting/interpreted languages,
I don't think we're there yet.

~~~
chrismdp
Easy porting to iPhone in the future is another big plus I should have
mentioned in the original post.

~~~
tptacek
The ObjC object model is very similar to Ruby's object model.

ObjC's way of handling mundane data structures (strings, arrays, hashes) is
(once you learn to stop worrying and love long sequences of calls to very long
method names) very similar to how Ruby addresses the same problems.

ObjC lets you drop into vanilla C code when you want to.

ObjC doesn't impose GC.

ObjC implements a form of duck typing.

You might be surprised at how good a fit ObjC is for a game engine you
prototyped in Ruby, as opposed to C++.

~~~
fleitz
ObjC++ might be an even better fit

~~~
tptacek
I always got a "stay on the golden path and away from ObjC++" vibe from
ObjC++, kind of like trying to ask Rails to do database stuff without using
ActiveRecord in 2008.

You can easily write C++ code without having to bridge ObjC's object system to
C++'s object-and-generics system: provide a simple C API to your C++
libraries.

But the other thing is, one reason to do ObjC at all is to avoid all the
heartache that comes bundled with C++.

 _PS: You got modded down. Baffling. Fixed._

~~~
cageface
Obj-C++ is working well for me so far and the STL is much better than Obj-C's
awkward and slow collection classes for anything that needs to run fast or
that requires significant algorithmic complexity.

~~~
tptacek
One of the nice things about going back from Ruby to a C language is, it's
hard to think of anything you could do in the C language that would be as non-
performant as Ruby. As slow as ObjC's collections are, they're faster than
Ruby's.

~~~
cageface
Yeah, and they're fast enough for a lot of things, but I'm doing DSP at
44.1k/sec and even C++ virtual functions are too slow for that. But I can use
an STL vector at no penalty over a native array.

------
gravitronic
I'm using SDL for writing a DJ application and have it cross-building on
Linux, Windows, and the target platform (HP TouchPad).

For the Windows build I'm using the excellent <http://www.mingw.org/> Mingw32
environment. I compiled SDL and my other needed libraries myself and there's
pretty much no code differences.

The only downside to mingw32 is that my target platform has full POSIX and
mingw32 doesn't, so sometimes I have to choose carefully to use stdlib
functions and not a POSIX function.

~~~
andrewflnr
Just out of curiosity: why is compiling on Windows important if your target is
POSIX? Is it just for development convenience?

~~~
gravitronic
Yes. For other reasons I am generally running Windows.

------
justinhj
A good takeaway from this is make your tests performance related. Since the op
is using unitests already, a test that updated the game loop for a few
minutes, rendering the target number of objects and failed if a frame dropped,
would have saved a lot of wasted development.

------
levifig
This sounds very "link bait-ish"…

Why were you trying to write a game in Ruby to start with? You didn't "switch
back to C++", you simply realized you were trying to use a wrench to tight a
philips screw…

-.-

~~~
chrismdp
I suppose it does: but it's the honest truth. I have two months of ruby code
that's rusting now, and it was quite a difficult post to write.

~~~
levifig
That was not the point of my comment. It was a realization of how it came
across (aka how I got here).

My main point, however, and this in reply to your post (that I have no doubt
it was honest and on the back of some tough thinking) was that you simply
started using the wrong tool for the job and then, realizing this, found a
more appropriate tool. Nothing wrong with that, but your post came across as
"Ruby sucks so I'm going with C++".

Having said that, I'm glad you "saw the light" and I do wish you the best of
lucks in your development endeavors! :)

And remember: your next endeavor might be in Ruby, C++, whatever… Just do some
thinking beforehand and choose the right tool for the job to avoid "rotting
code", which we all know is incredibly frustrating! ;)

~~~
chrismdp
That's a shame: I didn't mean to come across like that. I love Ruby: it's far
and away my favourite language. Anyone reading the rest of my blog can see
that very quickly.

And I'm not sure Ruby will be the wrong tool forever: there just isn't a way
through some of the environment and implementation issues (yet).

------
lallysingh
What I don't get is why you're writing it from scratch? There are over a
_dozen_ high-quality C++ game engines you can use.

A quick list: [http://nuverian.net/2011/01/17/the-best-game-engines-for-
ind...](http://nuverian.net/2011/01/17/the-best-game-engines-for-indie-game-
developers/)

As for what's "good performance," ask yourself: what's the clock speed of your
CPU, and how much work are you really trying to do? Say you've got a 2 GHz
CPU. A 300 FPS rate, is 2,000,000,000 Hz/300 Hz = 6.6 million clock ticks per
frame, on a single core. A modern CPU can be really good about using those
ticks very well. You can do some dumb blitting to figure out the I/O overhead
for getting to the screen.

------
chrismdp
I'd be interested in HNers' views on whether I made the right call.

~~~
cheald
Speaking as a huge fan of Ruby, I think it's absolutely the wrong language to
write games in, because games are enormously sensitive to runtime
fluctuations, and as you found out, Ruby has them. In particular, a stop-the-
world GC is just never going to give you satisfactory performance, unless
every GC pass happens in <1ms and never happens more than once per frame.

That said, you might consider Lua as a primary scripting engine for your game.
It's got a lot of your standard scripting language perks, but it's also
obnoxiously fast and has an incremental garbage collector. Furthermore,
there's no GIL, and it's designed to be embeddable, making it a very powerful
choice for game development.

~~~
chrismdp
I'll look into LUA. Never used it back in my games dev days as it was just
coming into vogue.

~~~
cheald
Just because the Lua community will ream you out for the mistake (though it's
the only thing they're mean about), it's "Lua" (Portuguese for "moon"), not an
acronym. :)

~~~
chrismdp
The joys of iPhone autocorrect :) thanks.

------
mjbellantoni
I don't why this needs to be an either/or proposition. Write your program in
Ruby. Where it needs speed, write the pertinent bits in C++.

I've done this before with Ruby and C. Two great tastes that go great
together!

~~~
chrismdp
I looked at this, but the stop the world GC would still kill the frame rate
from time to time sadly. Also there's a large amount of inefficiency in the
object translation layer between the two languages.

~~~
mjbellantoni
I can believe that, but wonder if it needs to be so.

For example, in my (limited) experience, you have to draw the boundary between
what's in Ruby and what's in C/C++ intelligently. If you're still doing most
of your computation in C on Ruby Arrays and Hashes, you're not going to get
much of a performance win at all.

------
chrismdp
UPDATE: In case anyone is interested, I've just added a screenshot to the blog
post by (very) popular demand. It's not final artwork, and it's only a few
days work!

[http://chrismdp.github.com/2012/01/why-i-switched-from-
ruby-...](http://chrismdp.github.com/2012/01/why-i-switched-from-ruby-back-to-
c-plus-plus/)

------
benburkert
I wonder if he gave Rubinius a go before switching to C++. IANAGD, but i'm
guessing some of it's features would benefit game engines: Tunable GC,
profiling (<http://rubini.us/doc/en/tools/profiler/>), JIT/LLVM. It wouldn't
solve the C extension problem (maybe FFI does?) or distribution though.

~~~
chrismdp
No, I didn't. I love the features Rubinius gives you, but Windows support
still needs a lot of work, and if I'd dived in to help, I'll never ship the
game.

------
subwindow
I wonder if switching to JRuby wouldn't have solved some of his problems? I'd
imagine that distribution is much easier on JRuby. I suppose the issue is with
libraries, but I'm not familiar with the libraries he mentioned.

~~~
chrismdp
Possibly, but I'm much more comfortable in C++ than Java. I also get a much
easier route to iOS if I stick with C++.

~~~
prophetjohn
With JRuby, you wouldn't have to be comfortable with Java. You get to use Ruby
with the benefit of it running in the JVM.

------
jt2190
Hi Chris,

Very nice post! I love seeing these kind of comparisons.

I had the same thought as Havoc's comment (not here, on your site): Why not
use both languages?

~~~
chrismdp
Thanks! I may still do that, if I makes sense to do so and I can distribute it
easily enough.

------
epynonymous
it's simple, ruby is about scale out, not scale up. and rails helps you to
build websites faster. multi-player games would probably be very fast to write
compared to c++, however, the code will certainly not be optimized as well as
c++, it's an interpreted language for gadsakes!

------
phzbOx
tl&dr: switch for performance but miss _Ruby_

~~~
frankPants
_cough_ ObjectiveC

------
rjurney
The author seems to be more interested in obsessive technical improvements
than shipping a game many people want to play. One slow frame out of sixty
prompts a rewrite? Product doomed. Wait until someone complains to fix
anything. Something tells me that frame should not be priority one, but it is.
Why?

~~~
apenwarr
You are completely right for things that don't involve real-time video (like
games do).

A 1/60 frame skip rate sounds like nothing important, but your eye will see it
easily and it's instantly annoying. It's not subtle at all, and not something
you can write off. Everyone will be annoyed by it and _then_ your product will
be doomed.

(Edit) I do however agree that the frame _rate_ is not that important. 30 fps
ought to be enough for anyone. However, it has to be a _really really smooth_
30 fps; all the frames need to come out exactly 1/30 of a second apart. Not
realizing this is where a lot of people go wrong. A smooth 30 fps looks much
better than 120 fps to a human eye. A game framerate that isn't an integer
divisor of your monitor's refresh rate is also a disaster (since it means the
display will be skipping frames).

~~~
rjurney
Would you rather have:

A complete game that people love, and is growing like mad, except for that
damned skip at 60fps...

or

A very smooth 60fps game nobody plays.

~~~
cheald
If it's the difference between shipping and not shipping, ship, of course. But
you propose a false dichotomy; the OP can both ship C++ code and avoid frame
skipping.

Speaking as an avid gamer, that dropped frame matters, a lot. It's incredibly
annoying to the gamer, and will produce an attitude of general discontent with
the product that will earn it reviews like "sluggish", "slow", "unoptimized",
and "chunky", none of which are exactly going to help you sell copies.

You might have missed the part where the author was saying that he wasn't even
nearly done with feature implementation; the problem was only going to get
worse as he added more garbage overhead. When you're talking about relatively
expensive GC passes in a stop-the-world garbage collector, that dropped frame
can turn into 150 dropped frames every 30 seconds pretty quickly (ie, a
2.5-second freeze/hitch), and that's enough to turn any player batty.

