+ All Categories
Home > Technology > Attributes Unwrapped: Lessons under the surface of active record

Attributes Unwrapped: Lessons under the surface of active record

Date post: 15-May-2015
Category:
Upload: toster
View: 1,001 times
Download: 1 times
Share this document with a friend
Description:
Ведущий разработчик Ruby on Rails (Rails Core member) Джон Лейтон не так давно работал над совершенствованием реализации работы с атрибутами в Active Record. Он расскажет о своем опыте работы над важной для производительности областью Rails, даст советы и расскажет о техниках, которые могут быть применены к собственным приложениям слушателей. Говоря о будущем, Джон также расскажет о своих идеях по изменению API работы с атрибутами в лучшую сторону; эти изменения могут появиться в Rails 4.0.
Popular Tags:
77
Attributes Unwrapped
Transcript
Page 1: Attributes Unwrapped: Lessons under the surface of active record

Attributes Unwrapped

Page 2: Attributes Unwrapped: Lessons under the surface of active record

@jonleighton

Page 3: Attributes Unwrapped: Lessons under the surface of active record
Page 4: Attributes Unwrapped: Lessons under the surface of active record

I lied to you

Page 5: Attributes Unwrapped: Lessons under the surface of active record
Page 6: Attributes Unwrapped: Lessons under the surface of active record

Measure

Page 7: Attributes Unwrapped: Lessons under the surface of active record

Measure

Refactor

Page 8: Attributes Unwrapped: Lessons under the surface of active record

Measure

Refactor

Optimise

Page 9: Attributes Unwrapped: Lessons under the surface of active record

LET’S DO SCIENCE

Page 10: Attributes Unwrapped: Lessons under the surface of active record

gem 'rails', '3.2.0'

require 'active_record'

ActiveRecord::Base

.establish_connection(

:adapter => 'sqlite3',

:database => ':memory:')

Page 11: Attributes Unwrapped: Lessons under the surface of active record

ActiveRecord::Schema.define do

create_table :posts do |t|

t.string :title

end

end

class Post < ActiveRecord::Base

end

p = Post.create(:title => "lol")

Page 12: Attributes Unwrapped: Lessons under the surface of active record

require 'benchmark'

n = 1_000_000

Benchmark.report(20) do |r|

r.report('attribute') do

n.times { p.title }

end

r.report('read_attribute') do

n.times { p[:title] }

end

end

Page 13: Attributes Unwrapped: Lessons under the surface of active record

attribute

read_attribute

1.09 s

2.87 s

Page 14: Attributes Unwrapped: Lessons under the surface of active record

gem install

benchmark_suite

Page 15: Attributes Unwrapped: Lessons under the surface of active record

require 'benchmark/ips'

Benchmark.ips do |r|

r.report('attribute') do

p.title

end

r.report('read_attribute') do

p[:title]

end

end

Page 16: Attributes Unwrapped: Lessons under the surface of active record

attribute

read_attribute

828,648

299,856

Page 17: Attributes Unwrapped: Lessons under the surface of active record

Ruby 1.9

Page 18: Attributes Unwrapped: Lessons under the surface of active record

Ruby 1.8

Page 19: Attributes Unwrapped: Lessons under the surface of active record

Ruby 1.8

oops!

Page 20: Attributes Unwrapped: Lessons under the surface of active record

define_method

Page 21: Attributes Unwrapped: Lessons under the surface of active record

method compilation

Page 22: Attributes Unwrapped: Lessons under the surface of active record
Page 23: Attributes Unwrapped: Lessons under the surface of active record
Page 24: Attributes Unwrapped: Lessons under the surface of active record

create_table :roflcopters do |t|

t.string " ROFL:ROFL:ROFL:ROFL"

t.string " _^____ "

t.string " L __/ []\ "

t.string "LOL===_ \ "

t.string " L \_________] "

t.string " I I "

t.string " --------/ "

end

Page 25: Attributes Unwrapped: Lessons under the surface of active record

if compilable?

class_eval <<-STR

def #{attr_name}

...

end

STR

else

define_method attr_name do

...

end

end

Page 26: Attributes Unwrapped: Lessons under the surface of active record

attr_name

=~

/\A[a-zA-Z_]\w*[!?=]?\z/

Page 27: Attributes Unwrapped: Lessons under the surface of active record

:title

=~

/\A[a-zA-Z_]\w*[!?=]?\z/

Page 28: Attributes Unwrapped: Lessons under the surface of active record

:title =~ /.../

# => true

Ruby 1.9

Page 29: Attributes Unwrapped: Lessons under the surface of active record

Ruby 1.8

:title =~ /.../

# => false

Page 30: Attributes Unwrapped: Lessons under the surface of active record

def __temp__

...

end

alias "@#>" :__temp__

undef_method :__temp__

Page 31: Attributes Unwrapped: Lessons under the surface of active record

def __temp__

...

end

alias "@#>" :__temp__

undef_method :__temp__

DON'T USE THIS

Page 32: Attributes Unwrapped: Lessons under the surface of active record

API Changes

Page 33: Attributes Unwrapped: Lessons under the surface of active record
Page 34: Attributes Unwrapped: Lessons under the surface of active record

def title

self[:title].upcase

end

Page 35: Attributes Unwrapped: Lessons under the surface of active record

def title

super.upcase

end

Page 36: Attributes Unwrapped: Lessons under the surface of active record

module A

def foo

"bar"

end

end

Page 37: Attributes Unwrapped: Lessons under the surface of active record

class B

include A

def foo

super.upcase

end

end

Page 38: Attributes Unwrapped: Lessons under the surface of active record

Don’t fight Ruby

<3 <3 <3

Page 39: Attributes Unwrapped: Lessons under the surface of active record

#read_attribute

#[]

Page 40: Attributes Unwrapped: Lessons under the surface of active record

def read_attribute(name)

name = "_#{name}"

if respond_to?(name)

send(name)

else

# other stuff

end

end

Page 41: Attributes Unwrapped: Lessons under the surface of active record

Module.new

Page 42: Attributes Unwrapped: Lessons under the surface of active record

def read_attribute(name)

mod = self.class.methods_module

if mod.respond_to?(name)

mod.send(name, @attributes)

else

# other stuff

end

end

Page 43: Attributes Unwrapped: Lessons under the surface of active record

Module.new.respond_to?(:name)

# => true

Page 44: Attributes Unwrapped: Lessons under the surface of active record

Module.new { extend self }

Page 45: Attributes Unwrapped: Lessons under the surface of active record

Module.new { extend self }

mod.method_defined?(:name)

Page 46: Attributes Unwrapped: Lessons under the surface of active record

Module.new { extend self }

INSANE HACKmod.method_defined?(:name)

Page 47: Attributes Unwrapped: Lessons under the surface of active record

Still too slow☹

Page 48: Attributes Unwrapped: Lessons under the surface of active record

gem install

perftools.rb

Page 49: Attributes Unwrapped: Lessons under the surface of active record
Page 50: Attributes Unwrapped: Lessons under the surface of active record

if attr_name == 'id'

attr_name =

self.class.primary_key

end

Page 51: Attributes Unwrapped: Lessons under the surface of active record

No code is fasterthan no code

Page 52: Attributes Unwrapped: Lessons under the surface of active record

def title

cast @attributes['title']

end

Page 53: Attributes Unwrapped: Lessons under the surface of active record

def title

cast @attributes[:title]

end

Page 54: Attributes Unwrapped: Lessons under the surface of active record
Page 55: Attributes Unwrapped: Lessons under the surface of active record

class A

def initialize

@attributes = { :foo => 1 }

end

def foo

@attributes[:foo]

end

end

Page 56: Attributes Unwrapped: Lessons under the surface of active record

class B

def initialize

@attributes = { 'foo' => 1 }

end

def foo

@attributes['foo']

end

end

Page 57: Attributes Unwrapped: Lessons under the surface of active record

Benchmark.ips do |r|

r.report('symbol') { a.foo }

r.report('string') { b.foo }

end

Page 58: Attributes Unwrapped: Lessons under the surface of active record
Page 59: Attributes Unwrapped: Lessons under the surface of active record

code = "@attributes['foo']"

iseq =

RubyVM::InstructionSequence

.compile(code)

puts iseq.disassemble

Page 60: Attributes Unwrapped: Lessons under the surface of active record

trace 1

getinstancevariable :@attributes

putstring "foo"

opt_aref <ic:2>

leave

Page 61: Attributes Unwrapped: Lessons under the surface of active record

trace 1

getinstancevariable :@attributes

putobject :foo

opt_aref <ic:2>

leave

Page 62: Attributes Unwrapped: Lessons under the surface of active record

DEFINE_INSN

putstring

(VALUE str)

()

(VALUE val)

{

val = rb_str_resurrect(str);

}

Page 63: Attributes Unwrapped: Lessons under the surface of active record

DEFINE_INSN

putobject

(VALUE val)

()

(VALUE val)

{

/* */

}

Page 64: Attributes Unwrapped: Lessons under the surface of active record
Page 65: Attributes Unwrapped: Lessons under the surface of active record

code = "@attributes['foo']"

compiled =

Rubinius::Compiler

.compile_string(code)

puts compiled.decode

Page 66: Attributes Unwrapped: Lessons under the surface of active record

push_ivar 0

push_literal "foo"

string_dup

send_stack :[], 1

pop

push_true

ret

Page 67: Attributes Unwrapped: Lessons under the surface of active record

push_ivar 0

push_literal :foo

send_stack :[], 1

pop

push_true

ret

Page 68: Attributes Unwrapped: Lessons under the surface of active record
Page 69: Attributes Unwrapped: Lessons under the surface of active record

jruby --bytecode

-e "@attributes['foo']"

Page 70: Attributes Unwrapped: Lessons under the surface of active record

RubyString

Page 71: Attributes Unwrapped: Lessons under the surface of active record

RubyString

RubySymbol

Page 72: Attributes Unwrapped: Lessons under the surface of active record

Performance problemsare a code smell

Page 73: Attributes Unwrapped: Lessons under the surface of active record

Be a scientist

Page 74: Attributes Unwrapped: Lessons under the surface of active record

But...

Page 75: Attributes Unwrapped: Lessons under the surface of active record

Avoid roflscaling!

Page 76: Attributes Unwrapped: Lessons under the surface of active record

Thanks!IT'S OVER!

Page 77: Attributes Unwrapped: Lessons under the surface of active record

Thanks!IT'S OVER!

(♥ @tenderlove ♥)


Recommended