Showing posts with label Thread. Show all posts
Showing posts with label Thread. Show all posts

Friday, October 28, 2011

A Modern Guide to Threads

Every time you execute ruby, rails or irb, you are creating a process. Within each process, you have something which is executing the code in your process. This is called a thread.

Your operating system starts every process with a “main” thread. Ruby allows you to create as many additional threads as you want by calling Thread.new with a block of code to be executed. Once the block of code has finished executing, the thread is considered dead. If the main thread exits, the process dies.

Saturday, March 19, 2011

Does ruby have real multithreading?

Ruby 1.8 only has green threads, there is no way to create a real "OS-level" thread. But, ruby 1.9 will have a new feature called fibers, which will allow you to create actual OS-level threads.
Another alternative is to use JRuby. JRuby implements threads as OS-level theads, there are no "green threads" in it.
There are currently around 11 different implementations of the Ruby Programming Language, with very different and unique threading models.
(Unfortunately, only two of those 11 implementations are actually ready for production use, but by the end of the year that number will probably go up to four or five.)
  1. The first implementation doesn't actually have a name, which makes it quite awkward to refer to it and is really annoying and confusing. It is most often referred to as "Ruby", which is even more annoying and confusing than having no name, because it leads to endless confusion between the features of the Ruby Programming Language and a particular Ruby Implementation.
    It is also sometimes called "MRI" (for "Matz's Ruby Implementation"), CRuby or MatzRuby.
    MRI implements Ruby Threads as Green Threads within its interpreter. Unfortunately, it doesn't allow those threads to be scheduled in parallel, they can only run one thread at a time.
    However, any number of C Threads (POSIX Threads etc.) can run in parallel to the Ruby Thread, so external C Libraries, or MRI C Extensions that create threads of their own can still run in parallel.
  2. The second implementation is YARV (short for "Yet Another Ruby VM"). YARV implements Ruby Threads as POSIX or Windows NT Threads, however, it uses a Global Interpreter Lock (GIL) to ensure that only one Ruby Thread can actually be scheduled at any one time.
    Like MRI, C Threads can actually run parallel to Ruby Threads.
    In the future, it is possible, that the GIL might get broken down into more fine-grained locks, thus allowing more and more code to actually run in parallel, but that's so far away, it is not even planned yet.
  3. JRuby implements Ruby Threads as Native Threads, where "Native Threads" in case of the JVM obviously means "JVM Threads". JRuby imposes no additional locking on them. So, whether those threads can actually run in parallel depends on the JVM: some JVMs implement JVM Threads as OS Threads and some as Green Threads.
  4. XRuby also implements Ruby Threads as JVM Threads.
  5. IronRuby implements Ruby Threads as Native Threads, where "Native Threads" in case of the CLR obviously means "CLR Threads". IronRuby imposes no additional locking on them, so, they should run in parallel, as long as your CLR supports that.
  6. Ruby.NET also implements Ruby Threads as CLR Threads.
  7. Rubinius implements Ruby Threads as Green Threads within its Virtual Machine. More precisely: the Rubinius VM exports a very lightweight, very flexible concurrency/parallelism/non-local control-flow construct, called a "Task", and all other concurrency constructs (Threads in this discussion, but also Continuations, Actors and other stuff) are implemented in pure Ruby, using Tasks.
    Rubinius can not (currently) schedule Threads in parallel, however, adding that isn't too much of a problem: Rubinius can already run several VM instances in several POSIX Threads in parallel, within one Rubinius process. Since Threads are actually implemented in Ruby, they can, like any other Ruby object, be serialized and sent to a different VM in a different POSIX Thread. (That's the same model the BEAM Erlang VM uses for SMP concurrency. It is already implemented for Rubinius Actors.)
  8. MacRuby started out as a port of YARV on top of the Objective-C Runtime and CoreFoundation and Cocoa Frameworks. It has now significantly diverged from YARV, but AFAIK it currently still shares the same Threading Model with YARV.
  9. Cardinal is a Ruby Implementation for the Parrot Virtual Machine. It doesn't implement threads yet, however, when it does, it will probably implement them as Parrot Threads.
  10. MagLev is a Ruby Implementation for the GemStone/S Smalltalk VM. I have no information what threading model GemStone/S uses, what threading model MagLev uses or even if threads are even implemented yet (probably not).
  11. HotRuby is not a full Ruby Implementation of its own. It is an implementation of a YARV bytecode VM in JavaScript. HotRuby doesn't support threads (yet?) and when it does, they won't be able to run in parallel, because JavaScript has no support for true parallelism. There is an ActionScript version of HotRuby, however, and ActionScript might actually support parallelism.
Unfortunately, only two of these 11 Ruby Implementations are actually production-ready: MRI and JRuby.
So, if you want true parallel threads, JRuby is currently your only choice – not that that's a bad one: JRuby is actually faster than MRI, and arguably more stable.
Otherwise, the "classical" Ruby solution is to use processes instead of threads for parallelism. The Ruby Core Library contains the Process module with the Process.fork method which makes it dead easy to fork off another Ruby process. Also, the Ruby Standard Library contains the Distributed Ruby (dRuby / dRb) library, which allows Ruby code to be trivially distributed across multiple processes, not only on the same machine but also across the network.
http://stackoverflow.com/questions/56087/does-ruby-have-real-multithreading

Tuesday, January 4, 2011

Getting to Know the Ruby Standard Library – Timeout

Timeout lets you run a block of code, and ensure it takes no longer than a specified amount of time. The most common use case is for operations that rely on a third party, for instance net/http uses it to make sure that your script does not wait forever while trying to connect to a server:
def connect
  ...
  timeout(@open_timeout) { 
    TCPSocket.open(conn_address(), 
    conn_port()) 
  }
  ...

You could also use Timeout to ensure that processing a file uploaded by a user does not take too long. For instance if you allow people to upload files to your server, you might want to limit reject any files that take more than 2 seconds to parse:
require 'csv'

def read_csv(path)
  begin
    timeout(2){ CSV.read(path) }
  rescue Timeout::Error => ex
    puts "File '#{path}' took too long to parse."
    return nil
  end
end

Lets take a look at how it works. Open up the Timeout library, you can use qw timeout if you have Qwandry installed. Peek at the timeout method, it is surprisingly short.
def timeout(sec, klass = nil)   #:yield: +sec+
  return yield(sec) if sec == nil or sec.zero?
  ...

First of all, we can see that if sec is either 0 or nil it just executes the block you passed in, and then returns the result. Next lets look at the part of Timeout that actually does the timing out:
...
x = Thread.current
y = Thread.start {
  sleep sec
  x.raise exception, "execution expired" if x.alive?
}
return yield(sec)
...

We quickly see the secret here is in ruby’s threads. If you’re not familiar with threading, it is more or less one way to make the computer do two things at once. First Timeout stashes the current thread in x. Next it starts up a new thread that will sleep for your timeout period. The sleeping thread is stored in y. While that thread is sleeping, it calls the block passed into timeout. As soon as that block completes, the result is returned. So what about that sleeping thread? When it wakes up it will raise an exception, which explains the how timeout stops code from running forever, but there is one last piece to the puzzle.
...
ensure
  if y and y.alive?
    y.kill
    y.join # make sure y is dead.
  end
end
...
At the end of timeout there is an ensure. If you haven’t come across this yet, it is an interesting feature in ruby. ensure will always be called after a method completes, even if there is an exception. In timeout the ensure kills thread y, the sleeping thread, which means that it won’t raise an exception if the block returns, or throws an exception before the thread wakes up.

It turns out that Timeout is a useful little library, and it contains some interesting examples of threading and ensure blocks.

http://endofline.wordpress.com/2010/12/31/ruby-standard-library-timeout/