127
Realtime Rails Four

Realtime Rails Four2012.rubyworld-conf.org/files/slides/rwc2012_A-6.pdfAllow concurrency (enable) Loading Code isn’t Thread-safe* Preload Frameworks ED Cache classes ED Dependency

  • Upload
    others

  • View
    36

  • Download
    0

Embed Size (px)

Citation preview

Page 1: Realtime Rails Four2012.rubyworld-conf.org/files/slides/rwc2012_A-6.pdfAllow concurrency (enable) Loading Code isn’t Thread-safe* Preload Frameworks ED Cache classes ED Dependency

RealtimeRails Four

Page 2: Realtime Rails Four2012.rubyworld-conf.org/files/slides/rwc2012_A-6.pdfAllow concurrency (enable) Loading Code isn’t Thread-safe* Preload Frameworks ED Cache classes ED Dependency

Rails FourFor you and for me!

Page 3: Realtime Rails Four2012.rubyworld-conf.org/files/slides/rwc2012_A-6.pdfAllow concurrency (enable) Loading Code isn’t Thread-safe* Preload Frameworks ED Cache classes ED Dependency

Aaron Patterson@tenderlove

Page 4: Realtime Rails Four2012.rubyworld-conf.org/files/slides/rwc2012_A-6.pdfAllow concurrency (enable) Loading Code isn’t Thread-safe* Preload Frameworks ED Cache classes ED Dependency

HI!! :-)

Page 5: Realtime Rails Four2012.rubyworld-conf.org/files/slides/rwc2012_A-6.pdfAllow concurrency (enable) Loading Code isn’t Thread-safe* Preload Frameworks ED Cache classes ED Dependency

AT&T, AT&T logo and all AT&T related marks are trademarks of AT&T Intellectual Property and/or AT&T affiliated companies.

Page 6: Realtime Rails Four2012.rubyworld-conf.org/files/slides/rwc2012_A-6.pdfAllow concurrency (enable) Loading Code isn’t Thread-safe* Preload Frameworks ED Cache classes ED Dependency

Rails FourFor you and me!!!

Page 7: Realtime Rails Four2012.rubyworld-conf.org/files/slides/rwc2012_A-6.pdfAllow concurrency (enable) Loading Code isn’t Thread-safe* Preload Frameworks ED Cache classes ED Dependency

The Web!

Page 8: Realtime Rails Four2012.rubyworld-conf.org/files/slides/rwc2012_A-6.pdfAllow concurrency (enable) Loading Code isn’t Thread-safe* Preload Frameworks ED Cache classes ED Dependency

Ruby

Rails

Web

Page 9: Realtime Rails Four2012.rubyworld-conf.org/files/slides/rwc2012_A-6.pdfAllow concurrency (enable) Loading Code isn’t Thread-safe* Preload Frameworks ED Cache classes ED Dependency

Thread SafetyIn Rails

Page 10: Realtime Rails Four2012.rubyworld-conf.org/files/slides/rwc2012_A-6.pdfAllow concurrency (enable) Loading Code isn’t Thread-safe* Preload Frameworks ED Cache classes ED Dependency

Delete config.threadsafe!

Page 11: Realtime Rails Four2012.rubyworld-conf.org/files/slides/rwc2012_A-6.pdfAllow concurrency (enable) Loading Code isn’t Thread-safe* Preload Frameworks ED Cache classes ED Dependency

Why delete?

Page 12: Realtime Rails Four2012.rubyworld-conf.org/files/slides/rwc2012_A-6.pdfAllow concurrency (enable) Loading Code isn’t Thread-safe* Preload Frameworks ED Cache classes ED Dependency

Always bethread safe!

Page 13: Realtime Rails Four2012.rubyworld-conf.org/files/slides/rwc2012_A-6.pdfAllow concurrency (enable) Loading Code isn’t Thread-safe* Preload Frameworks ED Cache classes ED Dependency

Always bethread safe!

MyOpinion!

Page 14: Realtime Rails Four2012.rubyworld-conf.org/files/slides/rwc2012_A-6.pdfAllow concurrency (enable) Loading Code isn’t Thread-safe* Preload Frameworks ED Cache classes ED Dependency

Simplify

Page 15: Realtime Rails Four2012.rubyworld-conf.org/files/slides/rwc2012_A-6.pdfAllow concurrency (enable) Loading Code isn’t Thread-safe* Preload Frameworks ED Cache classes ED Dependency

Is it safe to remove?

Page 16: Realtime Rails Four2012.rubyworld-conf.org/files/slides/rwc2012_A-6.pdfAllow concurrency (enable) Loading Code isn’t Thread-safe* Preload Frameworks ED Cache classes ED Dependency

What did it do?

Page 17: Realtime Rails Four2012.rubyworld-conf.org/files/slides/rwc2012_A-6.pdfAllow concurrency (enable) Loading Code isn’t Thread-safe* Preload Frameworks ED Cache classes ED Dependency

threadsafe!

❤ Preload frameworks (enable)❤ Cache classes (enable)❤ Dependency loading (disable)❤ Allow concurrency (enable)

Page 18: Realtime Rails Four2012.rubyworld-conf.org/files/slides/rwc2012_A-6.pdfAllow concurrency (enable) Loading Code isn’t Thread-safe* Preload Frameworks ED Cache classes ED Dependency

Loading Code isn’t Thread-safe*

Page 19: Realtime Rails Four2012.rubyworld-conf.org/files/slides/rwc2012_A-6.pdfAllow concurrency (enable) Loading Code isn’t Thread-safe* Preload Frameworks ED Cache classes ED Dependency

Preload Frameworks

ENABLED

Page 20: Realtime Rails Four2012.rubyworld-conf.org/files/slides/rwc2012_A-6.pdfAllow concurrency (enable) Loading Code isn’t Thread-safe* Preload Frameworks ED Cache classes ED Dependency

Cache classes

ENABLED

Page 21: Realtime Rails Four2012.rubyworld-conf.org/files/slides/rwc2012_A-6.pdfAllow concurrency (enable) Loading Code isn’t Thread-safe* Preload Frameworks ED Cache classes ED Dependency

Dependency Loading

DISABLED

Page 22: Realtime Rails Four2012.rubyworld-conf.org/files/slides/rwc2012_A-6.pdfAllow concurrency (enable) Loading Code isn’t Thread-safe* Preload Frameworks ED Cache classes ED Dependency

Allow Concurrency

ENABLED

Page 23: Realtime Rails Four2012.rubyworld-conf.org/files/slides/rwc2012_A-6.pdfAllow concurrency (enable) Loading Code isn’t Thread-safe* Preload Frameworks ED Cache classes ED Dependency

Get Lock

Read from Socket

Process Stuff

Write to Socket

Release Lock

Rack::Lock

Page 24: Realtime Rails Four2012.rubyworld-conf.org/files/slides/rwc2012_A-6.pdfAllow concurrency (enable) Loading Code isn’t Thread-safe* Preload Frameworks ED Cache classes ED Dependency

Thread 2 Get Lock

Read from Socket

Process Stuff

Write to Socket

Release Lock

Thread 1

Rack::Lock

Page 25: Realtime Rails Four2012.rubyworld-conf.org/files/slides/rwc2012_A-6.pdfAllow concurrency (enable) Loading Code isn’t Thread-safe* Preload Frameworks ED Cache classes ED Dependency

Thread 2 Get Lock

Read from Socket

Process Stuff

Write to Socket

Release Lock

Rack::Lock

Page 26: Realtime Rails Four2012.rubyworld-conf.org/files/slides/rwc2012_A-6.pdfAllow concurrency (enable) Loading Code isn’t Thread-safe* Preload Frameworks ED Cache classes ED Dependency

Thread 2

Get Lock

Read from Socket

Process Stuff

Write to Socket

Release Lock

Rack::Lock

Page 27: Realtime Rails Four2012.rubyworld-conf.org/files/slides/rwc2012_A-6.pdfAllow concurrency (enable) Loading Code isn’t Thread-safe* Preload Frameworks ED Cache classes ED Dependency

Rack::Lock with Processes

Page 28: Realtime Rails Four2012.rubyworld-conf.org/files/slides/rwc2012_A-6.pdfAllow concurrency (enable) Loading Code isn’t Thread-safe* Preload Frameworks ED Cache classes ED Dependency

Rack::Lock withThreads

Page 29: Realtime Rails Four2012.rubyworld-conf.org/files/slides/rwc2012_A-6.pdfAllow concurrency (enable) Loading Code isn’t Thread-safe* Preload Frameworks ED Cache classes ED Dependency

Best Case:Extra Overhead

Page 30: Realtime Rails Four2012.rubyworld-conf.org/files/slides/rwc2012_A-6.pdfAllow concurrency (enable) Loading Code isn’t Thread-safe* Preload Frameworks ED Cache classes ED Dependency

Worst Case:1 req at a time

Page 31: Realtime Rails Four2012.rubyworld-conf.org/files/slides/rwc2012_A-6.pdfAllow concurrency (enable) Loading Code isn’t Thread-safe* Preload Frameworks ED Cache classes ED Dependency

IMPACT

Page 32: Realtime Rails Four2012.rubyworld-conf.org/files/slides/rwc2012_A-6.pdfAllow concurrency (enable) Loading Code isn’t Thread-safe* Preload Frameworks ED Cache classes ED Dependency

Boot time increases (in prod)

Page 33: Realtime Rails Four2012.rubyworld-conf.org/files/slides/rwc2012_A-6.pdfAllow concurrency (enable) Loading Code isn’t Thread-safe* Preload Frameworks ED Cache classes ED Dependency

Fewer middleware

Page 34: Realtime Rails Four2012.rubyworld-conf.org/files/slides/rwc2012_A-6.pdfAllow concurrency (enable) Loading Code isn’t Thread-safe* Preload Frameworks ED Cache classes ED Dependency

Multi-Proc serversstay the same

Page 35: Realtime Rails Four2012.rubyworld-conf.org/files/slides/rwc2012_A-6.pdfAllow concurrency (enable) Loading Code isn’t Thread-safe* Preload Frameworks ED Cache classes ED Dependency

Threaded serversJust Work™

Page 36: Realtime Rails Four2012.rubyworld-conf.org/files/slides/rwc2012_A-6.pdfAllow concurrency (enable) Loading Code isn’t Thread-safe* Preload Frameworks ED Cache classes ED Dependency

Bug Fixes

Page 37: Realtime Rails Four2012.rubyworld-conf.org/files/slides/rwc2012_A-6.pdfAllow concurrency (enable) Loading Code isn’t Thread-safe* Preload Frameworks ED Cache classes ED Dependency

100% Caching

Page 38: Realtime Rails Four2012.rubyworld-conf.org/files/slides/rwc2012_A-6.pdfAllow concurrency (enable) Loading Code isn’t Thread-safe* Preload Frameworks ED Cache classes ED Dependency

Locking ||=

def some_method @value ||= some_calculationend

Page 39: Realtime Rails Four2012.rubyworld-conf.org/files/slides/rwc2012_A-6.pdfAllow concurrency (enable) Loading Code isn’t Thread-safe* Preload Frameworks ED Cache classes ED Dependency

check then act

Is nil?

Calculate

Return

Set

Page 40: Realtime Rails Four2012.rubyworld-conf.org/files/slides/rwc2012_A-6.pdfAllow concurrency (enable) Loading Code isn’t Thread-safe* Preload Frameworks ED Cache classes ED Dependency

check then act

Is nil?

Calculate

Return

Thread 1

Set

Page 41: Realtime Rails Four2012.rubyworld-conf.org/files/slides/rwc2012_A-6.pdfAllow concurrency (enable) Loading Code isn’t Thread-safe* Preload Frameworks ED Cache classes ED Dependency

check then act

Is nil?

Calculate

Return

Thread 1

Set

Thread 2

Page 42: Realtime Rails Four2012.rubyworld-conf.org/files/slides/rwc2012_A-6.pdfAllow concurrency (enable) Loading Code isn’t Thread-safe* Preload Frameworks ED Cache classes ED Dependency

check then act

Is nil?

Calculate

Return

Thread 1 Set

Thread 2

Page 43: Realtime Rails Four2012.rubyworld-conf.org/files/slides/rwc2012_A-6.pdfAllow concurrency (enable) Loading Code isn’t Thread-safe* Preload Frameworks ED Cache classes ED Dependency

check then act

Is nil?

Calculate

Return

Set

Page 44: Realtime Rails Four2012.rubyworld-conf.org/files/slides/rwc2012_A-6.pdfAllow concurrency (enable) Loading Code isn’t Thread-safe* Preload Frameworks ED Cache classes ED Dependency

Fix #1 (eager init)class Foo class << self def hard_calculation @calc end end

@calc = fib(34)end

p Foo.hard_calculation

Page 45: Realtime Rails Four2012.rubyworld-conf.org/files/slides/rwc2012_A-6.pdfAllow concurrency (enable) Loading Code isn’t Thread-safe* Preload Frameworks ED Cache classes ED Dependency

Fix #2 (locking)class Foo @lock = Mutex.new

class << self def hard_calculation @lock.synchronize do @calc ||= fib(34) end end endend

p Foo.hard_calculation

Page 46: Realtime Rails Four2012.rubyworld-conf.org/files/slides/rwc2012_A-6.pdfAllow concurrency (enable) Loading Code isn’t Thread-safe* Preload Frameworks ED Cache classes ED Dependency

Fix #2 (locking)class Foo @lock = Mutex.new

class << self def hard_calculation @lock.synchronize do @calc ||= fib(34) end end endend

p Foo.hard_calculation

Page 47: Realtime Rails Four2012.rubyworld-conf.org/files/slides/rwc2012_A-6.pdfAllow concurrency (enable) Loading Code isn’t Thread-safe* Preload Frameworks ED Cache classes ED Dependency

Fix #2 (locking)class Foo @lock = Mutex.new

class << self def hard_calculation @lock.synchronize do @calc ||= fib(34) end end endend

p Foo.hard_calculation

Page 48: Realtime Rails Four2012.rubyworld-conf.org/files/slides/rwc2012_A-6.pdfAllow concurrency (enable) Loading Code isn’t Thread-safe* Preload Frameworks ED Cache classes ED Dependency

Move methods to instances

Page 49: Realtime Rails Four2012.rubyworld-conf.org/files/slides/rwc2012_A-6.pdfAllow concurrency (enable) Loading Code isn’t Thread-safe* Preload Frameworks ED Cache classes ED Dependency

Move to objectclass Foo def initialize @calc = fib(34) end

def hard_calculation @calc endend

Foo.new.hard_calculation

Page 50: Realtime Rails Four2012.rubyworld-conf.org/files/slides/rwc2012_A-6.pdfAllow concurrency (enable) Loading Code isn’t Thread-safe* Preload Frameworks ED Cache classes ED Dependency

Lazy Objectclass Foo include Mutex_m

def hard_calculation synchronize do @calc ||= fib(34) end endend

Foo.new.hard_calculation

Page 51: Realtime Rails Four2012.rubyworld-conf.org/files/slides/rwc2012_A-6.pdfAllow concurrency (enable) Loading Code isn’t Thread-safe* Preload Frameworks ED Cache classes ED Dependency

Maintain APIclass Foo include Mutex_m

def hard_calculation synchronize do @calc ||= fib(34) end end

Instance = new

def self.hard_calculation Instance.hard_calculation endend

Foo.hard_calculation

Page 52: Realtime Rails Four2012.rubyworld-conf.org/files/slides/rwc2012_A-6.pdfAllow concurrency (enable) Loading Code isn’t Thread-safe* Preload Frameworks ED Cache classes ED Dependency

Hash.new { }class Foo def initialize @cache = Hash.new { |h,k| h[k] = [] } end

def some_value(key) @cache[key] endend

Page 53: Realtime Rails Four2012.rubyworld-conf.org/files/slides/rwc2012_A-6.pdfAllow concurrency (enable) Loading Code isn’t Thread-safe* Preload Frameworks ED Cache classes ED Dependency

Fix #1 (lock)class Foo include Mutex_m

def initialize super

@cache = Hash.new { |h,k| h[k] = [] } end

def some_value(key) synchronize { @cache[key] } endend

Page 54: Realtime Rails Four2012.rubyworld-conf.org/files/slides/rwc2012_A-6.pdfAllow concurrency (enable) Loading Code isn’t Thread-safe* Preload Frameworks ED Cache classes ED Dependency

Fix #2 thread_safe

https://github.com/headius/thread_safe

Page 55: Realtime Rails Four2012.rubyworld-conf.org/files/slides/rwc2012_A-6.pdfAllow concurrency (enable) Loading Code isn’t Thread-safe* Preload Frameworks ED Cache classes ED Dependency

What about the App Level?

Page 56: Realtime Rails Four2012.rubyworld-conf.org/files/slides/rwc2012_A-6.pdfAllow concurrency (enable) Loading Code isn’t Thread-safe* Preload Frameworks ED Cache classes ED Dependency

Thread SafetyIn Web Apps

Page 57: Realtime Rails Four2012.rubyworld-conf.org/files/slides/rwc2012_A-6.pdfAllow concurrency (enable) Loading Code isn’t Thread-safe* Preload Frameworks ED Cache classes ED Dependency

Avoid shared data

Page 58: Realtime Rails Four2012.rubyworld-conf.org/files/slides/rwc2012_A-6.pdfAllow concurrency (enable) Loading Code isn’t Thread-safe* Preload Frameworks ED Cache classes ED Dependency

Most people don’t type “Thread.new”

Page 59: Realtime Rails Four2012.rubyworld-conf.org/files/slides/rwc2012_A-6.pdfAllow concurrency (enable) Loading Code isn’t Thread-safe* Preload Frameworks ED Cache classes ED Dependency

Look for things that are global.

Page 60: Realtime Rails Four2012.rubyworld-conf.org/files/slides/rwc2012_A-6.pdfAllow concurrency (enable) Loading Code isn’t Thread-safe* Preload Frameworks ED Cache classes ED Dependency

Global Variables

$so_global = {}$so_global[:foo] ||= “bar”

Page 61: Realtime Rails Four2012.rubyworld-conf.org/files/slides/rwc2012_A-6.pdfAllow concurrency (enable) Loading Code isn’t Thread-safe* Preload Frameworks ED Cache classes ED Dependency

Constants

SET_TWICE = 10SET_TWICE = 10

ALSO_GLOBAL = {}ALSO_GLOBAL[:foo] ||= “bar”

Warning

No Warning

Page 62: Realtime Rails Four2012.rubyworld-conf.org/files/slides/rwc2012_A-6.pdfAllow concurrency (enable) Loading Code isn’t Thread-safe* Preload Frameworks ED Cache classes ED Dependency

Class methods

class MyModel def self.some_cache @foo ||= fib(34) endend

Page 63: Realtime Rails Four2012.rubyworld-conf.org/files/slides/rwc2012_A-6.pdfAllow concurrency (enable) Loading Code isn’t Thread-safe* Preload Frameworks ED Cache classes ED Dependency

Avoid global data

Page 64: Realtime Rails Four2012.rubyworld-conf.org/files/slides/rwc2012_A-6.pdfAllow concurrency (enable) Loading Code isn’t Thread-safe* Preload Frameworks ED Cache classes ED Dependency

Add locks

Page 65: Realtime Rails Four2012.rubyworld-conf.org/files/slides/rwc2012_A-6.pdfAllow concurrency (enable) Loading Code isn’t Thread-safe* Preload Frameworks ED Cache classes ED Dependency

Streaming

Page 66: Realtime Rails Four2012.rubyworld-conf.org/files/slides/rwc2012_A-6.pdfAllow concurrency (enable) Loading Code isn’t Thread-safe* Preload Frameworks ED Cache classes ED Dependency

Template Rendering Today

Page 67: Realtime Rails Four2012.rubyworld-conf.org/files/slides/rwc2012_A-6.pdfAllow concurrency (enable) Loading Code isn’t Thread-safe* Preload Frameworks ED Cache classes ED Dependency

Templates Results are Buffered

Page 68: Realtime Rails Four2012.rubyworld-conf.org/files/slides/rwc2012_A-6.pdfAllow concurrency (enable) Loading Code isn’t Thread-safe* Preload Frameworks ED Cache classes ED Dependency

Clients are blocked while Rails works

Page 69: Realtime Rails Four2012.rubyworld-conf.org/files/slides/rwc2012_A-6.pdfAllow concurrency (enable) Loading Code isn’t Thread-safe* Preload Frameworks ED Cache classes ED Dependency

The entire page must fit in memory

Page 70: Realtime Rails Four2012.rubyworld-conf.org/files/slides/rwc2012_A-6.pdfAllow concurrency (enable) Loading Code isn’t Thread-safe* Preload Frameworks ED Cache classes ED Dependency

Rack Encourages Buffering

class MyApplication def call(env) [200, {}, [‘my page’]] endend

Page 71: Realtime Rails Four2012.rubyworld-conf.org/files/slides/rwc2012_A-6.pdfAllow concurrency (enable) Loading Code isn’t Thread-safe* Preload Frameworks ED Cache classes ED Dependency

We can do I/O and CPU in parallel.

Page 72: Realtime Rails Four2012.rubyworld-conf.org/files/slides/rwc2012_A-6.pdfAllow concurrency (enable) Loading Code isn’t Thread-safe* Preload Frameworks ED Cache classes ED Dependency

So why buffer?

Page 73: Realtime Rails Four2012.rubyworld-conf.org/files/slides/rwc2012_A-6.pdfAllow concurrency (enable) Loading Code isn’t Thread-safe* Preload Frameworks ED Cache classes ED Dependency

ActionController::Live

Page 74: Realtime Rails Four2012.rubyworld-conf.org/files/slides/rwc2012_A-6.pdfAllow concurrency (enable) Loading Code isn’t Thread-safe* Preload Frameworks ED Cache classes ED Dependency

Exampleclass BrowserController < ApplicationController include ActionController::Live

def index 100.times do response.stream.write "hello!\n" end response.stream.close endend

Page 75: Realtime Rails Four2012.rubyworld-conf.org/files/slides/rwc2012_A-6.pdfAllow concurrency (enable) Loading Code isn’t Thread-safe* Preload Frameworks ED Cache classes ED Dependency

Exampleclass BrowserController < ApplicationController include ActionController::Live

def index 100.times do response.stream.write "hello!\n" end response.stream.close endend

Mix in

Stream

Page 76: Realtime Rails Four2012.rubyworld-conf.org/files/slides/rwc2012_A-6.pdfAllow concurrency (enable) Loading Code isn’t Thread-safe* Preload Frameworks ED Cache classes ED Dependency

response.stream acts likean I/O object

Page 77: Realtime Rails Four2012.rubyworld-conf.org/files/slides/rwc2012_A-6.pdfAllow concurrency (enable) Loading Code isn’t Thread-safe* Preload Frameworks ED Cache classes ED Dependency

EverythingIs a File

Page 78: Realtime Rails Four2012.rubyworld-conf.org/files/slides/rwc2012_A-6.pdfAllow concurrency (enable) Loading Code isn’t Thread-safe* Preload Frameworks ED Cache classes ED Dependency

How does it work?

Page 79: Realtime Rails Four2012.rubyworld-conf.org/files/slides/rwc2012_A-6.pdfAllow concurrency (enable) Loading Code isn’t Thread-safe* Preload Frameworks ED Cache classes ED Dependency

Our APIdef index response.status = 200 response.headers[‘X-Whatever’] = ‘<3’ response.stream.write ‘hello’ response.stream.write ‘ world’ response.stream.closeend

Page 80: Realtime Rails Four2012.rubyworld-conf.org/files/slides/rwc2012_A-6.pdfAllow concurrency (enable) Loading Code isn’t Thread-safe* Preload Frameworks ED Cache classes ED Dependency

Rack API

def call(env) return [200, {‘X-Whatever’ => ‘<3’}, [‘hello world’]]end

Page 81: Realtime Rails Four2012.rubyworld-conf.org/files/slides/rwc2012_A-6.pdfAllow concurrency (enable) Loading Code isn’t Thread-safe* Preload Frameworks ED Cache classes ED Dependency

Wrapped Requestclass Response attr_accessor :status attr_reader :headers, :stream

def initialize @status = 200 @headers = {} @stream = StringIO.new endend

def call(env) res = Response.new controller.response = res controller.index [res.status, res.headers, res.stream]end

Page 82: Realtime Rails Four2012.rubyworld-conf.org/files/slides/rwc2012_A-6.pdfAllow concurrency (enable) Loading Code isn’t Thread-safe* Preload Frameworks ED Cache classes ED Dependency

Threaded action

def call(env) res = Response.new controller.response = res Thread.new { controller.index } [res.status, res.headers, res.stream]end

Page 83: Realtime Rails Four2012.rubyworld-conf.org/files/slides/rwc2012_A-6.pdfAllow concurrency (enable) Loading Code isn’t Thread-safe* Preload Frameworks ED Cache classes ED Dependency

Block until writedef call(env) res = Response.new controller.response = res Thread.new { controller.index } res.stream.await [res.status, res.headers, res.stream]end

Page 84: Realtime Rails Four2012.rubyworld-conf.org/files/slides/rwc2012_A-6.pdfAllow concurrency (enable) Loading Code isn’t Thread-safe* Preload Frameworks ED Cache classes ED Dependency

Block until writedef call(env) res = Response.new controller.response = res Thread.new { controller.index } res.stream.await [res.status, res.headers, res.stream]end

Block

Page 85: Realtime Rails Four2012.rubyworld-conf.org/files/slides/rwc2012_A-6.pdfAllow concurrency (enable) Loading Code isn’t Thread-safe* Preload Frameworks ED Cache classes ED Dependency

Blocking Bufferclass Buffer def initialize @latch = Latch.new @buffer = Queue.new end

def await # wait for write @latch.await end

def write(str) @latch.release @buffer << str endend

Page 86: Realtime Rails Four2012.rubyworld-conf.org/files/slides/rwc2012_A-6.pdfAllow concurrency (enable) Loading Code isn’t Thread-safe* Preload Frameworks ED Cache classes ED Dependency

Blocking Bufferclass Buffer def initialize @latch = Latch.new @buffer = Queue.new end

def await # wait for write @latch.await end

def write(str) @latch.release @buffer << str endend

`call` blocks here

Page 87: Realtime Rails Four2012.rubyworld-conf.org/files/slides/rwc2012_A-6.pdfAllow concurrency (enable) Loading Code isn’t Thread-safe* Preload Frameworks ED Cache classes ED Dependency

Blocking Bufferclass Buffer def initialize @latch = Latch.new @buffer = Queue.new end

def await # wait for write @latch.await end

def write(str) @latch.release @buffer << str endend

`write` unblocks

Page 88: Realtime Rails Four2012.rubyworld-conf.org/files/slides/rwc2012_A-6.pdfAllow concurrency (enable) Loading Code isn’t Thread-safe* Preload Frameworks ED Cache classes ED Dependency

What can we do?

Page 89: Realtime Rails Four2012.rubyworld-conf.org/files/slides/rwc2012_A-6.pdfAllow concurrency (enable) Loading Code isn’t Thread-safe* Preload Frameworks ED Cache classes ED Dependency

Rails Internals

Page 90: Realtime Rails Four2012.rubyworld-conf.org/files/slides/rwc2012_A-6.pdfAllow concurrency (enable) Loading Code isn’t Thread-safe* Preload Frameworks ED Cache classes ED Dependency

Streaming ERB

Page 91: Realtime Rails Four2012.rubyworld-conf.org/files/slides/rwc2012_A-6.pdfAllow concurrency (enable) Loading Code isn’t Thread-safe* Preload Frameworks ED Cache classes ED Dependency

View Source

# encoding: utf-8

require 'erb'

doc = ERB.new '<%= hello %> world'puts doc.src

Page 92: Realtime Rails Four2012.rubyworld-conf.org/files/slides/rwc2012_A-6.pdfAllow concurrency (enable) Loading Code isn’t Thread-safe* Preload Frameworks ED Cache classes ED Dependency

Source

#coding:UTF-8_erbout = ''; _erbout.concat(( hello ).to_s); _erbout.concat " world"; _erbout.force_encoding(__ENCODING__)

Page 93: Realtime Rails Four2012.rubyworld-conf.org/files/slides/rwc2012_A-6.pdfAllow concurrency (enable) Loading Code isn’t Thread-safe* Preload Frameworks ED Cache classes ED Dependency

Control Outputclass MyERB < ERB def set_eoutvar(compiler, eoutvar = '_erbout') compiler.put_cmd = "#{eoutvar}.write" compiler.insert_cmd = "#{eoutvar}.write" compiler.pre_cmd = [] compiler.post_cmd = [] endend

doc = MyERB.new '<%= hello %> world', nil, nil, '$stdout'puts doc.src

Page 94: Realtime Rails Four2012.rubyworld-conf.org/files/slides/rwc2012_A-6.pdfAllow concurrency (enable) Loading Code isn’t Thread-safe* Preload Frameworks ED Cache classes ED Dependency

Source

#coding:UTF-8$stdout.write(( hello ).to_s); $stdout.write " world"

Page 95: Realtime Rails Four2012.rubyworld-conf.org/files/slides/rwc2012_A-6.pdfAllow concurrency (enable) Loading Code isn’t Thread-safe* Preload Frameworks ED Cache classes ED Dependency

$ ruby test.rbhello world$

Page 96: Realtime Rails Four2012.rubyworld-conf.org/files/slides/rwc2012_A-6.pdfAllow concurrency (enable) Loading Code isn’t Thread-safe* Preload Frameworks ED Cache classes ED Dependency

Web Apps

Page 97: Realtime Rails Four2012.rubyworld-conf.org/files/slides/rwc2012_A-6.pdfAllow concurrency (enable) Loading Code isn’t Thread-safe* Preload Frameworks ED Cache classes ED Dependency

Infinite Streams

Page 98: Realtime Rails Four2012.rubyworld-conf.org/files/slides/rwc2012_A-6.pdfAllow concurrency (enable) Loading Code isn’t Thread-safe* Preload Frameworks ED Cache classes ED Dependency

Server Sent Events

Page 99: Realtime Rails Four2012.rubyworld-conf.org/files/slides/rwc2012_A-6.pdfAllow concurrency (enable) Loading Code isn’t Thread-safe* Preload Frameworks ED Cache classes ED Dependency

SSE ResponseHTTP/1.1 200 OKX-Frame-Options: SAMEORIGINX-XSS-Protection: 1; mode=blockX-Content-Type-Options: nosniffContent-Type: text/event-streamTransfer-Encoding: chunked

event: pingdata: {"ping":"2012-10-06T21:44:41-07:00"}

event: reloaddata: {"changed":["/Users/aaron/git/lolwut/app/views/users/"]}

Page 100: Realtime Rails Four2012.rubyworld-conf.org/files/slides/rwc2012_A-6.pdfAllow concurrency (enable) Loading Code isn’t Thread-safe* Preload Frameworks ED Cache classes ED Dependency

SSE ResponseHTTP/1.1 200 OKX-Frame-Options: SAMEORIGINX-XSS-Protection: 1; mode=blockX-Content-Type-Options: nosniffContent-Type: text/event-streamTransfer-Encoding: chunked

event: pingdata: {"ping":"2012-10-06T21:44:41-07:00"}

event: reloaddata: {"changed":["/Users/aaron/git/lolwut/app/views/users/"]}

Page 101: Realtime Rails Four2012.rubyworld-conf.org/files/slides/rwc2012_A-6.pdfAllow concurrency (enable) Loading Code isn’t Thread-safe* Preload Frameworks ED Cache classes ED Dependency

SSE ResponseHTTP/1.1 200 OKX-Frame-Options: SAMEORIGINX-XSS-Protection: 1; mode=blockX-Content-Type-Options: nosniffContent-Type: text/event-streamTransfer-Encoding: chunked

event: pingdata: {"ping":"2012-10-06T21:44:41-07:00"}

event: reloaddata: {"changed":["/Users/aaron/git/lolwut/app/views/users/"]}

Page 102: Realtime Rails Four2012.rubyworld-conf.org/files/slides/rwc2012_A-6.pdfAllow concurrency (enable) Loading Code isn’t Thread-safe* Preload Frameworks ED Cache classes ED Dependency

SSE ResponseHTTP/1.1 200 OKX-Frame-Options: SAMEORIGINX-XSS-Protection: 1; mode=blockX-Content-Type-Options: nosniffContent-Type: text/event-streamTransfer-Encoding: chunked

event: pingdata: {"ping":"2012-10-06T21:44:41-07:00"}

event: reloaddata: {"changed":["/Users/aaron/git/lolwut/app/views/users/"]}

Page 103: Realtime Rails Four2012.rubyworld-conf.org/files/slides/rwc2012_A-6.pdfAllow concurrency (enable) Loading Code isn’t Thread-safe* Preload Frameworks ED Cache classes ED Dependency

Client SidejQuery(document).ready(function() { setTimeout(function() { var source = new EventSource('/control');

// if we get a reload command, reload the page source.addEventListener('reload', function(e) { window.location.reload(); }); }, 1);});

Page 104: Realtime Rails Four2012.rubyworld-conf.org/files/slides/rwc2012_A-6.pdfAllow concurrency (enable) Loading Code isn’t Thread-safe* Preload Frameworks ED Cache classes ED Dependency

Client SidejQuery(document).ready(function() { setTimeout(function() { var source = new EventSource('/control');

// if we get a reload command, reload the page source.addEventListener('reload', function(e) { window.location.reload(); }); }, 1);});

Page 105: Realtime Rails Four2012.rubyworld-conf.org/files/slides/rwc2012_A-6.pdfAllow concurrency (enable) Loading Code isn’t Thread-safe* Preload Frameworks ED Cache classes ED Dependency

Client SidejQuery(document).ready(function() { setTimeout(function() { var source = new EventSource('/control');

// if we get a reload command, reload the page source.addEventListener('reload', function(e) { window.location.reload(); }); }, 1);});

Page 106: Realtime Rails Four2012.rubyworld-conf.org/files/slides/rwc2012_A-6.pdfAllow concurrency (enable) Loading Code isn’t Thread-safe* Preload Frameworks ED Cache classes ED Dependency

Client SidejQuery(document).ready(function() { setTimeout(function() { var source = new EventSource('/control');

// if we get a reload command, reload the page source.addEventListener('reload', function(e) { window.location.reload(); }); }, 1);});

Page 107: Realtime Rails Four2012.rubyworld-conf.org/files/slides/rwc2012_A-6.pdfAllow concurrency (enable) Loading Code isn’t Thread-safe* Preload Frameworks ED Cache classes ED Dependency

Real-Time BrowserCommunication

Page 108: Realtime Rails Four2012.rubyworld-conf.org/files/slides/rwc2012_A-6.pdfAllow concurrency (enable) Loading Code isn’t Thread-safe* Preload Frameworks ED Cache classes ED Dependency
Page 109: Realtime Rails Four2012.rubyworld-conf.org/files/slides/rwc2012_A-6.pdfAllow concurrency (enable) Loading Code isn’t Thread-safe* Preload Frameworks ED Cache classes ED Dependency

Puma

BrowserFS-Events

FS Events

Page 110: Realtime Rails Four2012.rubyworld-conf.org/files/slides/rwc2012_A-6.pdfAllow concurrency (enable) Loading Code isn’t Thread-safe* Preload Frameworks ED Cache classes ED Dependency

Puma

BrowserFS-Events

FS Events

Page 111: Realtime Rails Four2012.rubyworld-conf.org/files/slides/rwc2012_A-6.pdfAllow concurrency (enable) Loading Code isn’t Thread-safe* Preload Frameworks ED Cache classes ED Dependency

Puma

BrowserFS-Events

FS Events

Page 112: Realtime Rails Four2012.rubyworld-conf.org/files/slides/rwc2012_A-6.pdfAllow concurrency (enable) Loading Code isn’t Thread-safe* Preload Frameworks ED Cache classes ED Dependency

Puma

BrowserFS-Events

FS Events

Page 113: Realtime Rails Four2012.rubyworld-conf.org/files/slides/rwc2012_A-6.pdfAllow concurrency (enable) Loading Code isn’t Thread-safe* Preload Frameworks ED Cache classes ED Dependency

Puma

BrowserConsole

DRB

DB Events

Page 114: Realtime Rails Four2012.rubyworld-conf.org/files/slides/rwc2012_A-6.pdfAllow concurrency (enable) Loading Code isn’t Thread-safe* Preload Frameworks ED Cache classes ED Dependency

Puma

BrowserConsole

DRB

DB Events

Socket

Page 115: Realtime Rails Four2012.rubyworld-conf.org/files/slides/rwc2012_A-6.pdfAllow concurrency (enable) Loading Code isn’t Thread-safe* Preload Frameworks ED Cache classes ED Dependency

Other Input Sources

❤ Embedded systems (sausage box)❤ Telephony (twilio)❤ Other users (chat systems)

Page 116: Realtime Rails Four2012.rubyworld-conf.org/files/slides/rwc2012_A-6.pdfAllow concurrency (enable) Loading Code isn’t Thread-safe* Preload Frameworks ED Cache classes ED Dependency

Thread Safety

P72NStreaming

Page 117: Realtime Rails Four2012.rubyworld-conf.org/files/slides/rwc2012_A-6.pdfAllow concurrency (enable) Loading Code isn’t Thread-safe* Preload Frameworks ED Cache classes ED Dependency

Cores are increasing.

Page 118: Realtime Rails Four2012.rubyworld-conf.org/files/slides/rwc2012_A-6.pdfAllow concurrency (enable) Loading Code isn’t Thread-safe* Preload Frameworks ED Cache classes ED Dependency

We need to utilize the entire machine

Page 119: Realtime Rails Four2012.rubyworld-conf.org/files/slides/rwc2012_A-6.pdfAllow concurrency (enable) Loading Code isn’t Thread-safe* Preload Frameworks ED Cache classes ED Dependency

High latency clients are increasing.

Page 120: Realtime Rails Four2012.rubyworld-conf.org/files/slides/rwc2012_A-6.pdfAllow concurrency (enable) Loading Code isn’t Thread-safe* Preload Frameworks ED Cache classes ED Dependency

Patience is decreasing.

Page 121: Realtime Rails Four2012.rubyworld-conf.org/files/slides/rwc2012_A-6.pdfAllow concurrency (enable) Loading Code isn’t Thread-safe* Preload Frameworks ED Cache classes ED Dependency

Lie.Using cached data

Page 122: Realtime Rails Four2012.rubyworld-conf.org/files/slides/rwc2012_A-6.pdfAllow concurrency (enable) Loading Code isn’t Thread-safe* Preload Frameworks ED Cache classes ED Dependency

Cheat.Updating partial parts of the page

Page 123: Realtime Rails Four2012.rubyworld-conf.org/files/slides/rwc2012_A-6.pdfAllow concurrency (enable) Loading Code isn’t Thread-safe* Preload Frameworks ED Cache classes ED Dependency

Steal.Move computations to client side via JS

Page 124: Realtime Rails Four2012.rubyworld-conf.org/files/slides/rwc2012_A-6.pdfAllow concurrency (enable) Loading Code isn’t Thread-safe* Preload Frameworks ED Cache classes ED Dependency

Lie.Cheat.Steal.

Page 125: Realtime Rails Four2012.rubyworld-conf.org/files/slides/rwc2012_A-6.pdfAllow concurrency (enable) Loading Code isn’t Thread-safe* Preload Frameworks ED Cache classes ED Dependency

Be GoodEngineers

Page 126: Realtime Rails Four2012.rubyworld-conf.org/files/slides/rwc2012_A-6.pdfAllow concurrency (enable) Loading Code isn’t Thread-safe* Preload Frameworks ED Cache classes ED Dependency

THANK YOU

Page 127: Realtime Rails Four2012.rubyworld-conf.org/files/slides/rwc2012_A-6.pdfAllow concurrency (enable) Loading Code isn’t Thread-safe* Preload Frameworks ED Cache classes ED Dependency

Questions?