0
OMG HELLO!
Friday, November 5, 2010
THANK YOU
Friday, November 5, 2010
Aaron Patterson
Friday, November 5, 2010
AT&T, AT&T logo and all AT&T related marks are trademarks of AT&T Intellectual Property and/or AT&T affiliated companies.
...
@tenderlove
Friday, November 5, 2010
nokogiri
Friday, November 5, 2010
ruby core
committer
Friday, November 5, 2010
YAML
Friday, November 5, 2010
Psych
Friday, November 5, 2010
DL
Friday, November 5, 2010
rails core
committer
Friday, November 5, 2010
rails core
committer
Friday, November 5, 2010
ActiveRecord
Friday, November 5, 2010
ARel
Friday, November 5, 2010
anywhere...
Friday, November 5, 2010
aaron.patterson@gmail.com
Friday, November 5, 2010
Friday, November 5, 2010
WWFMD?
Friday, November 5, 2010
Preparations
the @tenderlove way
Friday, November 5, 2010
What should
I talk about?
Friday, November 5, 2010
Yehuda?
Friday, November 5, 2010
Evan?
Friday, November 5, 2010
DHH?
Friday, November 5, 2010
I will talk
about
Concurrency!
Friday, November 5, 2010
Threads!
Friday, November 5, 2010
Iterators!
Friday, November 5, 2010
Generators!
Friday, November 5, 2010
Fibers!
Friday, November 5, 2010
Coroutines!
Friday, November 5, 2010
Friday, November 5, 2010
the @tenderlove
process for
producing slides
Friday, November 5, 2010
BOOKS ARE IN
STORES NOW!
Friday, November 5, 2010
ONLY $24.99!!!
Friday, November 5, 2010
BUY TODAY!
Friday, November 5, 2010
Fun with Fibers!
Friday, November 5, 2010
Concurrency
Friday, November 5, 2010
WARNING!
Friday, November 5, 2010
fork()
Friday, November 5, 2010
fork()
foo = "hello"
fork do
foo << " world"
puts foo
end
fork do
foo << " everyone!"
puts foo
end
puts foo
Process.wait
F...
Copy on Write
Friday, November 5, 2010
Threads
Friday, November 5, 2010
Why Use Threads?
Friday, November 5, 2010
Friday, November 5, 2010
Thread API
Friday, November 5, 2010
thread = Thread.new {
... do some work ...
}
thread.join
new and join
Friday, November 5, 2010
100.times { Thread.new { ... } }
(Thread.list - [Thread.main]).each { |t|
t.join
}
list / main
Friday, November 5, 2010
Return Value
thread = Thread.new do
10
end
thread.join
thread.value # => 10
Friday, November 5, 2010
Shared Data
Friday, November 5, 2010
n = 0
def increment(v)
v + 1
end
threads = 2.times.map {
Thread.new {
1_000_000.times { n = increment(n) }
}
}
threads.eac...
2,000,000?
Friday, November 5, 2010
Friday, November 5, 2010
Friday, November 5, 2010
Read
Increment
Update
v = n
v += 1
n = v
n = 2
n = 2
n = 3
Friday, November 5, 2010
Thread 1 Thread 2
Friday, November 5, 2010
Read
Read
Thread 1 Thread 2
Increment
Increment
Update
Update
Friday, November 5, 2010
Read
Read
Thread 1 Thread 2
Increment
Increment
Update
Update
n = 2
n = 3
Friday, November 5, 2010
Solutions
Friday, November 5, 2010
Locking
Friday, November 5, 2010
Mutex
n = 0
mutex = Mutex.new
def increment(v)
v + 1
end
2.times do
Thread.new {
1_000_000.times {
mutex.synchronize { n =...
Mutex
n = 0
mutex = Mutex.new
def increment(v)
v + 1
end
2.times do
Thread.new {
1_000_000.times {
mutex.synchronize { n =...
Friday, November 5, 2010
Mutex_m
require 'mutex_m'
class Tenderlove
include Mutex_m
end
n = 0
mutex = Tenderlove.new
mutex.synchronize { ... }
Frid...
Conditional Variable
Friday, November 5, 2010
mutex = Mutex.new
resource = ConditionVariable.new
a = Thread.new {
mutex.synchronize {
puts "hello"
resource.wait(mutex)
...
mutex = Mutex.new
resource = ConditionVariable.new
a = Thread.new {
mutex.synchronize {
puts "hello"
resource.wait(mutex)
...
mutex = Mutex.new
resource = ConditionVariable.new
a = Thread.new {
mutex.synchronize {
puts "hello"
resource.wait(mutex)
...
Friday, November 5, 2010
Thread Safe
Objects
Friday, November 5, 2010
Queue
queue = Queue.new
[
Thread.new { 100.times {
queue << "omg!"
} },
Thread.new { 100.times {
queue << "omgagain!"
} },...
SizedQueue
Friday, November 5, 2010
Iterators
Friday, November 5, 2010
Internal
Friday, November 5, 2010
%w{ a b c d e }.each do
...
...
end
Friday, November 5, 2010
%w{ a b c d e }.each do
...
...
end
Friday, November 5, 2010
External
Friday, November 5, 2010
list = %w{ a b }
iter = Enumerator.new(list)
iter.next # => a
iter.next # => b
iter.next # raises StopIteration
Friday, No...
list = %w{ a b }
iter = Enumerator.new(list)
begin
3.times do
iter.next
end
rescue StopIteration => e
p e.result
end
Frida...
list = %w{ a b }
iter = Enumerator.new(list)
begin
3.times do
iter.next
end
rescue StopIteration => e
p e.result # => ["a"...
External => Internal
Friday, November 5, 2010
list = %w{ a b }
iter = Enumerator.new(list)
iter.each do |thing|
p thing
end
Friday, November 5, 2010
list = %w{ a b }
iter = Enumerator.new(list)
iter.each do |thing|
p thing
end
Friday, November 5, 2010
Specify a Method
Friday, November 5, 2010
list = %w{ a b }
iter = Enumerator.new(list, :map)
x = iter.each do |thing|
thing + " hello!"
end
p x
Friday, November 5, ...
list = %w{ a b }
iter = Enumerator.new(list, :map)
x = iter.each do |thing|
thing + " hello!"
end
p x # => ["a hello!", "b...
list = %w{ a b }
iter = Enumerator.new(list, :map)
x = iter.each_with_index do |thing, i|
thing + ":#{i}"
end
p x
Friday, ...
list = %w{ a b }
iter = Enumerator.new(list, :map)
x = iter.each_with_index do |thing, i|
thing + ":#{i}"
end
p x # => ["a...
DRY it up
Friday, November 5, 2010
list = %w{ a b }
iter = list.enum_for(:each)
3.times do
p iter.next
end
Friday, November 5, 2010
list = %w{ a b }
iter = list.each
3.times do
p itr.next
end
Friday, November 5, 2010
list = %w{ a b }
list.map.each_with_index { |obj, i|
"#{obj} => #{i}"
}
Friday, November 5, 2010
list = %w{ a b }
list.map.each_with_index { |obj, i|
"#{obj} => #{i}"
} # => ["a => 0", "b => 1"]
Friday, November 5, 2010
Fun with Iterators!
Friday, November 5, 2010
Parallel Iteration
Friday, November 5, 2010
a = %w{ a b c d }
b = %w{ a b c d }
iter = a.each
b.all? { |v| iter.next == v }
Friday, November 5, 2010
Iteration Strategy
Friday, November 5, 2010
Tree
Node
NodeNode
NodeNode
Friday, November 5, 2010
Node
class Node < Struct.new(:children)
def initialize(children = [])
super
end
end
Friday, November 5, 2010
Bottom Up
class DepthFirst < Struct.new(:tree)
def each(&block)
iterate(tree, block)
end
private
def iterate(node, block)
...
Node
NodeNode
NodeNode
Bottom Up
Node
NodeNode
NodeNode
Friday, November 5, 2010
Node
NodeNode
NodeNode
Bottom Up
Node
NodeNode
NodeNode
Friday, November 5, 2010
Top Down
class TopDown < Struct.new(:tree)
def each(&block)
iterate(tree, block)
end
private
def iterate(node, block)
bloc...
Node
NodeNode
NodeNode
Top Down
Node
NodeNode
NodeNode
Friday, November 5, 2010
Node
NodeNode
NodeNode
Top Down
Node
NodeNode
NodeNode
Friday, November 5, 2010
Node
class Node < Struct.new(:children)
def initialize(children = [])
super
end
def each(&block)
return enum_for(:each) un...
Parallel Iteration
iter = tree1.each
tree2.all? { |node| node == iter.next }
Friday, November 5, 2010
To Infinity, and
Beyond!
Friday, November 5, 2010
Infinite Series
n → ∞
Friday, November 5, 2010
class Infinity
include Enumerable
def each
return enum_for(:each) unless block_given?
i = 0
loop do
yield i
i += 1
end
end...
Friday, November 5, 2010
infinity = Enumerator.new do |yielder|
i = 0
loop do
yielder << i
i += 1
end
end
Friday, November 5, 2010
infinity = Enumerator.new do |yielder|
i = 0
loop do
yielder << i
i += 1
end
end
Friday, November 5, 2010
Friday, November 5, 2010
π
Pi
Friday, November 5, 2010
Mādhavan of Sangamagrāmam
Friday, November 5, 2010
Friday, November 5, 2010
pi = Enumerator.new do |yielder|
root_12 = Math.sqrt(12)
pi = 0
infinity.each do |k|
pi += (-1 / 3.0) ** k / (2 * k + 1).t...
pi = Enumerator.new do |yielder|
root_12 = Math.sqrt(12)
pi = 0
infinity.each do |k|
pi += (-1 / 3.0) ** k / (2 * k + 1).t...
Friday, November 5, 2010
Generators
Friday, November 5, 2010
Iterator.is_a?
Generator
Friday, November 5, 2010
Generator Client
Friday, November 5, 2010
Generator Client
Value
Friday, November 5, 2010
Fibers
Friday, November 5, 2010
Abstract Methods
Friday, November 5, 2010
method = Proc.new { ... }
method.call # => "hello"
method.call # => "world"
method.call # => "how are you?"
Friday, Novemb...
method = Proc.new { ... }
method.call('1') # => "1: hello"
method.call('2') # => "2: world"
method.call('3') # => "3: how ...
Proc => Fiber
Friday, November 5, 2010
call => resume
Friday, November 5, 2010
method = Proc.new { ... }
method.call('1') # => "1: hello"
method.call('2') # => "2: world"
method.call('3') # => "3: how ...
method = Fiber.new { ... }
method.resume('1') # => "1: hello"
method.resume('2') # => "2: world"
method.resume('3') # => "...
Arbitrary Exits
Friday, November 5, 2010
method = Fiber.new do
Fiber.yield "hello"
Fiber.yield "world"
end
method.resume # => "hello"
method.resume # => "world"
me...
Accept Parameters
Friday, November 5, 2010
method = Fiber.new do |val|
val = Fiber.yield "#{val}: hello"
val = Fiber.yield "#{val}: world"
val
end
method.resume(1) #...
method = Fiber.new do |val|
val = Fiber.yield "#{val}: hello"
val = Fiber.yield "#{val}: world"
val
end
method.resume(1) #...
method = Fiber.new do |val|
val = Fiber.yield "#{val}: hello"
val = Fiber.yield "#{val}: world"
val
end
method.resume(1) #...
First "resume" is
the block argument
Friday, November 5, 2010
method = Fiber.new do |val|
val = Fiber.yield "#{val}: hello"
val = Fiber.yield "#{val}: world"
val
end
method.resume(1) #...
The rest are
returned by
Fiber.yield
Friday, November 5, 2010
method = Fiber.new do |val|
val = Fiber.yield "#{val}: hello"
val = Fiber.yield "#{val}: world"
val
end
method.resume(1) #...
Cool story bro
Friday, November 5, 2010
Friday, November 5, 2010
Callbacks -> FSM
Friday, November 5, 2010
YAML
because XML is boring
Friday, November 5, 2010
YAML
yes, I wrote nokogiri. :-P
Friday, November 5, 2010
Psych
Ruby 1.9.2 Only
Friday, November 5, 2010
class Foo < Psych::Handler
def start_document(...)
...
end
def end_document(...)
...
end
end
SAX Style Handler
Friday, Nov...
Event Handler
class EventHandler
def initialize(fiber)
@fiber = fiber
end
def method_missing(name, *args)
@fiber.resume(na...
fiber = Fiber.new do |method, args|
stack = []
loop do
case method
when :start_mapping
stack << []
when :end_mapping
h = H...
case method
when :start_mapping
stack << []
when :end_mapping
h = Hash[*stack.pop]
if stack.empty?
stdout.resume h
else
st...
StdOut Fiber
stdout = Fiber.new do |obj|
loop do
p obj
obj = Fiber.yield
end
end
Friday, November 5, 2010
Tied Together
parser = Psych::Parser.new EventHandler.new
fiber
parser.parse(<<-eoyaml)
---
- foo: { fiz: buzz }
- bar: { ...
Friday, November 5, 2010
Filtering Results
Friday, November 5, 2010
Foo Filter
foo_filter = Fiber.new do |hash|
loop do
stdout.resume hash if hash.key? 'foo'
hash = Fiber.yield
end
end
Frida...
Output
{"foo"=>{"fiz"=>"buzz"}}
Friday, November 5, 2010
Scheduling
Threads Without Threads
Friday, November 5, 2010
P1
P2
Processes
Friday, November 5, 2010
P1
P2
Processes
fopen()
fread()
fseek()
fopen()
fopen()
Friday, November 5, 2010
Simple Example
Friday, November 5, 2010
Producer
producer = Fiber.new do
loop do
5.times do |i|
queue << "hello :#{i}"
end
Fiber.yield
end
end
Friday, November 5,...
Consumer
hungry = Fiber.new do
loop do
while !queue.empty?
puts queue.pop
end
Fiber.yield
end
end
Friday, November 5, 2010
Scheduler
fibers = [producer, hungry]
loop do
fibers.each do |fiber|
fiber.resume
end
end
Friday, November 5, 2010
Slow Consumer
slow = Fiber.new do
loop do
while !queue.empty?
sleep 1
puts "########### slow: " + queue.pop
Fiber.yield
en...
Random Scheduler
fibers = [producer, hungry, slow]
loop do
fibers.sort_by { rand }.each do |fiber|
fiber.resume
end
end
Fr...
Friday, November 5, 2010
"Processes"
•Anonymous
•We control when to "give up"
Friday, November 5, 2010
Homework
•Favor fast processes
•Favor queue fillers
•Favor queue drainers
•Deal with multiple queues
Friday, November 5, 20...
Generators
The Fiber Edition
Friday, November 5, 2010
infinity = Fiber.new do
i = 0
loop do
Fiber.yield i
i += 1
end
end
Friday, November 5, 2010
infinity = Enumerator.new do |yielder|
i = 0
loop do
yielder << i
i += 1
end
end
Friday, November 5, 2010
Our Own
Enumerator
Friday, November 5, 2010
class SimpleEnum
def initialize &block
@fiber = Fiber.new do
block.call(self)
end
end
def << value
Fiber.yield value
end
d...
infinity = SimpleEnum.new do |yielder|
i = 0
loop do
yielder << i
i += 1
end
end
Friday, November 5, 2010
•Capture return value
•Add StopIteration Exception
Homework
Friday, November 5, 2010
Coroutines
Friday, November 5, 2010
Fiber implements
Coroutine
Friday, November 5, 2010
Coroutine Client
Value
Friday, November 5, 2010
Coroutine Client
Value
Friday, November 5, 2010
Pipelines
Friday, November 5, 2010
Coroutine CoroutineGenerator
Friday, November 5, 2010
Coroutine CoroutineGenerator
Friday, November 5, 2010
Our Friend, Infinity
infinity = Fiber.new do
i = 0
loop do
Fiber.yield i
i += 1
end
end
Friday, November 5, 2010
Even Numbers
evens = Fiber.new do
loop do
value = infinity.resume
Fiber.yield value if value % 2 == 0
end
end
Friday, Nove...
Friday, November 5, 2010
Three's
threes = Fiber.new do
loop do
value = evens.resume
Fiber.yield value if value % 3 == 0
end
end
Friday, November 5,...
Three's
threes = Fiber.new do
loop do
value = evens.resume
Fiber.yield value if value % 3 == 0
end
end
Friday, November 5,...
Friday, November 5, 2010
Abstraction
Friday, November 5, 2010
Common Elements
•Source
•Sink
•Runloop
•Work
Friday, November 5, 2010
class Pipe < Struct.new(:source)
def initialize(source = nil)
super
@fiber = Fiber.new { self.loop }
end
def loop
while va...
class Infinity < Pipe
def loop
i = 0
while true
write i
i += 1
end
end
end
Infinity (again)
Friday, November 5, 2010
Evens
class Evens < Pipe
def process(value)
super if value % 2 == 0
end
end
Friday, November 5, 2010
StdOut
class StdOut < Pipe
def write value
puts value
end
end
Friday, November 5, 2010
Connection
infinity = Infinity.new
even = Evens.new infinity
stdout = StdOut.new even
stdout.resume
Friday, November 5, 20...
Pretty Syntax
class Pipe
def |(other)
other.source = self
other
end
end
Friday, November 5, 2010
Connection
(Infinity.new | Evens.new | StdOut.new).resume
Friday, November 5, 2010
Producer / Consumer
Friday, November 5, 2010
ERb
Friday, November 5, 2010
Compiled Template
template = ERB.new('<%= "hello" %>')
puts template.src
Friday, November 5, 2010
Compiled Template
#coding:US-ASCII
_erbout = '';
_erbout.concat(( "hello" ).to_s);
_erbout.force_encoding(__ENCODING__)
Fr...
Redirect Output
Friday, November 5, 2010
Compiled Template
erb = ERB.new('<%= "hello" %>', nil, nil, 'self')
puts erb.src
Friday, November 5, 2010
Compiled Template
#coding:US-ASCII
self = '';
self.concat(( "hello" ).to_s);
self.force_encoding(__ENCODING__)
Friday, Nov...
Compiled Template
#coding:US-ASCII
self = '';
self.concat(( "hello" ).to_s);
self.force_encoding(__ENCODING__)
Friday, Nov...
Monkey Patch!
class ERB::Compiler
def pre_cmd= x; end
end
erb = ERB.new('<%= "hello" %>', nil, nil,
'self')
puts erb.src
F...
Compiled Source
#coding:US-ASCII
self.concat(( "hello" ).to_s);
self.force_encoding(__ENCODING__)
Friday, November 5, 2010
ERb Pipe
Friday, November 5, 2010
ERb Pipe
class PipERB < Pipe
def initialize data
super()
@erb = ERB.new(data, nil, nil, 'self')
end
alias :concat :process...
Pipe to StdOut
(PipERB.new("<%= 'hello' %>") | StdOut.new).resume
Friday, November 5, 2010
ERb Pipe + Rack
Friday, November 5, 2010
Slow Template
<ul>
<% a = b = 1 %>
<% 10.times do %>
<li><%= a %></li>
<% sleep(1) # simulate work %>
<% a, b = b, a + b %...
Normal Handler
class ERBHandler
def initialize
@fib_template = DATA.read
end
def call env
result = [
ERB.new(@fib_template...
Friday, November 5, 2010
Rack API
Demands "each"
Friday, November 5, 2010
Each Pipe
class Each < Pipe
def each(&block)
@block = block
resume
end
def process(value)
@block.call(value)
end
end
Frida...
Each Pipe
(PipERB.new(DATA.read) | Each.new).each do |chunk|
print chunk
end
__END__
<ul>
<% a = b = 1 %>
<% 10.times do %...
Each Pipe
(PipERB.new(DATA.read) | Each.new).each do |chunk|
print chunk
end
__END__
<ul>
<% a = b = 1 %>
<% 10.times do %...
Fiber Handler
class ERBHandler
def initialize
@fib_template = DATA.read
end
def call env
[ 200, {},
(PipERB.new(@fib_templ...
Friday, November 5, 2010
Cooperative
Scheduling
Friday, November 5, 2010
ERb
Rack
Friday, November 5, 2010
Caveats?
Friday, November 5, 2010
Conclusion
Friday, November 5, 2010
Two Pipelines
Friday, November 5, 2010
Real Life?
Friday, November 5, 2010
Fibers are
Interesting!
Friday, November 5, 2010
Concurrency is
Interesting
Friday, November 5, 2010
But it requires a
shift in thinking
Friday, November 5, 2010
Install Ruby 1.9.2
Friday, November 5, 2010
Play with this at
home!
Friday, November 5, 2010
Questions?
Friday, November 5, 2010
Friday, November 5, 2010
Upcoming SlideShare
Loading in...5
×

RubyConf Brazil 2010

1,292

Published on

The slides for the talk I gave at RubyConf Brazil 2010!

Published in: Technology
0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total Views
1,292
On Slideshare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
9
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

Transcript of "RubyConf Brazil 2010"

  1. 1. OMG HELLO! Friday, November 5, 2010
  2. 2. THANK YOU Friday, November 5, 2010
  3. 3. Aaron Patterson Friday, November 5, 2010
  4. 4. AT&T, AT&T logo and all AT&T related marks are trademarks of AT&T Intellectual Property and/or AT&T affiliated companies. Friday, November 5, 2010
  5. 5. @tenderlove Friday, November 5, 2010
  6. 6. nokogiri Friday, November 5, 2010
  7. 7. ruby core committer Friday, November 5, 2010
  8. 8. YAML Friday, November 5, 2010
  9. 9. Psych Friday, November 5, 2010
  10. 10. DL Friday, November 5, 2010
  11. 11. rails core committer Friday, November 5, 2010
  12. 12. rails core committer Friday, November 5, 2010
  13. 13. ActiveRecord Friday, November 5, 2010
  14. 14. ARel Friday, November 5, 2010
  15. 15. anywhere... Friday, November 5, 2010
  16. 16. aaron.patterson@gmail.com Friday, November 5, 2010
  17. 17. Friday, November 5, 2010
  18. 18. WWFMD? Friday, November 5, 2010
  19. 19. Preparations the @tenderlove way Friday, November 5, 2010
  20. 20. What should I talk about? Friday, November 5, 2010
  21. 21. Yehuda? Friday, November 5, 2010
  22. 22. Evan? Friday, November 5, 2010
  23. 23. DHH? Friday, November 5, 2010
  24. 24. I will talk about Concurrency! Friday, November 5, 2010
  25. 25. Threads! Friday, November 5, 2010
  26. 26. Iterators! Friday, November 5, 2010
  27. 27. Generators! Friday, November 5, 2010
  28. 28. Fibers! Friday, November 5, 2010
  29. 29. Coroutines! Friday, November 5, 2010
  30. 30. Friday, November 5, 2010
  31. 31. the @tenderlove process for producing slides Friday, November 5, 2010
  32. 32. BOOKS ARE IN STORES NOW! Friday, November 5, 2010
  33. 33. ONLY $24.99!!! Friday, November 5, 2010
  34. 34. BUY TODAY! Friday, November 5, 2010
  35. 35. Fun with Fibers! Friday, November 5, 2010
  36. 36. Concurrency Friday, November 5, 2010
  37. 37. WARNING! Friday, November 5, 2010
  38. 38. fork() Friday, November 5, 2010
  39. 39. fork() foo = "hello" fork do foo << " world" puts foo end fork do foo << " everyone!" puts foo end puts foo Process.wait Friday, November 5, 2010
  40. 40. Copy on Write Friday, November 5, 2010
  41. 41. Threads Friday, November 5, 2010
  42. 42. Why Use Threads? Friday, November 5, 2010
  43. 43. Friday, November 5, 2010
  44. 44. Thread API Friday, November 5, 2010
  45. 45. thread = Thread.new { ... do some work ... } thread.join new and join Friday, November 5, 2010
  46. 46. 100.times { Thread.new { ... } } (Thread.list - [Thread.main]).each { |t| t.join } list / main Friday, November 5, 2010
  47. 47. Return Value thread = Thread.new do 10 end thread.join thread.value # => 10 Friday, November 5, 2010
  48. 48. Shared Data Friday, November 5, 2010
  49. 49. n = 0 def increment(v) v + 1 end threads = 2.times.map { Thread.new { 1_000_000.times { n = increment(n) } } } threads.each { |x| x.join } puts n Friday, November 5, 2010
  50. 50. 2,000,000? Friday, November 5, 2010
  51. 51. Friday, November 5, 2010
  52. 52. Friday, November 5, 2010
  53. 53. Read Increment Update v = n v += 1 n = v n = 2 n = 2 n = 3 Friday, November 5, 2010
  54. 54. Thread 1 Thread 2 Friday, November 5, 2010
  55. 55. Read Read Thread 1 Thread 2 Increment Increment Update Update Friday, November 5, 2010
  56. 56. Read Read Thread 1 Thread 2 Increment Increment Update Update n = 2 n = 3 Friday, November 5, 2010
  57. 57. Solutions Friday, November 5, 2010
  58. 58. Locking Friday, November 5, 2010
  59. 59. Mutex n = 0 mutex = Mutex.new def increment(v) v + 1 end 2.times do Thread.new { 1_000_000.times { mutex.synchronize { n = increment(n) } } } end Friday, November 5, 2010
  60. 60. Mutex n = 0 mutex = Mutex.new def increment(v) v + 1 end 2.times do Thread.new { 1_000_000.times { mutex.synchronize { n = increment(n) } } } end Friday, November 5, 2010
  61. 61. Friday, November 5, 2010
  62. 62. Mutex_m require 'mutex_m' class Tenderlove include Mutex_m end n = 0 mutex = Tenderlove.new mutex.synchronize { ... } Friday, November 5, 2010
  63. 63. Conditional Variable Friday, November 5, 2010
  64. 64. mutex = Mutex.new resource = ConditionVariable.new a = Thread.new { mutex.synchronize { puts "hello" resource.wait(mutex) puts "world" } } b = Thread.new { mutex.synchronize { puts "hello1" sleep 1 resource.signal } } a.join b.join Friday, November 5, 2010
  65. 65. mutex = Mutex.new resource = ConditionVariable.new a = Thread.new { mutex.synchronize { puts "hello" resource.wait(mutex) puts "world" } } b = Thread.new { mutex.synchronize { puts "hello1" sleep 1 resource.signal } } a.join b.join Friday, November 5, 2010
  66. 66. mutex = Mutex.new resource = ConditionVariable.new a = Thread.new { mutex.synchronize { puts "hello" resource.wait(mutex) puts "world" } } b = Thread.new { mutex.synchronize { puts "hello1" sleep 1 resource.signal } } a.join b.join Friday, November 5, 2010
  67. 67. Friday, November 5, 2010
  68. 68. Thread Safe Objects Friday, November 5, 2010
  69. 69. Queue queue = Queue.new [ Thread.new { 100.times { queue << "omg!" } }, Thread.new { 100.times { queue << "omgagain!" } }, ].each { |t| t.join } Friday, November 5, 2010
  70. 70. SizedQueue Friday, November 5, 2010
  71. 71. Iterators Friday, November 5, 2010
  72. 72. Internal Friday, November 5, 2010
  73. 73. %w{ a b c d e }.each do ... ... end Friday, November 5, 2010
  74. 74. %w{ a b c d e }.each do ... ... end Friday, November 5, 2010
  75. 75. External Friday, November 5, 2010
  76. 76. list = %w{ a b } iter = Enumerator.new(list) iter.next # => a iter.next # => b iter.next # raises StopIteration Friday, November 5, 2010
  77. 77. list = %w{ a b } iter = Enumerator.new(list) begin 3.times do iter.next end rescue StopIteration => e p e.result end Friday, November 5, 2010
  78. 78. list = %w{ a b } iter = Enumerator.new(list) begin 3.times do iter.next end rescue StopIteration => e p e.result # => ["a", "b"] end Friday, November 5, 2010
  79. 79. External => Internal Friday, November 5, 2010
  80. 80. list = %w{ a b } iter = Enumerator.new(list) iter.each do |thing| p thing end Friday, November 5, 2010
  81. 81. list = %w{ a b } iter = Enumerator.new(list) iter.each do |thing| p thing end Friday, November 5, 2010
  82. 82. Specify a Method Friday, November 5, 2010
  83. 83. list = %w{ a b } iter = Enumerator.new(list, :map) x = iter.each do |thing| thing + " hello!" end p x Friday, November 5, 2010
  84. 84. list = %w{ a b } iter = Enumerator.new(list, :map) x = iter.each do |thing| thing + " hello!" end p x # => ["a hello!", "b hello!"] Friday, November 5, 2010
  85. 85. list = %w{ a b } iter = Enumerator.new(list, :map) x = iter.each_with_index do |thing, i| thing + ":#{i}" end p x Friday, November 5, 2010
  86. 86. list = %w{ a b } iter = Enumerator.new(list, :map) x = iter.each_with_index do |thing, i| thing + ":#{i}" end p x # => ["a:0", "b:1"] Friday, November 5, 2010
  87. 87. DRY it up Friday, November 5, 2010
  88. 88. list = %w{ a b } iter = list.enum_for(:each) 3.times do p iter.next end Friday, November 5, 2010
  89. 89. list = %w{ a b } iter = list.each 3.times do p itr.next end Friday, November 5, 2010
  90. 90. list = %w{ a b } list.map.each_with_index { |obj, i| "#{obj} => #{i}" } Friday, November 5, 2010
  91. 91. list = %w{ a b } list.map.each_with_index { |obj, i| "#{obj} => #{i}" } # => ["a => 0", "b => 1"] Friday, November 5, 2010
  92. 92. Fun with Iterators! Friday, November 5, 2010
  93. 93. Parallel Iteration Friday, November 5, 2010
  94. 94. a = %w{ a b c d } b = %w{ a b c d } iter = a.each b.all? { |v| iter.next == v } Friday, November 5, 2010
  95. 95. Iteration Strategy Friday, November 5, 2010
  96. 96. Tree Node NodeNode NodeNode Friday, November 5, 2010
  97. 97. Node class Node < Struct.new(:children) def initialize(children = []) super end end Friday, November 5, 2010
  98. 98. Bottom Up class DepthFirst < Struct.new(:tree) def each(&block) iterate(tree, block) end private def iterate(node, block) node.children.each { |n| iterate(n, block) } block.call node end end Friday, November 5, 2010
  99. 99. Node NodeNode NodeNode Bottom Up Node NodeNode NodeNode Friday, November 5, 2010
  100. 100. Node NodeNode NodeNode Bottom Up Node NodeNode NodeNode Friday, November 5, 2010
  101. 101. Top Down class TopDown < Struct.new(:tree) def each(&block) iterate(tree, block) end private def iterate(node, block) block.call node node.children.each { |n| iterate(n, block) } end end Friday, November 5, 2010
  102. 102. Node NodeNode NodeNode Top Down Node NodeNode NodeNode Friday, November 5, 2010
  103. 103. Node NodeNode NodeNode Top Down Node NodeNode NodeNode Friday, November 5, 2010
  104. 104. Node class Node < Struct.new(:children) def initialize(children = []) super end def each(&block) return enum_for(:each) unless block_given? DepthFirst.new(self).each(&block) end end Friday, November 5, 2010
  105. 105. Parallel Iteration iter = tree1.each tree2.all? { |node| node == iter.next } Friday, November 5, 2010
  106. 106. To Infinity, and Beyond! Friday, November 5, 2010
  107. 107. Infinite Series n → ∞ Friday, November 5, 2010
  108. 108. class Infinity include Enumerable def each return enum_for(:each) unless block_given? i = 0 loop do yield i i += 1 end end end Friday, November 5, 2010
  109. 109. Friday, November 5, 2010
  110. 110. infinity = Enumerator.new do |yielder| i = 0 loop do yielder << i i += 1 end end Friday, November 5, 2010
  111. 111. infinity = Enumerator.new do |yielder| i = 0 loop do yielder << i i += 1 end end Friday, November 5, 2010
  112. 112. Friday, November 5, 2010
  113. 113. π Pi Friday, November 5, 2010
  114. 114. Mādhavan of Sangamagrāmam Friday, November 5, 2010
  115. 115. Friday, November 5, 2010
  116. 116. pi = Enumerator.new do |yielder| root_12 = Math.sqrt(12) pi = 0 infinity.each do |k| pi += (-1 / 3.0) ** k / (2 * k + 1).to_f yielder << (root_12 * pi) end end Friday, November 5, 2010
  117. 117. pi = Enumerator.new do |yielder| root_12 = Math.sqrt(12) pi = 0 infinity.each do |k| pi += (-1 / 3.0) ** k / (2 * k + 1).to_f yielder << (root_12 * pi) end end Friday, November 5, 2010
  118. 118. Friday, November 5, 2010
  119. 119. Generators Friday, November 5, 2010
  120. 120. Iterator.is_a? Generator Friday, November 5, 2010
  121. 121. Generator Client Friday, November 5, 2010
  122. 122. Generator Client Value Friday, November 5, 2010
  123. 123. Fibers Friday, November 5, 2010
  124. 124. Abstract Methods Friday, November 5, 2010
  125. 125. method = Proc.new { ... } method.call # => "hello" method.call # => "world" method.call # => "how are you?" Friday, November 5, 2010
  126. 126. method = Proc.new { ... } method.call('1') # => "1: hello" method.call('2') # => "2: world" method.call('3') # => "3: how are you?" Friday, November 5, 2010
  127. 127. Proc => Fiber Friday, November 5, 2010
  128. 128. call => resume Friday, November 5, 2010
  129. 129. method = Proc.new { ... } method.call('1') # => "1: hello" method.call('2') # => "2: world" method.call('3') # => "3: how are you?" Friday, November 5, 2010
  130. 130. method = Fiber.new { ... } method.resume('1') # => "1: hello" method.resume('2') # => "2: world" method.resume('3') # => "3: how are you?" Friday, November 5, 2010
  131. 131. Arbitrary Exits Friday, November 5, 2010
  132. 132. method = Fiber.new do Fiber.yield "hello" Fiber.yield "world" end method.resume # => "hello" method.resume # => "world" method.resume # => nil method.resume # => (FiberError) Friday, November 5, 2010
  133. 133. Accept Parameters Friday, November 5, 2010
  134. 134. method = Fiber.new do |val| val = Fiber.yield "#{val}: hello" val = Fiber.yield "#{val}: world" val end method.resume(1) # => "1: hello" method.resume(2) # => "2: world" method.resume(3) # => 3 method.resume(4) # => (FiberError) Friday, November 5, 2010
  135. 135. method = Fiber.new do |val| val = Fiber.yield "#{val}: hello" val = Fiber.yield "#{val}: world" val end method.resume(1) # => "1: hello" method.resume(2) # => "2: world" method.resume(3) # => 3 method.resume(4) # => (FiberError) Friday, November 5, 2010
  136. 136. method = Fiber.new do |val| val = Fiber.yield "#{val}: hello" val = Fiber.yield "#{val}: world" val end method.resume(1) # => "1: hello" method.resume(2) # => "2: world" method.resume(3) # => 3 method.resume(4) # => (FiberError) Friday, November 5, 2010
  137. 137. First "resume" is the block argument Friday, November 5, 2010
  138. 138. method = Fiber.new do |val| val = Fiber.yield "#{val}: hello" val = Fiber.yield "#{val}: world" val end method.resume(1) # => "1: hello" method.resume(2) # => "2: world" method.resume(3) # => 3 method.resume(4) # => (FiberError) Friday, November 5, 2010
  139. 139. The rest are returned by Fiber.yield Friday, November 5, 2010
  140. 140. method = Fiber.new do |val| val = Fiber.yield "#{val}: hello" val = Fiber.yield "#{val}: world" val end method.resume(1) # => "1: hello" method.resume(2) # => "2: world" method.resume(3) # => 3 method.resume(4) # => (FiberError) Friday, November 5, 2010
  141. 141. Cool story bro Friday, November 5, 2010
  142. 142. Friday, November 5, 2010
  143. 143. Callbacks -> FSM Friday, November 5, 2010
  144. 144. YAML because XML is boring Friday, November 5, 2010
  145. 145. YAML yes, I wrote nokogiri. :-P Friday, November 5, 2010
  146. 146. Psych Ruby 1.9.2 Only Friday, November 5, 2010
  147. 147. class Foo < Psych::Handler def start_document(...) ... end def end_document(...) ... end end SAX Style Handler Friday, November 5, 2010
  148. 148. Event Handler class EventHandler def initialize(fiber) @fiber = fiber end def method_missing(name, *args) @fiber.resume(name, args) end end Friday, November 5, 2010
  149. 149. fiber = Fiber.new do |method, args| stack = [] loop do case method when :start_mapping stack << [] when :end_mapping h = Hash[*stack.pop] if stack.empty? p h else stack.last << h end when :scalar stack.last << args.first end method, args = Fiber.yield end end Friday, November 5, 2010
  150. 150. case method when :start_mapping stack << [] when :end_mapping h = Hash[*stack.pop] if stack.empty? stdout.resume h else stack.last << h end when :scalar stack.last << args.first end method, args = Fiber.yield Friday, November 5, 2010
  151. 151. StdOut Fiber stdout = Fiber.new do |obj| loop do p obj obj = Fiber.yield end end Friday, November 5, 2010
  152. 152. Tied Together parser = Psych::Parser.new EventHandler.new fiber parser.parse(<<-eoyaml) --- - foo: { fiz: buzz } - bar: { fiz: buzz } - baz: { fiz: buzz } eoyaml Friday, November 5, 2010
  153. 153. Friday, November 5, 2010
  154. 154. Filtering Results Friday, November 5, 2010
  155. 155. Foo Filter foo_filter = Fiber.new do |hash| loop do stdout.resume hash if hash.key? 'foo' hash = Fiber.yield end end Friday, November 5, 2010
  156. 156. Output {"foo"=>{"fiz"=>"buzz"}} Friday, November 5, 2010
  157. 157. Scheduling Threads Without Threads Friday, November 5, 2010
  158. 158. P1 P2 Processes Friday, November 5, 2010
  159. 159. P1 P2 Processes fopen() fread() fseek() fopen() fopen() Friday, November 5, 2010
  160. 160. Simple Example Friday, November 5, 2010
  161. 161. Producer producer = Fiber.new do loop do 5.times do |i| queue << "hello :#{i}" end Fiber.yield end end Friday, November 5, 2010
  162. 162. Consumer hungry = Fiber.new do loop do while !queue.empty? puts queue.pop end Fiber.yield end end Friday, November 5, 2010
  163. 163. Scheduler fibers = [producer, hungry] loop do fibers.each do |fiber| fiber.resume end end Friday, November 5, 2010
  164. 164. Slow Consumer slow = Fiber.new do loop do while !queue.empty? sleep 1 puts "########### slow: " + queue.pop Fiber.yield end Fiber.yield end end Friday, November 5, 2010
  165. 165. Random Scheduler fibers = [producer, hungry, slow] loop do fibers.sort_by { rand }.each do |fiber| fiber.resume end end Friday, November 5, 2010
  166. 166. Friday, November 5, 2010
  167. 167. "Processes" •Anonymous •We control when to "give up" Friday, November 5, 2010
  168. 168. Homework •Favor fast processes •Favor queue fillers •Favor queue drainers •Deal with multiple queues Friday, November 5, 2010
  169. 169. Generators The Fiber Edition Friday, November 5, 2010
  170. 170. infinity = Fiber.new do i = 0 loop do Fiber.yield i i += 1 end end Friday, November 5, 2010
  171. 171. infinity = Enumerator.new do |yielder| i = 0 loop do yielder << i i += 1 end end Friday, November 5, 2010
  172. 172. Our Own Enumerator Friday, November 5, 2010
  173. 173. class SimpleEnum def initialize &block @fiber = Fiber.new do block.call(self) end end def << value Fiber.yield value end def next @fiber.resume end end Friday, November 5, 2010
  174. 174. infinity = SimpleEnum.new do |yielder| i = 0 loop do yielder << i i += 1 end end Friday, November 5, 2010
  175. 175. •Capture return value •Add StopIteration Exception Homework Friday, November 5, 2010
  176. 176. Coroutines Friday, November 5, 2010
  177. 177. Fiber implements Coroutine Friday, November 5, 2010
  178. 178. Coroutine Client Value Friday, November 5, 2010
  179. 179. Coroutine Client Value Friday, November 5, 2010
  180. 180. Pipelines Friday, November 5, 2010
  181. 181. Coroutine CoroutineGenerator Friday, November 5, 2010
  182. 182. Coroutine CoroutineGenerator Friday, November 5, 2010
  183. 183. Our Friend, Infinity infinity = Fiber.new do i = 0 loop do Fiber.yield i i += 1 end end Friday, November 5, 2010
  184. 184. Even Numbers evens = Fiber.new do loop do value = infinity.resume Fiber.yield value if value % 2 == 0 end end Friday, November 5, 2010
  185. 185. Friday, November 5, 2010
  186. 186. Three's threes = Fiber.new do loop do value = evens.resume Fiber.yield value if value % 3 == 0 end end Friday, November 5, 2010
  187. 187. Three's threes = Fiber.new do loop do value = evens.resume Fiber.yield value if value % 3 == 0 end end Friday, November 5, 2010
  188. 188. Friday, November 5, 2010
  189. 189. Abstraction Friday, November 5, 2010
  190. 190. Common Elements •Source •Sink •Runloop •Work Friday, November 5, 2010
  191. 191. class Pipe < Struct.new(:source) def initialize(source = nil) super @fiber = Fiber.new { self.loop } end def loop while value = read process value end end def read; source.resume end def write(value); Fiber.yield(value) end def process(value); write(value) end def resume; @fiber.resume end end Friday, November 5, 2010
  192. 192. class Infinity < Pipe def loop i = 0 while true write i i += 1 end end end Infinity (again) Friday, November 5, 2010
  193. 193. Evens class Evens < Pipe def process(value) super if value % 2 == 0 end end Friday, November 5, 2010
  194. 194. StdOut class StdOut < Pipe def write value puts value end end Friday, November 5, 2010
  195. 195. Connection infinity = Infinity.new even = Evens.new infinity stdout = StdOut.new even stdout.resume Friday, November 5, 2010
  196. 196. Pretty Syntax class Pipe def |(other) other.source = self other end end Friday, November 5, 2010
  197. 197. Connection (Infinity.new | Evens.new | StdOut.new).resume Friday, November 5, 2010
  198. 198. Producer / Consumer Friday, November 5, 2010
  199. 199. ERb Friday, November 5, 2010
  200. 200. Compiled Template template = ERB.new('<%= "hello" %>') puts template.src Friday, November 5, 2010
  201. 201. Compiled Template #coding:US-ASCII _erbout = ''; _erbout.concat(( "hello" ).to_s); _erbout.force_encoding(__ENCODING__) Friday, November 5, 2010
  202. 202. Redirect Output Friday, November 5, 2010
  203. 203. Compiled Template erb = ERB.new('<%= "hello" %>', nil, nil, 'self') puts erb.src Friday, November 5, 2010
  204. 204. Compiled Template #coding:US-ASCII self = ''; self.concat(( "hello" ).to_s); self.force_encoding(__ENCODING__) Friday, November 5, 2010
  205. 205. Compiled Template #coding:US-ASCII self = ''; self.concat(( "hello" ).to_s); self.force_encoding(__ENCODING__) Friday, November 5, 2010
  206. 206. Monkey Patch! class ERB::Compiler def pre_cmd= x; end end erb = ERB.new('<%= "hello" %>', nil, nil, 'self') puts erb.src Friday, November 5, 2010
  207. 207. Compiled Source #coding:US-ASCII self.concat(( "hello" ).to_s); self.force_encoding(__ENCODING__) Friday, November 5, 2010
  208. 208. ERb Pipe Friday, November 5, 2010
  209. 209. ERb Pipe class PipERB < Pipe def initialize data super() @erb = ERB.new(data, nil, nil, 'self') end alias :concat :process def read; @erb.result(binding) end def force_encoding encoding; end end Friday, November 5, 2010
  210. 210. Pipe to StdOut (PipERB.new("<%= 'hello' %>") | StdOut.new).resume Friday, November 5, 2010
  211. 211. ERb Pipe + Rack Friday, November 5, 2010
  212. 212. Slow Template <ul> <% a = b = 1 %> <% 10.times do %> <li><%= a %></li> <% sleep(1) # simulate work %> <% a, b = b, a + b %> <% end %> </ul> Friday, November 5, 2010
  213. 213. Normal Handler class ERBHandler def initialize @fib_template = DATA.read end def call env result = [ ERB.new(@fib_template).result(binding) ] [ 200, {'X-Hello' => 'World'}, result ] end end Friday, November 5, 2010
  214. 214. Friday, November 5, 2010
  215. 215. Rack API Demands "each" Friday, November 5, 2010
  216. 216. Each Pipe class Each < Pipe def each(&block) @block = block resume end def process(value) @block.call(value) end end Friday, November 5, 2010
  217. 217. Each Pipe (PipERB.new(DATA.read) | Each.new).each do |chunk| print chunk end __END__ <ul> <% a = b = 1 %> <% 10.times do %> <li><%= a %></li> <% sleep 1; a, b = b, a + b %> <% end %> </ul> Friday, November 5, 2010
  218. 218. Each Pipe (PipERB.new(DATA.read) | Each.new).each do |chunk| print chunk end __END__ <ul> <% a = b = 1 %> <% 10.times do %> <li><%= a %></li> <% sleep 1; a, b = b, a + b %> <% end %> </ul> Friday, November 5, 2010
  219. 219. Fiber Handler class ERBHandler def initialize @fib_template = DATA.read end def call env [ 200, {}, (PipERB.new(@fib_template) | Each.new) ] end end Friday, November 5, 2010
  220. 220. Friday, November 5, 2010
  221. 221. Cooperative Scheduling Friday, November 5, 2010
  222. 222. ERb Rack Friday, November 5, 2010
  223. 223. Caveats? Friday, November 5, 2010
  224. 224. Conclusion Friday, November 5, 2010
  225. 225. Two Pipelines Friday, November 5, 2010
  226. 226. Real Life? Friday, November 5, 2010
  227. 227. Fibers are Interesting! Friday, November 5, 2010
  228. 228. Concurrency is Interesting Friday, November 5, 2010
  229. 229. But it requires a shift in thinking Friday, November 5, 2010
  230. 230. Install Ruby 1.9.2 Friday, November 5, 2010
  231. 231. Play with this at home! Friday, November 5, 2010
  232. 232. Questions? Friday, November 5, 2010
  233. 233. Friday, November 5, 2010
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×