Skip to content

Instantly share code, notes, and snippets.

@tiagopog
Last active August 29, 2015 14:23
Show Gist options
  • Save tiagopog/fa5d82912be9aea2ff27 to your computer and use it in GitHub Desktop.
Save tiagopog/fa5d82912be9aea2ff27 to your computer and use it in GitHub Desktop.
Some concurrency samples in Ruby.
require "./lib/mailer"
require "benchmark"
require "celluloid"
class MailWorker
include Celluloid
def send_email(id)
Mailer.deliver do
from "eki_#{id}@eqbalq.com"
to "jill_#{id}@example.com"
subject "Threading and Forking (#{id})"
body "Some content"
end
end
end
mailer_pool = MailWorker.pool(size: 10)
10_000.times do |i|
mailer_pool.async.send_email(i)
end
require 'benchmark'
class Mailer
def self.deliver(&block)
mail = MailBuilder.new(&block).mail
mail.send_mail
end
Mail = Struct.new(:from, :to, :subject, :body) do
def send_mail
fib(30)
puts "Email from: #{from}"
puts "Email to : #{to}"
puts "Subject : #{subject}"
puts "Body : #{body}"
end
def fib(n)
n < 2 ? n : fib(n-1) + fib(n-2)
end
end
class MailBuilder
def initialize(&block)
@mail = Mail.new
instance_eval(&block)
end
attr_reader :mail
%w(from to subject body).each do |m|
define_method(m) do |val|
@mail.send("#{m}=", val)
end
end
end
end
# Sequential:
# puts Benchmark.measure {
# 100.times do |i|
# Mailer.deliver do
# from "[email protected]"
# to "[email protected]"
# subject "Threading and Forking"
# body "Some content"
# end
# end
# } #=> It takes about 13s to get done.
# Multiprocesses:
# puts Benchmark.measure {
# 100.times do |i|
# fork do
# Mailer.deliver do
# from "[email protected]"
# to "[email protected]"
# subject "Threading and Forking"
# body "Some content"
# end
# end
# end
# Process.waitall
# } #=> It takes about 6s to get done.
# Multithreading:
threads = []
puts Benchmark.measure{
100.times do |i|
threads << Thread.new do
Mailer.deliver do
from "eki_#{i}@eqbalq.com"
to "jill_#{i}@example.com"
subject "Threading and Forking (#{i})"
body "Some content"
end
end
end
threads.map(&:join)
} #=> It takes about 6s to get done.
POOL_SIZE = 10
jobs = Queue.new
10_0000.times{|i| jobs.push i}
workers = (POOL_SIZE).times.map do
Thread.new do
begin
while x = jobs.pop(true)
Mailer.deliver do
from "eki_#{x}@eqbalq.com"
to "jill_#{x}@example.com"
subject "Threading and Forking (#{x})"
body "Some content"
end
end
rescue ThreadError
end
end
end
workers.map(&:join)
require_relative "../lib/mailer"
require "sidekiq"
class MailWorker
include Sidekiq::Worker
def perform(id)
Mailer.deliver do
from "eki_#{id}@eqbalq.com"
to "jill_#{id}@example.com"
subject "Threading and Forking (#{id})"
body "Some content"
end
end
end
# sidekiq -r ./mail_worker.rb
# $ irb
# >> require_relative "mail_worker"
# => true
# >> 100.times{|i| MailWorker.perform_async(i)}
# 2014-12-20T02:42:30Z 46549 TID-ouh10w8gw INFO: Sidekiq client with redis options {}
# => 100
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment