The dark arts of concurrent programming.
A DSL that adds parallel programming constructs to make your life a little easier.
- Install it
gem install eldritch
- Require it
require 'eldritch'
- Use it (see features below)
By default eldritch will inject the DSL into the global scope. If you don't want
this, you can require eldritch/safe
instead of eldritch
.
require 'eldricth/safe'
class MyClass
include Eldritch::DSL
extend Eldritch::DSL
# The DSL is available in this class
end
bundler install
bundler exec rake
ruby -I lib examples/{your favorite example}.rb
bundle exec rake doc
Async methods run concurrently when called. The caller is returned control right away and the method runs in the background.
require 'eldritch'
# define an async method
async def send_email(email)
# ...
end
send_email(some_email) # runs in the background
For all versions of ruby before 2.1.0, you need to define async methods like so:
def foo
# stuff
end
async :foo
Since ruby 2.1.0, def returns the name of the method defined as a symbol. This
allows for the cleaner async def foo
syntax.
Async blocks are run concurrently.
require 'eldritch'
async do
# runs in the background
end
Async blocks and async methods both return tasks. These can be used to interact with the async block/method.
require 'eldritch'
task = async do
# calculate something that will take a long time
end
# we need to result of the task
res = 2 + task.value # waits for the task to finish
Together blocks are used to control all async blocks and methods within them as a group. Before exiting, together blocks wait for all their async calls to be done before returning.
require 'eldritch'
together do
1000.times do
async do
# do some work
end
end
end
# all 1000 tasks are done
These blocks can also take an argument. This argument is a group that can be used to control the async calls in the block. See the documentation for Eldritch::Group for more information.
require 'eldritch'
together do |group|
5.times do
async do
# do something
group.interrupt if some_condition # stops all other tasks
end
end
end
MRI has this nasty little feature called a GIL or Global Interpreter Lock. This lock makes it so that only one thread can run at a time. Let's say that you have 4 cores, running threaded code on MRI will only make use of 1 core. Sometimes, you might not gain a speed boost if you make code parallel. This could the case even if theory says otherwise.
Not all ruby implementations use a GIL. For example, jRuby does not use a GIL.
If your ruby implementation has a GIL, you will probably see a speed boost if your code does a lot of IO or anything that's blocking. In that case running on a single core is not that much of a hindrance, because most of the threads will be blocked and your code should run more often.