Ruby, Concurrency, and You »

Created at: 14.10.2011 19:41, source: Engine Yard Blog, tagged: Open Source Technology 1.8 1.9 concurrency GIL implementations ironruby jruby macruby maglev MRI parallelism rubinius ruby threads

tl;dr
Ruby Implementation Concurrency Parallelism
MRI 1.8
MRI 1.9
Rubinius 1
Rubinius 2
JRuby
MacRuby
Maglev
IronRuby

A big topic in the world of Ruby this year has been how to get more out of Ruby, specifically, how to get more done in parallel. The topic of concurrency, though, is one fraught with misunderstanding. This is largely due to the complexities of not only thinking about multiple things at once, but the limitations of Ruby implementations and operating systems.

In this article, I’ll lay the groundwork for understanding the difference between concurrency and parallelism. Then, I’ll look at how a programmer experiences them.

Concurrency vs. Parallelism

This has been discussed many times, but I sometimes still have difficulty with it. Let’s first break down the definitions of these two words:

  • Concurrent: existing, happening, or done at the same time
  • Parallel: occurring or existing at the same time or in a simple way

Hmm, ok. Well, that hasn’t improved our thinking about these two topics. We need to dig deeper into how the world of computing applies to these words. Rather than looking at the abstract, let’s instead consider some real world examples.

A “Real World” Example

Let’s say you’ve sat down for the evening to complete tomorrow’s homework. This evening you’ve got both Math and History worksheets to fill out. Tonight for some reason, you decide to do one problem in Math, then one problem in History, then back to Math, etc until all the problems are done.

In the parlance of computing, you’re now doing your Math and History worksheets concurrently. This is because your Current task list includes 2 items: Math worksheet and History worksheet.

Now, clearly you the reader can see a problem here. By switching back and forth, completing your homework will probably take longer than if you did the complete Math worksheet then did the History worksheet. In other words, if you did the worksheets in serial.

So, if concurrent means “having multiple outstanding tasks at once”, then what is parallel? Parallel is the ability to make progress on multiple tasks simultaneously.

Let’s say you’ve been asked to read the book One O’Clock Jump by Lise McClendon. You also need to drive down to San Diego for Comic-Con. Thankfully you find that One O’Clock Jump is available on audiobook!

You can now listen to the book while driving. You’re simultaneously making progress on two separate tasks. This is the equivalent of parallelism in computing.

I hope that these real world examples help illustrate the difference between concurrency and parallelism. Now let's apply this newfound knowledge to Ruby.

Back to Ruby

One reason this problem can be difficult to understand is because Ruby only provides a single mechanism for concurrency. But, whether or not these Threads are parallel depends on a number of factors.

MRI 1.8

Let’s look at MRI 1.8 (and MRI forks such as REE) to begin with, because it has the simplest model. MRI 1.8 uses a technique known as “green threads” to implement Threads. This means that every once in a while (around 100 milliseconds), the program says “oh, I should let another thread run now!” This saves the current info into the current thread and restores another thread. This is exactly like our homework example above. We can have as many things as we’d like in our task list, but we can only make progress on one of them at a time.

There is a wrinkle in the concurrency/parallelism game that I haven’t mentioned before now. This wrinkle is IO, namely how Threads interact when waiting for some external event. MRI 1.8.7 is quite smart, and knows that when a Thread is waiting for some external event (such as a browser to send an HTTP request), the Thread can be put to sleep and be woken up when data is detected. This simple consolation improves the usage of Threads so much that for a very long time the MRI 1.8.7 model was good enough for all Ruby programs.

MRI 1.9

Switching back to Ruby implementations, let’s look at MRI 1.9. As has been previously reported, MRI 1.9 removes the “green threads” we had in MRI 1.8 and uses native threads to implement the Thread class. Now, what are these “native threads”? These are are units of concurrency that the underlying operating system is aware of. A big reason to switch to use native threads is that it vastly simplifies the implementation of Threading. The operating system handles the low level parts of saving and restoring Thread information in a completely transparent way. Additionally, letting the OS know what parts of a program should be concurrent allows it to use the full resources of the computer to make that happen. In this modern world, that means using multiple cores.

Up until now, all we’ve talked about with Ruby’s Threading model was about concurrency, the ability to have multiple outstanding tasks at once. Now when we add in the idea of multiple cores, we can finally talk about parallelism. When a computer includes multiple cores (which is pretty much every computer now), those cores can run different code simultaneously, providing true parallelism. When a computer only has one core, there is no true parallelism, instead there is just simple concurrency, even at the OS level. The OS manages all the processes and threads in the system the same way you handled your Math and History worksheets, doing one for a little while, then grabbing another one.

Back to multiple cores though. Now that there is the opportunity to run things truly in parallel, we have to look at if Ruby can take advantage of that. Since MRI 1.9 uses OS threads, it can actually spread out your Ruby Threads to multiple cores!

Unfortunately, MRI 1.9 prevents the Ruby code itself from running in parallel by requiring that any thread running Ruby code hold a lock. This lock is commonly knows as the GIL (Global Interpreter Lock) or GVL (Global VM Lock).

There are a few reasons the GIL to exists, but for this discussion we will say that it’s because the non-Ruby parts of MRI 1.9 are not thread-safe. This means if data were manipulated by multiple threads at the same time, the data could become corrupt. The important thing for this post is how it applies to parallelism: the GIL inhibits parallelism within Ruby code.

MRI 1.9 uses the same technique as MRI 1.8 to improve the situation, namely the GIL is released if a Thread is waiting on an external event (normally IO) which improves responsiveness. MRI 1.9 also includes an experimental API that C extensions can use to run some C code without the GIL locked to utilize parallelism. This API is very restrictive though because no Ruby object may be accessed in any way while the GIL is not held by the current thread.

That about sums up the situation with MRI 1.8 and 1.9 with regards to concurrency and parallelism. Both provide concurrency of Ruby code, but neither provide parallelism of Ruby code.

Rubinius

Let’s take a quick look at other Ruby implementations where things are a bit different than MRI. I’ll start with Rubinius, since it’s the one I’m most familiar with. Rubinius 1.x also had a GIL and worked pretty much the same as MRI 1.9. With the upcoming 2.0 release though, the GIL will be removed, allowing Ruby code to run fully concurrent and fully parallel. We think this opens up a lot of uses for Ruby (parallel algorithms, etc) that Rubinius couldn’t handle well previously.

JRuby

JRuby layers the Thread class on top of Java’s thread class, so the threading model is whatever the JVM supports. That being said, OpenJDK is the primary JVM; it puts a Java thread directly onto an OS thread with no GIL. Thusly, JRuby almost always has full concurrency and parallelism available to it.

MacRuby

MacRuby also uses Cocoa’s NSThread as its abstraction, which runs without a GIL. So, this is another fully parallel implementation.

Maglev

Maglev runs directly on top of a Smalltalk VM and thusly layers the Thread class on top of a concept called Smalltalk Processes. In this case, the GemStone VM implements Processes in the same way as MRI 1.8, namely via “green threads” that don’t expose concurrency to the OS, and therefore, have no parallelism.

IronRuby

Lastly, IronRuby layers Thread directly on top of CLR’s threads without a GIL.

Conclusion

I hope that this helps to clear up what concurrency and parallelism are and how the different Ruby implementations address them. Having this understanding is critical for discussing and understanding topics such and thread-safety of libraries and performance of applications.

In future posts, we’ll look to build on this knowledge to help you make the best use of Ruby!


more »

Video Available: Rubinius and Ruby – A Love Story »

Created at: 01.09.2011 01:57, source: Engine Yard Blog, tagged: Open Source rubinius

Earlier this month Evan Phoenix, Brian Ford and I (Shane Becker) conducted a web-based presentation called Rubinius and Ruby: A Love Story. The event recording is now available to watch.

Rubinius and Ruby: A Love Story Webinar from Engine Yard on Vimeo.

We fielded questions during the presentation, so if you're interested in the Q&A, jump to timecode 27:30 in the video. If you have any other Rubinius related questions, feel free to direct them to @Rubinius on Twitter, or email them to community@rubini.us.

NOTE: Don't miss the upcoming JRuby webinar led by Nick Sieger on September 15. Register now to save a spot. Topics you want to learn about in the webinar? Direct them to @JRuby on Twitter.


more »

Ruby MRI, JRuby and Rubinius Throwdown Brodown »

Created at: 01.07.2011 01:34, source: Engine Yard Blog, tagged: community events Open Source jruby rubinius Ruby MRI Webinar

At RailsConf I had just given a thorough, yet humorous, overview of why everyone should run their production Ruby web applications on JRuby or Rubinius. I introduce into evidence exhibit A, the video replay of my 15 minute keynote. My beloved friend Aaron “Tenderlove” Patterson then stood up to give his own keynote and publicly rejected all my good advice with, "Ignore what Dr Nic said, [don’t use Rubinius or JRuby]. I’m on the MRI core team, so I think you should use that instead.” (paraphrased) Oh really, Aaron. This calls for a Ruby Platforms Virtual Brodown. I invite you all to join us for the webinar event. We’ve lined up a great panel of folks. Each awesome panelist will represent a different implementation: Ruby MRI, JRuby or Rubinius.

Ruby Platforms Virtual Brodown

Who: Aaron Patterson (Ruby MRI), Nick Sieger (JRuby), Brian Ford (Rubinius) and yours truly When: Thursday, July 21, 2011 from 10:00 to 10:50 AM Pacific Where: Online (WebEx) “Why should I attend? This sounds like it could get ugly...” some of you may be contemplating. Rightfully so. We know you have other options. Your 50 minutes could, very well, be better allocated to earning DJ points on turntable.fm, replying to heaps of email, or pondering summer getaways whilst billing hours. However, if you decide to join us, we’ll vow to leave you with a solid understanding of Ruby MRI, JRuby and Rubinius. More specifically, we will cover:
  • The Ecosystem: What works where, integrations and other capabilities to know about
  • Tooling: Profiling, debugging, monitoring, VPN introspection
  • Concurrency: Threading models and doing two things simultaneously
  • Windows: Life on planet Windows
  • Deployment: Sample stacks and how to run in production
We hope this laundry list of takeaways is enough to convince you to register to attend, or at least register to watch the recorded version we’ll email you post-event. Hope you can make it.


more »

Get your Rubinius T-Shirts and Stickers at RailsConf »

Created at: 12.05.2011 04:02, source: Engine Yard Blog, tagged: community Open Source rubinius swag

Hey kids, Rubinius is going to Baltimore! We've got a lot of rad stuff planned for next week, but wait -- there's more. Rubinius "Use Ruby™" TShirts at the Farmhouse in Hollywood, CA Photo by Tj Nelson Jr @tjnelsonjr It’s been a long time coming, but we’ve finally made some t-shirts and stickers for you to show your love and support of your Rubinius. Two different shirts and four different stickers, to be exact. “How do I get my grubby paws on one of those them there shirts?” That’s great question (if not a weird way to ask it). The answer is simple — go to the Engine Yard booth at RailsConf next week in Baltimore. We’ll have 500 shirts on hand and a giant pile of stickers. Both are free. You don’t have to sing for your supper. All you do is show up. “But I won’t be at RailsConf. How do I get one?” Don’t worry. We’ve got you covered. This first batch is all for RailsConf, but right afterward we’ll have lots more of this kind of stuff available. We’ll have a way for you to order them from us. Rubinius logo diecut sticker Stroll on over to the Rubinius blog to read all about it. See you in Baltimore (or not). If you will be in B'more, hit up Brian Ford (@brixen) to talk shop during Rubinius Office Hours. — Use Ruby™ PS. This is just the tip of the iceberg of what all we have planned. Stay tuned.


more »

Rubinius on AppCloud »

Created at: 22.03.2011 20:06, source: Engine Yard Blog, tagged: Product appcloud Engine Yard Beta Program rubinius

I'm extremely proud to announce that Rubinius on Engine Yard AppCloud is now available in Alpha. This has been the culmination of years of work by countless people inside and outside of Engine Yard. Way back in 2007, when I first started at Engine Yard we began talking about this day. A lot has changed in the intervening years with both Engine Yard and Rubinius but nothing has changed the focus on building Rubinius as a first class Ruby environment that is easy to use. Engine Yard has seen significant movement into the cloud/platform services realm and Rubinius has meanwhile begun to push the boundaries of Ruby performance. We've been building software and services to get us to this exact point in time and I couldn't be more excited. Rubinius now has all kinds of tools for making a developer's life easier, from builtin profilers to external monitoring.

Enabling Access to Rubinius on AppCloud

Now for the nitty gritty. We're going to be making Rubinius available in Alpha (as a part of our Beta Program). This means it will only be available to users that specifically request it. To request to have Rubinius available as one of your Rubies, fill in this form for each AppCloud account email. We'll flip a bit in your account and you'll have Rubinius as an option when configuring your instances.

Support for Rubinius on AppCloud

As a trial program, we want Alpha users to report issues back to us as quickly as possible. This will help us get them fixed and help smooth out the rough edges before Rubinius is moved into Beta, and then finally made available to all our users. Please initiate Support requests and feedback via the EY Beta discussion group.

Thank You

On a final personal note, I'd like to thank all the people who have contributed to Rubinius over the past many years. Your help, no matter the size, has helped us get to this point. I can't wait to see where users take Rubinius on AppCloud!


more »