merb day keynote

148
Merb 2.0 The long march into the future

Upload: yehuda-katz

Post on 18-May-2015

4.954 views

Category:

Technology


3 download

TRANSCRIPT

Page 1: Merb Day Keynote

Merb 2.0

The long march into the future

Page 2: Merb Day Keynote

Core Merb Principles

Page 3: Merb Day Keynote

In Depth

Page 4: Merb Day Keynote

Performance

Page 5: Merb Day Keynote

Requests Per Second

Page 6: Merb Day Keynote

Thin Mongrel

Page 7: Merb Day Keynote

run proc do |env| [ 200, {"Content-Type" => "text/html"}, "Hello from rack" ]end

Page 8: Merb Day Keynote

class QuickApp def call(env) [ 200, {"Content-Type" => "text/html"}, "Hello from rack" ] endend

run QuickApp.new

Page 9: Merb Day Keynote

class QuickApp def call(env) [ 200, {"Content-Type" => "text/html"}, "Hello from rack" ] endend

run QuickApp.new

Page 10: Merb Day Keynote

Thin Mongrel

Page 11: Merb Day Keynote

match("/router").defer_to do |req, res| [ 200, {"Content-Type" => "text/html"}, "Hello" ]end

Page 12: Merb Day Keynote

Thin Mongrel

Page 13: Merb Day Keynote

class MyApp < Application def string "String" end end

Page 14: Merb Day Keynote

class MyApp < Application def string "String" end end

Page 15: Merb Day Keynote

Thin Mongrel

Page 16: Merb Day Keynote

class MyApp < Application

def index render end def string "String" end end

Page 17: Merb Day Keynote

class MyApp < Application

def index render end def string "String" end end

Page 18: Merb Day Keynote

Close to the metal as possible

Page 19: Merb Day Keynote

Close to the metal as you want

Page 20: Merb Day Keynote

Performance Testing

Page 21: Merb Day Keynote

KCacheGrind

Page 22: Merb Day Keynote

use Merb::Rack::Profile

Page 23: Merb Day Keynote

profile/url/callgrind.out.time

Page 24: Merb Day Keynote

5% or greater

Page 25: Merb Day Keynote

10% or greater

Page 26: Merb Day Keynote

Merb::RenderMixin::_get_layout10.05 %

10% or greater

Page 27: Merb Day Keynote

Mini-demo

Page 28: Merb Day Keynote

Concurrency

Page 29: Merb Day Keynote

0

4

8

12

16

20

1 2 4 8 16 32

Ideal concurrency curve

Page 30: Merb Day Keynote

1 request in 16ms (16ms/req)

Page 31: Merb Day Keynote

2 requests in 16ms (8ms/req)

Page 32: Merb Day Keynote

4 requests in 16ms (4ms/req)

Page 33: Merb Day Keynote

8 requests in 16ms (2ms/req)

Page 34: Merb Day Keynote

16 requests in 16ms (1ms/req)

Page 35: Merb Day Keynote

32 requests in 16ms (2req/ms)

Page 36: Merb Day Keynote

0

4

8

12

16

20

1 2 4 8 16 32

Ideal concurrency curve

Page 37: Merb Day Keynote

0

3.75

7.50

11.25

15.00

1 2 4 8 16 32

Chart 10

Merb MRI concurrency curve

Page 38: Merb Day Keynote

0

3.75

7.50

11.25

15.00

1 2 4 8 16 32

Chart 12

Merb JRuby (Mongrel) concurrency curve

Page 39: Merb Day Keynote

0

3.75

7.50

11.25

15.00

1 2 4 8 16 32 64 128 256

Chart 13

Merb Glassfish concurrency curve

Page 40: Merb Day Keynote

0

3.75

7.50

11.25

15.00

1 2 4 8 16 32 64 128 256

Chart 13

Not ideal

Page 41: Merb Day Keynote

0

3.75

7.50

11.25

15.00

1 2 4 8 16 32 64 128 256

Chart 13

Not ideal

Page 42: Merb Day Keynote

0

3.75

7.50

11.25

15.00

1 2 4 8 16 32 64 128 256

Chart 13

Not ideal (but it works)

Page 43: Merb Day Keynote

0

3.75

7.50

11.25

15.00

1 2 4 8 16 32 64 128 256

Chart 13

Not ideal (but it works)

Page 44: Merb Day Keynote

Threadsafety

Page 45: Merb Day Keynote

Merb::Config[:use_mutex]

Page 46: Merb Day Keynote

class User cattr_accessor :currentend

class Foo < Merb::Controller before do User.current = session.user endend

Page 47: Merb Day Keynote

class User cattr_accessor :currentend

class Foo < Merb::Controller before do User.current = session.user endend

FAIL

Page 48: Merb Day Keynote

Shared state hurts puppies

Page 49: Merb Day Keynote

Solutions

Page 50: Merb Day Keynote

Thread-local

Page 51: Merb Day Keynote

class User def self.current=(user) Thread.current[:user] = user end def self.current Thread.current[:user] endend

class Foo < Merb::Controller before do User.current = session.user endend

Page 52: Merb Day Keynote

Using a Hash across threads

Page 53: Merb Day Keynote

Hash {:x => 5}

Page 54: Merb Day Keynote

Thread 1 Thread 2

Hash {:x => 5}

Page 55: Merb Day Keynote

Thread 1 Thread 2

Hash {:x => 5}

Page 56: Merb Day Keynote

Thread 1 Thread 2

Read x

Hash {:x => 5}

Page 57: Merb Day Keynote

Thread 1 Thread 2

Read x Write x=”1”

Hash {:x => 5}

Page 58: Merb Day Keynote

Thread 1 Thread 2

Read x Write x=”1”

clear x

Hash {:x => 5}

Page 59: Merb Day Keynote

Thread 1 Thread 2

Read x Write x=”1”

clear x

is there an x?

Hash {:x => 5}

Page 60: Merb Day Keynote

Thread 1 Thread 2

Read x Write x=”1”

clear x

is there an x?

x = 1no? return nil

Hash {:x => 5}

Page 61: Merb Day Keynote

Mutex

Page 62: Merb Day Keynote

Hash {:x => 5}

Page 63: Merb Day Keynote

Thread 1 Thread 2

Hash {:x => 5}

Page 64: Merb Day Keynote

Thread 1 Thread 2

Read x

is there an x?

yes? return 5

Hash {:x => 5}

Page 65: Merb Day Keynote

Thread 1 Thread 2

Write x=”1”

clear x

x = 1

Read x

is there an x?

yes? return 5

Hash {:x => 5}

Page 66: Merb Day Keynote

Hash {:x => 5}

Page 67: Merb Day Keynote

Thread 1 Thread 2

Hash {:x => 5}

Page 68: Merb Day Keynote

Thread 1 Thread 2

Write x=”1”

clear x

x = 1

Hash {:x => 5}

Page 69: Merb Day Keynote

Thread 1 Thread 2

Write x=”1”

clear x

x = 1

Read x

is there an x?

yes? return 1

Hash {:x => 5}

Page 70: Merb Day Keynote

Mutexes make non-atomic operations atomic

Page 71: Merb Day Keynote

Modularity

Page 72: Merb Day Keynote

merb_gems_version = "1.0.4"dm_gems_version = "0.9.7"

dependency "merb-action-args", merb_gems_versiondependency "merb-assets", merb_gems_version dependency "merb-cache", merb_gems_version dependency "merb-helpers", merb_gems_version dependency "merb-mailer", merb_gems_version dependency "merb-slices", merb_gems_version dependency "merb-auth-core", merb_gems_versiondependency "merb-auth-more", merb_gems_versiondependency "merb-auth-slice-password", merb_gems_versiondependency "merb-param-protection", merb_gems_versiondependency "merb-exceptions", merb_gems_version dependency "dm-core", dm_gems_version dependency "dm-aggregates", dm_gems_version dependency "dm-migrations", dm_gems_version dependency "dm-timestamps", dm_gems_version dependency "dm-types", dm_gems_version dependency "dm-validations", dm_gems_version

Page 73: Merb Day Keynote

merb_gems_version = "1.0.4"dm_gems_version = "0.9.7"

dependency "merb-action-args", merb_gems_versiondependency "merb-assets", merb_gems_version dependency "merb-cache", merb_gems_version dependency "merb-helpers", merb_gems_version dependency "merb-mailer", merb_gems_version dependency "merb-slices", merb_gems_version dependency "merb-auth-core", merb_gems_versiondependency "merb-auth-more", merb_gems_versiondependency "merb-auth-slice-password", merb_gems_versiondependency "merb-param-protection", merb_gems_versiondependency "merb-exceptions", merb_gems_version dependency "dm-core", dm_gems_version dependency "dm-aggregates", dm_gems_version dependency "dm-migrations", dm_gems_version dependency "dm-timestamps", dm_gems_version dependency "dm-types", dm_gems_version dependency "dm-validations", dm_gems_version

Page 74: Merb Day Keynote

merb_gems_version = "1.0.4"dm_gems_version = "0.9.7"

dependency "merb-action-args", merb_gems_versiondependency "merb-assets", merb_gems_version dependency "merb-cache", merb_gems_version dependency "merb-helpers", merb_gems_version dependency "merb-mailer", merb_gems_version dependency "merb-slices", merb_gems_version dependency "merb-auth-core", merb_gems_versiondependency "merb-auth-more", merb_gems_versiondependency "merb-auth-slice-password", merb_gems_versiondependency "merb-param-protection", merb_gems_versiondependency "merb-exceptions", merb_gems_version dependency "dm-core", dm_gems_version dependency "dm-aggregates", dm_gems_version dependency "dm-migrations", dm_gems_version dependency "dm-timestamps", dm_gems_version dependency "dm-types", dm_gems_version dependency "dm-validations", dm_gems_version

Page 75: Merb Day Keynote

merb_gems_version = "1.0.4"dm_gems_version = "0.9.7"

dependency "merb-action-args", merb_gems_versiondependency "merb-assets", merb_gems_version dependency "merb-cache", merb_gems_version dependency "merb-helpers", merb_gems_version dependency "merb-mailer", merb_gems_version dependency "merb-slices", merb_gems_version dependency "merb-auth-core", merb_gems_versiondependency "merb-auth-more", merb_gems_versiondependency "merb-auth-slice-password", merb_gems_versiondependency "merb-param-protection", merb_gems_versiondependency "merb-exceptions", merb_gems_version dependency "dm-core", dm_gems_version dependency "dm-aggregates", dm_gems_version dependency "dm-migrations", dm_gems_version dependency "dm-timestamps", dm_gems_version dependency "dm-types", dm_gems_version dependency "dm-validations", dm_gems_version

JRuby 1.1.4

Page 76: Merb Day Keynote

merb_gems_version = "1.0.4"dm_gems_version = "0.9.7"

dependency "merb-action-args", merb_gems_versiondependency "merb-assets", merb_gems_version dependency "merb-cache", merb_gems_version dependency "merb-helpers", merb_gems_version dependency "merb-mailer", merb_gems_version dependency "merb-slices", merb_gems_version dependency "merb-auth-core", merb_gems_versiondependency "merb-auth-more", merb_gems_versiondependency "merb-auth-slice-password", merb_gems_versiondependency "merb-param-protection", merb_gems_versiondependency "merb-exceptions", merb_gems_version dependency "dm-core", dm_gems_version dependency "dm-aggregates", dm_gems_version dependency "dm-migrations", dm_gems_version dependency "dm-timestamps", dm_gems_version dependency "dm-types", dm_gems_version dependency "dm-validations", dm_gems_version

Page 77: Merb Day Keynote

merb_gems_version = "1.0.4"dm_gems_version = "0.9.7"

dependency "merb-action-args", merb_gems_versiondependency "merb-assets", merb_gems_version dependency "merb-cache", merb_gems_version dependency "merb-helpers", merb_gems_version dependency "merb-mailer", merb_gems_version dependency "merb-slices", merb_gems_version dependency "merb-auth-core", merb_gems_versiondependency "merb-auth-more", merb_gems_versiondependency "merb-auth-slice-password", merb_gems_versiondependency "merb-param-protection", merb_gems_versiondependency "merb-exceptions", merb_gems_version dependency "dm-core", dm_gems_version dependency "dm-aggregates", dm_gems_version dependency "dm-migrations", dm_gems_version dependency "dm-timestamps", dm_gems_version dependency "dm-types", dm_gems_version dependency "dm-validations", dm_gems_version

JRuby 1.1.5+

Page 78: Merb Day Keynote

@overridable

Page 79: Merb Day Keynote

# This is a stub method so plugins can # implement param filtering if they want.## ==== Parameters# params<Hash{Symbol => String}>:: # A list of params## ==== Returns# Hash{Symbol => String}:: # A new list of params, filtered as desired# # :api: plugin# @overridabledef self._filter_params(params) paramsend

Page 80: Merb Day Keynote

class Articles < Application params_accessible :article => [:title, :body]end

Page 81: Merb Day Keynote

class Articles < Application params_accessible :article => [:title, :body]end

Page 82: Merb Day Keynote

class Articles < Application def self._filter_params(params) # deep_clone ret = Marshal.load(Marshal.dump(params))

ret[:post].reject! do |k,v| !k.in?(:title, :body) end endend

Page 83: Merb Day Keynote

class Articles < Application def self._filter_params(params) # deep_clone ret = Marshal.load(Marshal.dump(params))

ret[:post].reject! do |k,v| !k.in?(:title, :body) end endend

Page 84: Merb Day Keynote

# :api: public# @overridabledef _template_location(ctx, type, ctrlr) _conditionally_append_extension( ctrlr ? "#{ctrlr}/#{ctx}" : "#{ctx}", type)end

Page 85: Merb Day Keynote

class Articles < Application def self._template_location( ctx, type, ctrlr)

"#{ctrlr}.#{ctx}.#{type}" endend

Page 86: Merb Day Keynote

class Articles < Application def self._template_location( ctx, type, ctrlr)

"#{ctrlr}.#{ctx}.#{type}" endend

Page 87: Merb Day Keynote

class Articles < Application def self._template_location( ctx, type, ctrlr)

"#{ctrlr}.#{ctx}.#{type}" endend

controller = “layout”

Page 88: Merb Day Keynote

class Articles < Application self.template_roots = [ [ Merb.root / "app" / "views", :_template_location ], [ Merb.root / "my_views", :_my_template_location ] ]end

Page 89: Merb Day Keynote

>> MerbAuthSlicePassword::Sessions.template_roots#=> [["/Users/wycats/Code/wycats/test/awesome/app/views", :_template_location], ["/Library/Ruby/Gems/1.8/gems/merb-auth-slice-password-1.0.4/app/views", :_slice_template_location], ["/Users/wycats/Code/wycats/test/awesome/slices/merb-auth-slice-password/app/views", :_slice_template_location]]

Page 90: Merb Day Keynote

>> MerbAuthSlicePassword::Sessions.template_roots#=> [["/Users/wycats/Code/wycats/test/awesome/app/views", :_template_location], ["/Library/Ruby/Gems/1.8/gems/merb-auth-slice-password-1.0.4/app/views", :_slice_template_location], ["/Users/wycats/Code/wycats/test/awesome/slices/merb-auth-slice-password/app/views", :_slice_template_location]]

Page 91: Merb Day Keynote

>> MerbAuthSlicePassword::Sessions.template_roots#=> [["/Users/wycats/Code/wycats/test/awesome/app/views", :_template_location], ["/Library/Ruby/Gems/1.8/gems/merb-auth-slice-password-1.0.4/app/views", :_slice_template_location], ["/Users/wycats/Code/wycats/test/awesome/slices/merb-auth-slice-password/app/views", :_slice_template_location]]

Page 92: Merb Day Keynote

>> MerbAuthSlicePassword::Sessions.template_roots#=> [["/Users/wycats/Code/wycats/test/awesome/app/views", :_template_location], ["/Library/Ruby/Gems/1.8/gems/merb-auth-slice-password-1.0.4/app/views", :_slice_template_location], ["/Users/wycats/Code/wycats/test/awesome/slices/merb-auth-slice-password/app/views", :_slice_template_location]]

Page 93: Merb Day Keynote

>> MerbAuthSlicePassword::Sessions.template_roots#=> [["/Users/wycats/Code/wycats/test/awesome/app/views", :_template_location], ["/Library/Ruby/Gems/1.8/gems/merb-auth-slice-password-1.0.4/app/views", :_slice_template_location], ["/Users/wycats/Code/wycats/test/awesome/slices/merb-auth-slice-password/app/views", :_slice_template_location]]

Page 94: Merb Day Keynote

>> MerbAuthSlicePassword::Sessions.template_roots#=> [["/Users/wycats/Code/wycats/test/awesome/app/views", :_template_location], ["/Library/Ruby/Gems/1.8/gems/merb-auth-slice-password-1.0.4/app/views", :_slice_template_location], ["/Users/wycats/Code/wycats/test/awesome/slices/merb-auth-slice-password/app/views", :_slice_template_location]]

Page 95: Merb Day Keynote

>> MerbAuthSlicePassword::Sessions.template_roots#=> [["/Users/wycats/Code/wycats/test/awesome/app/views", :_template_location], ["/Library/Ruby/Gems/1.8/gems/merb-auth-slice-password-1.0.4/app/views", :_slice_template_location], ["/Users/wycats/Code/wycats/test/awesome/slices/merb-auth-slice-password/app/views", :_slice_template_location]]

Page 96: Merb Day Keynote

def _slice_template_location(ctx, type, ctrlr) if ctrlr && ctrlr.include?('/') # skip first segment if given (which is the module name) segments = ctrlr.split('/') "#{segments[1,segments.length-1].join('/')}/#{ctx}.#{type}" else # default template location logic _template_location(ctx, type, ctrlr) endend

Page 97: Merb Day Keynote

Templates

Page 98: Merb Day Keynote

def load_template_io(path) file = Dir[ "#{path}.{#{template_extensions.join(',')}}" ].first File.open(file, "r") if fileend

Page 99: Merb Day Keynote

def load_template_io(path) templates = { Merb.root / "app" / "views" / "template_io" / "index.html.erb" => "Hello world", Merb.root / "app" / "views" / "template_io" / "two.html.erb" => "Two" }

if templates[path + ".erb"] VirtualFile.new(templates[path + ".erb"], path + ".erb") else file = Dir[ "#{path}.{#{template_extensions.join(',')}}" ].first File.open(file, "r") if file endend

Page 100: Merb Day Keynote

Merb::Router.prepare {default_routes}

class TemplateIo < Merb::Controller def index render end def two render endend

Page 101: Merb Day Keynote

Quick demo

Page 102: Merb Day Keynote

Good Ruby citizen

Page 103: Merb Day Keynote

Rubygems

Page 104: Merb Day Keynote

Rubygems :(

Page 105: Merb Day Keynote

Rubygems -- but getting :)

Page 106: Merb Day Keynote

Working with community == helping the community

Page 107: Merb Day Keynote

Rack

Page 108: Merb Day Keynote

Rack middleware

Page 109: Merb Day Keynote

Where is this going?

Page 110: Merb Day Keynote

Apps as a first-class concept

Page 111: Merb Day Keynote

module MyApp class TemplateIo < Application def index render end def two render end endend

Page 112: Merb Day Keynote

module MyApp class TemplateIo < Application def index render end def two render end endend

Page 113: Merb Day Keynote

module MyApp class TemplateIo < Application def index render end def two render end endend

MyApp::Application

Page 114: Merb Day Keynote

module MyApp extend Merb::App mount ::Blog, :at => "/blog" Config[:framework] = flatend

Page 115: Merb Day Keynote

Blog::Config[:log_delimiter] = "BLOG: "

Page 116: Merb Day Keynote

Admin Application/Framework

Page 117: Merb Day Keynote

CMS Application

Page 118: Merb Day Keynote

DB Admin Application

Page 119: Merb Day Keynote

Slices on Steroids

Page 120: Merb Day Keynote

Resources as a first-class concept

Page 121: Merb Day Keynote

module MyApp class Resource < Merb::Resource def list(klass) klass.all end def get(klass, ids) klass.get(ids) end def authorized?(namespace, *args) user == "wycats" end

def user request.session.user end endend

Page 122: Merb Day Keynote
Page 123: Merb Day Keynote

Why?

Page 124: Merb Day Keynote

DRYing up common idioms

Page 125: Merb Day Keynote

Increasing flexibility (where needed)

Page 126: Merb Day Keynote

Core principle:Simple cases can’t get harder

Page 127: Merb Day Keynote

Further improve merb server

Page 128: Merb Day Keynote

Short term

Page 129: Merb Day Keynote

Long term

Page 130: Merb Day Keynote

Dynamic worker pools

Page 131: Merb Day Keynote

Remove need for nginx

Page 132: Merb Day Keynote

Self-managing cluster

Page 133: Merb Day Keynote

Additional modules

Page 134: Merb Day Keynote

i18n

Page 135: Merb Day Keynote

l10n

Page 136: Merb Day Keynote

Feed syndication

Page 137: Merb Day Keynote

Flat pages

Page 138: Merb Day Keynote

More powerful router

Page 139: Merb Day Keynote

Router directly to a view

Page 140: Merb Day Keynote

even better resource()

Page 141: Merb Day Keynote

Framework for OSS Apps

Page 142: Merb Day Keynote

Authentication

Page 143: Merb Day Keynote

User Management

Page 144: Merb Day Keynote

Authorization

Page 145: Merb Day Keynote

Note:Communication primitives

Page 146: Merb Day Keynote

Tailored stacks

Page 147: Merb Day Keynote

Designers

Page 148: Merb Day Keynote

Web shops