Hacker News new | past | comments | ask | show | jobs | submit login
Why I switched from Ruby back to C++ (chrismdp.github.com)
143 points by chrismdp on Jan 8, 2012 | hide | past | favorite | 94 comments



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.


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.


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.


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.


> 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.


> 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++

Show them some numbers

http://shootout.alioth.debian.org/u32/which-programming-lang...


It's not because it would not be wise to write a Gran Turismo 7 in an interpreted language such as ruby or python that writing any game with such language wouldn't work. Not all games have such specific requirements as Gran Turismo 7 where huge teams want to extract the most power out of some very specific piece of hardware.

Nowadays it gets easier and easier to use interpreted language as the hardware gets more and more things delegated. For some games, it may be better to do everything in C/C++, some others C/C++ with some interpreted language on top for some parts, and some others whatever language you prefer.

Given higher level language usually help you write code faster, I would definitely give up some performance (which is not really visible usually) in exchange for some efficiency. Even for some 3d game. But then again, not everyone is writing the next Gran Turismo :)

Although I can't speak of ruby or its vm since I never used it, but have used python + OpenGL or pygame quite a few times.

In his case not only performance suffered too much from ruby but writing code in ruby didn't make him more efficient. So ruby didn't bring enough value.


As an example, Toontown is a full game written in Python, with a C++ game engine (Panda3D) and runs without performance issues at all in a single core 1.6GHz CPU.


I'm a full-time ruby developer (have been for 6 years). I do web development exclusively and all the experience I have with C and C++ came in college. In other words, I'm pretty ignorant when it comes to game development.

What you're saying here is extremely disturbing to me. For one inexperienced developer to make a wild unsupportable claim like Ruby can do anything C++ can do performance-wise is an act of hubris. For a whole roomful of such devs to nod in agreement is a little microcosm of willful ignorance that must have been terrifying to behold. If this is typical of your experience with Ruby devs I will suggest that your moving in C-player circles and you should expand your travels. We are not all that ignorant.


These sound like designers turned quasi-developers rather than serious programmers. I don't know anyone that actually understands real software development that would make this claim.


First, those are all pretty fantastic claims that need support.

Second, technically speaking of course it can do anything C++ can do. The question is can it do it well, or fast?


Heh :) I'll take the bait :)

I've written lots of Ruby for things that are serious (large websites with lots of traffic), and I've worked as part of a team that built on commercially available games in C++ that sold lots of copies.

Ruby has come along enormously recently, especially with 1.9.3 and the other flavours that are out there now. I thought it might be worth trying it and advancing the state of the possible. Eventually I decided that actually shipping something was more important.


The title of your self-submitted post is misleading. The bait post you're referring to stated the obvious, albeit in highly charged language.

It's one thing to choose the wrong language for a project. But having done that, please don't submit a post that suggests expert knowledge or deep experience in Ruby.

For what it's worth, I use both Ruby and C++. I would probably have gone with Qt if I wanted to build such a game. It would never have crossed my mind to write it in Ruby, and I don't consider myself an expert in Ruby.


Reasonable comments - thanks for the HN feedback. It's not for me to say if I'm an expert in Ruby or not, but I don't think attempting something to push some boundaries is mutually incompatible with experience or knowledge. If I'd succeeded, it would have been awesome for Ruby (far and away my favourite language).


This post is mean, and has no place on Hacker News. It's fine to say there's no reason to ever use Ruby for a game, but it seems like the main purpose of your post is just to call into question the OP's intelligence and experience.


I thought he was just calling into question the link-baity title.

The title is designed to be controversial as people don't like their favourite programming language to be slandered, thus they will be obliged to read the article so that they can defend their baby.

Using link bait as a title is contrary to HN guidelines, so if anything, it is the article that does not belong on HN, not the grandparent comment.


Fair enough: perhaps I should have been more specific about the context and thought of a better title.


Don't sweat it. I was more annoyed at the parents attack on the grandparent than your title. You got a discussion going, so well done :-)


Agreed. This is pure link bait.


Sure.

He coded his game in one language and then SWITCHED in mid-development to another, with all the delay and hassles that that brings, in order to get links...


It is mean. That's nothing wrong with trying new thing even if most people are saying it's the wrong choice. And there's no shame in failing in the process. People will say, I told you so. But you never know until you have tried it, and you would learn a lot in the process. And sometime you might just have a break-thru.


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...)


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

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


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


Not necessarily in Ruby, it may be Scheme or some proprietary in-house scripting language.


"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.


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.


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


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.


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


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++.


ObjC++ might be an even better fit


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.


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.


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.


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.


It is just a shame that in some areas Objective-C is still lacking compared with more modern languages:

- a proper module system; - reliance on the primitive #import/#include which slows down compilation - no namespacing, relying instead on conventions to avoid clashes


what about lua/love/corona?


I've thought of using Lua and if I recall correctly, work has been done to develop iPhone games with Lua as well? Ah, where is the time?


yeah corona sdk (which is not free, but seems to be worth the price of entry from my dabbling) compiles for iphone and android from common lua codebase. The api docs are easy to read, tons of examples and plugins (box2d etc.). I threw together an ipad app for my "boiling water" game I've been joking about for years with corona in about an hour having only ever looked at lua from afar. If you grok js/ruby/python than lua will be simple.


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.


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


Yes. For other reasons I am generally running Windows.


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.


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…

-.-


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.


Ruby was simply the wrong language for games. There's a reason a huge percentage of real-world games use Lua for scripting.

Floats for one aren't objects, and LuaJIT is probably 10x faster than Ruby.


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! ;)


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).


A more honest title would by "Why C++ is better than Ruby for game development".


Fair enough: thanks.


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...

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.


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


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.


Usually the way you solve GC issues is by either not allocating after some initial massive allocation, or by running the GC constantly and having it clean up bits and peices every frame. I don't know enough about ruby to know if this is possible but this is how you handle GC in Java and C#.

As for Lua, Garry's mod runs almost entirely in Lua (outside of the source engine).


You can run GC manually in Ruby, but at the end of the day, it's a stop-the-world GC; your program doesn't get to do anything until it decides that it's finished. If that takes too long, you drop that frame. Additionally, Ruby doesn't have the concept of primitives (mostly), and all objects are stored on the heap! So, every time you use a float (which you do a lot of in games), you end up with a new struct on the heap that has to be garbage collected eventually. Ouch.

(By way of demonstration:)

    ree-1.8.7-2011.03 :002 > 123.456.object_id
     => 33681660
    ree-1.8.7-2011.03 :003 > 123.456.object_id
     => 33674740
Languages with incremental GCs will yield between phases of the GC pass, letting program execution continue even when a GC pass is in progress, making sure that you don't end up with dropped frames, which vastly improves the player experience.


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


Mike Pall's LuaJIT[0] is excellent from a game dev perspective--incremental GC (so you can spend a fixed amount of your frame budget in it) and JIT with a huge number of optimisation make it fairly compelling to write the top 50% of your game in (and not a terrible choice for the bottom 50%).

I think you were absolutely right to switch from Ruby, I can't see the problems that you had getting any better unless Ruby lets you manage object allocation (in which case you could allocate to a per-frame memory buffer and just nuke it at the end of every frame).

[0] http://luajit.org/


The cause of its popularity in the games community comes from the fact that it is, by design, meant to be embedded in larger programs. So, for example, it will compile on any platform with a conforming ANSI C compiler.

And for x86/x64 and ARM, you can try LuaJIT to get even more zing (though you probably won't need to).


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. :)


The joys of iPhone autocorrect :) thanks.


I think it's absolutely the wrong language to write games in, because games are enormously sensitive to runtime fluctuations

No-one is nailing down the definition of "game" in this entire discussion. For a FPS or game filled with live special effects, sure. For a chess game, a puzzler, or even a graphic adventure? Ruby's GC wouldn't be a problem at all (although Ruby has other issues that could well crop up).


Seems to me that no matter what the language du jour may be, games are still often written in c++. When you're not getting the performance out of the tools you're using and you've spent some time trying to work around the problems, I think it's the right call to switch tools.


Thanks: after three days I think it was the right call. I just found myself burning too much brain energy on things I didn't want to have to care about.


You might want to explore Lua as an alternative. Lots of games are written in Lua/C/C++ combo. Low level primitive routines in C/C++ and high level game stuff in Lua.


One advantage of using C/C++ is that (performance allowing) it's going to be relatively easy to port to Android's NDK or iOS.


Writing everything in C++ is not my idea of fun. It's definitely possible to write almost all of the game code in a scripting language. It would be reasonably easy to abstract all the native APIs you want, but you could also just let someone else do it: http://love2d.org/


Of course you did, and I say that as a self-described Ruby programmer. What I really want to know is what gave you the idea that it might be a good idea to use Ruby for a project so obviously not suitable for Ruby?


Just out of interest, why did you choose not to use Gosu in your C++ port?


I hope it was because of this: http://gosu-lang.org/comparison.shtml


Wrong Gosu.

He said he used www.libgosu.org for Ruby but the library also works with C++, so I'm wondering why he's switched to www.libsdl.org


Yeah, thought about it (Gosu was great for getting started), but decided I wanted to get back to fundamentals and switch to a slightly lower level framework to aid my understanding of what's really going on under the hood.


ruby excels where time to market and RAD are more important than performance, and where the standard and other libraries work well. Ruby saves lots of time doing things like CRUD operations where you're basically mapping on set of fields to another in a predictable way. When performance and memory are an issue and you can't trivially scale your code (eg. More processes or more machines) C++ is a big win.


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!


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.


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.


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-...


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.


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.


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.


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++.


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.


Sounds like he's wanting to use a lot of native C++ libraries, so I imagine he'd still run into performance problems even if he found a way to use JNI with JRuby.


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?


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


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!


tl&dr: switch for performance but miss Ruby


cough ObjectiveC


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?


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).


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.


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.


It seems a pretty sensible decision to switch to a more suitable technology when you're only a couple of days into a project.


A complete game that people love, and is growing like mad that is very smooth at 60fps.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: