zomg why is this code so slow

277
Nokogiri のお母さん Thursday, November 11, 2010

Upload: aaron-patterson

Post on 07-Jul-2015

19.260 views

Category:

Technology


0 download

DESCRIPTION

My RubyConf 2010 talk

TRANSCRIPT

Page 1: ZOMG WHY IS THIS CODE SO SLOW

Nokogiri のお母さんThursday, November 11, 2010

Page 2: ZOMG WHY IS THIS CODE SO SLOW

@flavorjones

Thursday, November 11, 2010

Page 3: ZOMG WHY IS THIS CODE SO SLOW

ZOMG!!!!!

Thursday, November 11, 2010

Page 4: ZOMG WHY IS THIS CODE SO SLOW

HAPPY THURSDAY!!

Thursday, November 11, 2010

Page 5: ZOMG WHY IS THIS CODE SO SLOW

WELCOME TO RubyConf X!

Thursday, November 11, 2010

Page 6: ZOMG WHY IS THIS CODE SO SLOW

X-TREMERUBYCONF!!!!!

Thursday, November 11, 2010

Page 7: ZOMG WHY IS THIS CODE SO SLOW

Aaron Patterson

Thursday, November 11, 2010

Page 8: ZOMG WHY IS THIS CODE SO SLOW

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

Thursday, November 11, 2010

Page 9: ZOMG WHY IS THIS CODE SO SLOW

@tenderlove

Thursday, November 11, 2010

Page 11: ZOMG WHY IS THIS CODE SO SLOW

Thursday, November 11, 2010

Page 12: ZOMG WHY IS THIS CODE SO SLOW

ruby committer

Thursday, November 11, 2010

Page 13: ZOMG WHY IS THIS CODE SO SLOW

rails committer

Thursday, November 11, 2010

Page 14: ZOMG WHY IS THIS CODE SO SLOW

CommitterHOWTO

Thursday, November 11, 2010

Page 15: ZOMG WHY IS THIS CODE SO SLOW

Ruby

Thursday, November 11, 2010

Page 16: ZOMG WHY IS THIS CODE SO SLOW

Thursday, November 11, 2010

Page 17: ZOMG WHY IS THIS CODE SO SLOW

♥Thursday, November 11, 2010

Page 18: ZOMG WHY IS THIS CODE SO SLOW

Rails

Thursday, November 11, 2010

Page 19: ZOMG WHY IS THIS CODE SO SLOW

Thursday, November 11, 2010

Page 20: ZOMG WHY IS THIS CODE SO SLOW

♥Thursday, November 11, 2010

Page 21: ZOMG WHY IS THIS CODE SO SLOW

RubyConf

Thursday, November 11, 2010

Page 22: ZOMG WHY IS THIS CODE SO SLOW

Thursday, November 11, 2010

Page 23: ZOMG WHY IS THIS CODE SO SLOW

♥Thursday, November 11, 2010

Page 24: ZOMG WHY IS THIS CODE SO SLOW

WWFMD?Thursday, November 11, 2010

Page 25: ZOMG WHY IS THIS CODE SO SLOW

RubyConf 5k

Thursday, November 11, 2010

Page 26: ZOMG WHY IS THIS CODE SO SLOW

RUBYCONFFIVE THOUSAND

Thursday, November 11, 2010

Page 27: ZOMG WHY IS THIS CODE SO SLOW

Thursday, November 11, 2010

Page 28: ZOMG WHY IS THIS CODE SO SLOW

Thursday, November 11, 2010

Page 29: ZOMG WHY IS THIS CODE SO SLOW

ZOMG WHY IS THIS CODE SO SLOW?

Thursday, November 11, 2010

Page 30: ZOMG WHY IS THIS CODE SO SLOW

Performance

Thursday, November 11, 2010

Page 31: ZOMG WHY IS THIS CODE SO SLOW

Code Analysis

Thursday, November 11, 2010

Page 32: ZOMG WHY IS THIS CODE SO SLOW

Story Form

Thursday, November 11, 2010

Page 33: ZOMG WHY IS THIS CODE SO SLOW

Thursday, November 11, 2010

Page 34: ZOMG WHY IS THIS CODE SO SLOW

IRL

Tools

IRL

Theory

IRL

Thursday, November 11, 2010

Page 35: ZOMG WHY IS THIS CODE SO SLOW

ARel

Thursday, November 11, 2010

Page 36: ZOMG WHY IS THIS CODE SO SLOW

What is it?

Thursday, November 11, 2010

Page 37: ZOMG WHY IS THIS CODE SO SLOW

"Relational Algebra"

Thursday, November 11, 2010

Page 38: ZOMG WHY IS THIS CODE SO SLOW

AST Manipulation

Thursday, November 11, 2010

Page 39: ZOMG WHY IS THIS CODE SO SLOW

Statement

Column Sources

Table

Conditions

Thursday, November 11, 2010

Page 40: ZOMG WHY IS THIS CODE SO SLOW

Statement

Column Sources

Table

Conditions

Table 1 = 1

Thursday, November 11, 2010

Page 41: ZOMG WHY IS THIS CODE SO SLOW

AST Translation

Thursday, November 11, 2010

Page 42: ZOMG WHY IS THIS CODE SO SLOW

Statement

Column Sources

Table

Conditions

Table 1 = 1

Thursday, November 11, 2010

Page 43: ZOMG WHY IS THIS CODE SO SLOW

Statement

Column Sources

Table

Conditions

Table 1 = 1

Statement

Column Sources

Table

Conditions

Table 1 = 1

Thursday, November 11, 2010

Page 44: ZOMG WHY IS THIS CODE SO SLOW

SELECT COLUMN FROM TABLE, TABLE

WHERE 1 = 1

Thursday, November 11, 2010

Page 45: ZOMG WHY IS THIS CODE SO SLOW

Relationship with Rails

Thursday, November 11, 2010

Page 46: ZOMG WHY IS THIS CODE SO SLOW

ActiveRecord

User (YOU!)

ARel

Thursday, November 11, 2010

Page 47: ZOMG WHY IS THIS CODE SO SLOW

ActiveRecord

User (YOU!)

ARel

Records PLZ

SQL STMT

Thursday, November 11, 2010

Page 48: ZOMG WHY IS THIS CODE SO SLOW

Thursday, November 11, 2010

Page 49: ZOMG WHY IS THIS CODE SO SLOW

The More You Know™

Thursday, November 11, 2010

Page 50: ZOMG WHY IS THIS CODE SO SLOW

Getting Started

Thursday, November 11, 2010

Page 51: ZOMG WHY IS THIS CODE SO SLOW

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

Thursday, November 11, 2010

Page 52: ZOMG WHY IS THIS CODE SO SLOW

Rails

Thursday, November 11, 2010

Page 53: ZOMG WHY IS THIS CODE SO SLOW

Prepared Statement Caching

Thursday, November 11, 2010

Page 54: ZOMG WHY IS THIS CODE SO SLOW

Thursday, November 11, 2010

Page 55: ZOMG WHY IS THIS CODE SO SLOW

DEEPER UNDERSTANDING

REQUIRED

Thursday, November 11, 2010

Page 56: ZOMG WHY IS THIS CODE SO SLOW

ActiveRecord 5x slower than Rails

2.3.5

Thursday, November 11, 2010

Page 57: ZOMG WHY IS THIS CODE SO SLOW

http://bit.ly/omgslow

Thursday, November 11, 2010

Page 58: ZOMG WHY IS THIS CODE SO SLOW

5x Slower?!?

Thursday, November 11, 2010

Page 59: ZOMG WHY IS THIS CODE SO SLOW

WTF?

Thursday, November 11, 2010

Page 60: ZOMG WHY IS THIS CODE SO SLOW

Yes, 5x Slower

Thursday, November 11, 2010

Page 61: ZOMG WHY IS THIS CODE SO SLOW

What could possibly go wrong?

Thursday, November 11, 2010

Page 62: ZOMG WHY IS THIS CODE SO SLOW

Motivation

Thursday, November 11, 2010

Page 63: ZOMG WHY IS THIS CODE SO SLOW

Why do you care about speed?

Thursday, November 11, 2010

Page 64: ZOMG WHY IS THIS CODE SO SLOW

Scaling Ruby

Thursday, November 11, 2010

Page 65: ZOMG WHY IS THIS CODE SO SLOW

Thursday, November 11, 2010

Page 66: ZOMG WHY IS THIS CODE SO SLOW

Thursday, November 11, 2010

Page 67: ZOMG WHY IS THIS CODE SO SLOW

When should I make my code faster?

Thursday, November 11, 2010

Page 68: ZOMG WHY IS THIS CODE SO SLOW

When it isn't fast enough.

Thursday, November 11, 2010

Page 69: ZOMG WHY IS THIS CODE SO SLOW

What is"fast enough"?

Thursday, November 11, 2010

Page 70: ZOMG WHY IS THIS CODE SO SLOW

Do people notice it?

Thursday, November 11, 2010

Page 71: ZOMG WHY IS THIS CODE SO SLOW

In comparison to?

Thursday, November 11, 2010

Page 72: ZOMG WHY IS THIS CODE SO SLOW

Finishes in a reasonable amount

of time.

Thursday, November 11, 2010

Page 73: ZOMG WHY IS THIS CODE SO SLOW

What code should I improve?

Thursday, November 11, 2010

Page 74: ZOMG WHY IS THIS CODE SO SLOW

*Only* the code that matters.

Thursday, November 11, 2010

Page 75: ZOMG WHY IS THIS CODE SO SLOW

Don't believe me.

Thursday, November 11, 2010

Page 76: ZOMG WHY IS THIS CODE SO SLOW

Think Critically

Thursday, November 11, 2010

Page 77: ZOMG WHY IS THIS CODE SO SLOW

Discovery

Thursday, November 11, 2010

Page 78: ZOMG WHY IS THIS CODE SO SLOW

What to measure?

Thursday, November 11, 2010

Page 79: ZOMG WHY IS THIS CODE SO SLOW

Breakdown

Thursday, November 11, 2010

Page 80: ZOMG WHY IS THIS CODE SO SLOW

Thursday, November 11, 2010

Page 81: ZOMG WHY IS THIS CODE SO SLOW

Post.find(1)

ARel....

find_by_sql()

execute()

log()

Thursday, November 11, 2010

Page 82: ZOMG WHY IS THIS CODE SO SLOW

find_by_sql()

execute()

log()

Thursday, November 11, 2010

Page 83: ZOMG WHY IS THIS CODE SO SLOW

Work per Time

Thursday, November 11, 2010

Page 84: ZOMG WHY IS THIS CODE SO SLOW

Performance Degraded

Thursday, November 11, 2010

Page 85: ZOMG WHY IS THIS CODE SO SLOW

Benchmarking

Thursday, November 11, 2010

Page 86: ZOMG WHY IS THIS CODE SO SLOW

Our Enemies

Thursday, November 11, 2010

Page 87: ZOMG WHY IS THIS CODE SO SLOW

Time

Thursday, November 11, 2010

Page 88: ZOMG WHY IS THIS CODE SO SLOW

Space

Thursday, November 11, 2010

Page 89: ZOMG WHY IS THIS CODE SO SLOW

For Performance:

Thursday, November 11, 2010

Page 90: ZOMG WHY IS THIS CODE SO SLOW

Things To Reduce

•Method calls

• Branching and looping

•Objects (memory consumption)

Thursday, November 11, 2010

Page 91: ZOMG WHY IS THIS CODE SO SLOW

For Clean Code:

Thursday, November 11, 2010

Page 92: ZOMG WHY IS THIS CODE SO SLOW

Things To Reduce

•Method calls

• Branching and looping

•Objects (memory consumption)

Thursday, November 11, 2010

Page 93: ZOMG WHY IS THIS CODE SO SLOW

∴(therefore)

Thursday, November 11, 2010

Page 94: ZOMG WHY IS THIS CODE SO SLOW

Clean Code==

Performant code

Thursday, November 11, 2010

Page 95: ZOMG WHY IS THIS CODE SO SLOW

Measurement is Paramount

Thursday, November 11, 2010

Page 96: ZOMG WHY IS THIS CODE SO SLOW

require 'benchmark'

Thursday, November 11, 2010

Page 97: ZOMG WHY IS THIS CODE SO SLOW

require 'benchmark'

def fib n a = 0 b = 1 n.times { a, b = b, a + b } aend

Benchmark.bm(7) do |x| x.report("fib") do 3000.times do |i| fib(1000) end endend

Thursday, November 11, 2010

Page 98: ZOMG WHY IS THIS CODE SO SLOW

user system total realfib 1.570000 0.000000 1.570000 ( 1.570726)

Thursday, November 11, 2010

Page 99: ZOMG WHY IS THIS CODE SO SLOW

user

system

total

real

1.570000

0.000000

1.570000

1.570726

Thursday, November 11, 2010

Page 100: ZOMG WHY IS THIS CODE SO SLOW

Benchmark.bm(10) do |x| [1, 10, 100, 1000, 10000].each do |n| x.report("fib #{n}") do n.times { fib(1000) } end endend

Thursday, November 11, 2010

Page 101: ZOMG WHY IS THIS CODE SO SLOW

user system total realfib 1 0.000000 0.000000 0.000000 ( 0.000671)fib 10 0.010000 0.000000 0.010000 ( 0.008352)fib 100 0.070000 0.000000 0.070000 ( 0.074577)fib 1000 0.740000 0.000000 0.740000 ( 0.734922)fib 10000 7.330000 0.000000 7.330000 ( 7.370046)

Thursday, November 11, 2010

Page 102: ZOMG WHY IS THIS CODE SO SLOW

0

2

4

6

8

0 2500 5000 7500 10000

y = 0.0007x - 1.899E-5

fib (n, 1 - 10000)

Thursday, November 11, 2010

Page 103: ZOMG WHY IS THIS CODE SO SLOW

minitest/benchmark

Thursday, November 11, 2010

Page 104: ZOMG WHY IS THIS CODE SO SLOW

require 'rubygems'require 'minitest/autorun'require 'minitest/benchmark'

class BenchFib < MiniTest::Unit::TestCase def fib n a = 0 b = 1 n.times { a, b = b, a + b } a end

def bench_fib assert_performance_linear 0.99 do |n| n.times { fib(1000) } end endend

Thursday, November 11, 2010

Page 105: ZOMG WHY IS THIS CODE SO SLOW

Benchmark.bm(10) do |x| [1, 10, 100, 1000, 10000].each do |n| x.report("fib #{n}") do n.times { fib(1000) } end endend

Thursday, November 11, 2010

Page 106: ZOMG WHY IS THIS CODE SO SLOW

assert_performance_linear 0.99 do |n| n.times { fib(1000) }end

Thursday, November 11, 2010

Page 107: ZOMG WHY IS THIS CODE SO SLOW

BenchFib 1 10 100 1000 10000bench_fib 0.000571 0.005318 0.052582 0.825676 8.180719

Thursday, November 11, 2010

Page 108: ZOMG WHY IS THIS CODE SO SLOW

0

2.25

4.5

6.75

9

0 2500 5000 7500 10000

y = 0.0008x - 0.0067

BenchFib

Thursday, November 11, 2010

Page 109: ZOMG WHY IS THIS CODE SO SLOW

def bench_find_by_sql assert_performance_linear 0.999 do |n| n.times do Post.find_by_sql( 'SELECT * FROM posts WHERE id = 1') end endend

find_by_sql

Thursday, November 11, 2010

Page 110: ZOMG WHY IS THIS CODE SO SLOW

execute()

def bench_execute conn = Post.connection assert_performance_linear 0.999 do |n| n.times do conn.execute( 'SELECT * FROM posts WHERE id = 1') end endend

Thursday, November 11, 2010

Page 111: ZOMG WHY IS THIS CODE SO SLOW

log()def bench_log conn = Post.connection class << conn public :log end

assert_performance_linear 0.999 do |n| n.times do conn.log('SQL', 'hi mom!') {} end endend

Thursday, November 11, 2010

Page 112: ZOMG WHY IS THIS CODE SO SLOW

0

0.75

1.5

2.25

3

0 2500 5000 7500 10000

y = 0.0001x - 0.0097

y = 0.0002x - 0.0135y = 0.0002x - 0.0047

ActiveRecord 3.0 Beta

bench_find_by_sql bench_execute bench_log

Thursday, November 11, 2010

Page 113: ZOMG WHY IS THIS CODE SO SLOW

0

0.75

1.5

2.25

3

0 2500 5000 7500 10000

y = 5.164E-5x - 0.0121

y = 0.0001x - 0.0037y = 0.0002x - 0.0053

ActiveRecord 2.3.x

bench_find_by_sql bench_execute bench_log

Thursday, November 11, 2010

Page 114: ZOMG WHY IS THIS CODE SO SLOW

0

0.75

1.5

2.25

3

0 2500 5000 7500 10000

bench_log 2.3.x + 3.0

bench_log (2.3) bench_log (3.0)

Thursday, November 11, 2010

Page 115: ZOMG WHY IS THIS CODE SO SLOW

Δ find_by_sql()=

Δ execute()=

Δ log()

Thursday, November 11, 2010

Page 116: ZOMG WHY IS THIS CODE SO SLOW

Δ execute() - Δ log() = 0

Thursday, November 11, 2010

Page 117: ZOMG WHY IS THIS CODE SO SLOW

Method Call Analysis

Thursday, November 11, 2010

Page 118: ZOMG WHY IS THIS CODE SO SLOW

perftools.rbhttp://github.com/tmm1/perftools.rb/

Thursday, November 11, 2010

Page 119: ZOMG WHY IS THIS CODE SO SLOW

CPUPROFILE=/tmp/my_profile RUBYOPT="-

r`gem which perftools | tail -1`" ruby ...

Thursday, November 11, 2010

Page 120: ZOMG WHY IS THIS CODE SO SLOW

CPUPROFILE=/tmp/my_profile RUBYOPT="-

r`gem which perftools | tail -1`" ruby ...

Thursday, November 11, 2010

Page 121: ZOMG WHY IS THIS CODE SO SLOW

Rails 3.0 Beta

Thursday, November 11, 2010

Page 122: ZOMG WHY IS THIS CODE SO SLOW

/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/bin/rubyTotal samples: 468Focusing on: 468Dropped nodes with <= 2 abs(samples)Dropped edges with <= 0 samples

Integer#times25 (5.3%)

of 293 (62.6%)

ActiveRecordConnectionAdaptersAbstractAdapter#log

55 (11.8%)of 268 (57.3%)

268

ActiveSupportNotifications.instrument

32 (6.8%)of 213 (45.5%)

213

Benchmark.ms122 (26.1%)

of 130 (27.8%)

130

ActiveSupportNotifications

Instrumenter#instrument6 (1.3%)

of 180 (38.5%)

180

130

ActiveSupportNotifications

Fanout#publish3 (0.6%)

of 35 (7.5%)

35

Time.now15 (3.2%)

9

Benchmark.realtime2 (0.4%)

of 9 (1.9%)

9

garbage_collector113 (24.1%)

Array#each12 (2.6%)

of 70 (15.0%)

Object#require9 (1.9%)

of 51 (10.9%)

1

23

Gem.load_plugins0 (0.0%)

of 18 (3.8%)

2

GemGemPathSearcher#initialize

0 (0.0%)of 16 (3.4%)

1

GemSourceIndex#load_gems_in

0 (0.0%)of 15 (3.2%)

15

Object#find0 (0.0%)

of 10 (2.1%)

10

ActiveSupportDependencies

WatchStack#new_constants_for0 (0.0%)

of 5 (1.1%)

4

46

Kernel#gem_original_require8 (1.7%)

of 28 (6.0%)

48

Object#load_dependency0 (0.0%)

of 28 (6.0%)

5218

GemGemPathSearcher#find

0 (0.0%)of 10 (2.1%)

10

34

ActiveSupportNotifications

FanoutSubscriber#publish

3 (0.6%)of 21 (4.5%)

21

44

Module#new_constants_in0 (0.0%)

of 28 (6.0%)

45

5

ActiveSupportDependencies

WatchStack#add_modules0 (0.0%)

of 4 (0.9%)

4

45

54

ActiveSupportLogSubscriber#call

18 (3.8%)

18

Class#new2 (0.4%)

of 19 (4.1%)

14

GemSpecification#initialize

0 (0.0%)of 5 (1.1%)

5

GemVersion#initialize

0 (0.0%)of 3 (0.6%)

3

2

Gem.find_files1 (0.2%)

of 16 (3.4%)

16

Gem.searcher0 (0.0%)

of 14 (3.0%)

12

Array#map1 (0.2%)

of 6 (1.3%)

1

GemGemPathSearcher#find_all

0 (0.0%)of 3 (0.6%)

3

1

GemGemPathSearcher#init_gemspecs

0 (0.0%)of 15 (3.2%)

15

GemSourceIndex.from_installed_gems

0 (0.0%)of 16 (3.4%)

GemSourceIndex.from_gems_in

0 (0.0%)of 15 (3.2%)

15

Array#reverse_each0 (0.0%)

of 15 (3.2%)

15

Gem.source_index0 (0.0%)

of 15 (3.2%)

15

15

15

15

GemSourceIndex.load_specification

9 (1.9%)of 15 (3.2%)

15

GemSourceIndex#refresh!

0 (0.0%)of 15 (3.2%)

15

15

9

6

14

Mutex#synchronize0 (0.0%)

of 13 (2.8%)

12

GemGemPathSearcher#matching_file?

0 (0.0%)of 13 (2.8%)

GemGemPathSearcher#matching_files

13 (2.8%)

13

13

10

10

10

10

1

6

Object#require_library_or_gem0 (0.0%)

of 9 (1.9%)

9

Object#silence_warnings0 (0.0%)

of 4 (0.9%)

4

Module#class_eval3 (0.6%)

of 8 (1.7%)

1

4

Module#local_constant_names1 (0.2%)

of 8 (1.7%)

1

Module#local_constants5 (1.1%)

of 6 (1.3%)

6

1

4

Array#select1 (0.2%)

of 4 (0.9%)

1

5

4

4

ActiveRecordBase.sqlite3_connection

0 (0.0%)of 4 (0.9%)

4

ActiveRecordConnectionAdapters

ConnectionPool#checkout_new_connection0 (0.0%)

of 4 (0.9%)

ActiveRecordConnectionAdapters

ConnectionPool#new_connection0 (0.0%)

of 4 (0.9%)

4

4

4

4

3

4

Object#with_warnings0 (0.0%)

of 4 (0.9%)

4 4

33

GemVersion#segments

3 (0.6%)

3

Thursday, November 11, 2010

Page 123: ZOMG WHY IS THIS CODE SO SLOW

/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/bin/rubyTotal samples: 468Focusing on: 468Dropped nodes with <= 2 abs(samples)Dropped edges with <= 0 samples

Integer#times25 (5.3%)

of 293 (62.6%)

ActiveRecordConnectionAdaptersAbstractAdapter#log

55 (11.8%)of 268 (57.3%)

268

ActiveSupportNotifications.instrument

32 (6.8%)of 213 (45.5%)

213

Benchmark.ms122 (26.1%)

of 130 (27.8%)

130

ActiveSupportNotifications

Instrumenter#instrument6 (1.3%)

of 180 (38.5%)

180

130

ActiveSupportNotifications

Fanout#publish3 (0.6%)

of 35 (7.5%)

35

Time.now15 (3.2%)

9

Benchmark.realtime2 (0.4%)

of 9 (1.9%)

9

garbage_collector113 (24.1%)

Array#each12 (2.6%)

of 70 (15.0%)

Object#require9 (1.9%)

of 51 (10.9%)

1

23

Gem.load_plugins0 (0.0%)

of 18 (3.8%)

2

GemGemPathSearcher#initialize

0 (0.0%)of 16 (3.4%)

1

GemSourceIndex#load_gems_in

0 (0.0%)of 15 (3.2%)

15

Object#find0 (0.0%)

of 10 (2.1%)

10

ActiveSupportDependencies

WatchStack#new_constants_for0 (0.0%)

of 5 (1.1%)

4

46

Kernel#gem_original_require8 (1.7%)

of 28 (6.0%)

48

Object#load_dependency0 (0.0%)

of 28 (6.0%)

5218

GemGemPathSearcher#find

0 (0.0%)of 10 (2.1%)

10

34

ActiveSupportNotifications

FanoutSubscriber#publish

3 (0.6%)of 21 (4.5%)

21

44

Module#new_constants_in0 (0.0%)

of 28 (6.0%)

45

5

ActiveSupportDependencies

WatchStack#add_modules0 (0.0%)

of 4 (0.9%)

4

45

54

ActiveSupportLogSubscriber#call

18 (3.8%)

18

Class#new2 (0.4%)

of 19 (4.1%)

14

GemSpecification#initialize

0 (0.0%)of 5 (1.1%)

5

GemVersion#initialize

0 (0.0%)of 3 (0.6%)

3

2

Gem.find_files1 (0.2%)

of 16 (3.4%)

16

Gem.searcher0 (0.0%)

of 14 (3.0%)

12

Array#map1 (0.2%)

of 6 (1.3%)

1

GemGemPathSearcher#find_all

0 (0.0%)of 3 (0.6%)

3

1

GemGemPathSearcher#init_gemspecs

0 (0.0%)of 15 (3.2%)

15

GemSourceIndex.from_installed_gems

0 (0.0%)of 16 (3.4%)

GemSourceIndex.from_gems_in

0 (0.0%)of 15 (3.2%)

15

Array#reverse_each0 (0.0%)

of 15 (3.2%)

15

Gem.source_index0 (0.0%)

of 15 (3.2%)

15

15

15

15

GemSourceIndex.load_specification

9 (1.9%)of 15 (3.2%)

15

GemSourceIndex#refresh!

0 (0.0%)of 15 (3.2%)

15

15

9

6

14

Mutex#synchronize0 (0.0%)

of 13 (2.8%)

12

GemGemPathSearcher#matching_file?

0 (0.0%)of 13 (2.8%)

GemGemPathSearcher#matching_files

13 (2.8%)

13

13

10

10

10

10

1

6

Object#require_library_or_gem0 (0.0%)

of 9 (1.9%)

9

Object#silence_warnings0 (0.0%)

of 4 (0.9%)

4

Module#class_eval3 (0.6%)

of 8 (1.7%)

1

4

Module#local_constant_names1 (0.2%)

of 8 (1.7%)

1

Module#local_constants5 (1.1%)

of 6 (1.3%)

6

1

4

Array#select1 (0.2%)

of 4 (0.9%)

1

5

4

4

ActiveRecordBase.sqlite3_connection

0 (0.0%)of 4 (0.9%)

4

ActiveRecordConnectionAdapters

ConnectionPool#checkout_new_connection0 (0.0%)

of 4 (0.9%)

ActiveRecordConnectionAdapters

ConnectionPool#new_connection0 (0.0%)

of 4 (0.9%)

4

4

4

4

3

4

Object#with_warnings0 (0.0%)

of 4 (0.9%)

4 4

33

GemVersion#segments

3 (0.6%)

3

Thursday, November 11, 2010

Page 124: ZOMG WHY IS THIS CODE SO SLOW

Total: 468 samples 122 26.1% 26.1% 130 27.8% Benchmark.ms 113 24.1% 50.2% 113 24.1% garbage_collector 55 11.8% 62.0% 268 57.3% ::AbstractAdapter#log 32 6.8% 68.8% 213 45.5% ::Notifications.instrument 25 5.3% 74.1% 293 62.6% Integer#times 18 3.8% 78.0% 18 3.8%::LogSubscriber#call 15 3.2% 81.2% 15 3.2% Time.now 13 2.8% 84.0% 13 2.8% GemPathSearcher#matching_files 12 2.6% 86.5% 70 15.0% Array#each 9 1.9% 88.5% 15 3.2% SourceIndex.load_specification 9 1.9% 90.4% 51 10.9% Object#require

Thursday, November 11, 2010

Page 125: ZOMG WHY IS THIS CODE SO SLOW

Rails 2-3-stable

Thursday, November 11, 2010

Page 126: ZOMG WHY IS THIS CODE SO SLOW

/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/bin/rubyTotal samples: 212Focusing on: 212Dropped nodes with <= 1 abs(samples)Dropped edges with <= 0 samples

Integer#times4 (1.9%)

of 104 (49.1%)

ActiveRecordConnectionAdaptersAbstractAdapter#log

6 (2.8%)of 100 (47.2%)

100

Benchmark.ms80 (37.7%)

of 94 (44.3%)

94

Benchmark.realtime8 (3.8%)

of 15 (7.1%)

15

garbage_collector55 (25.9%)

Object#require5 (2.4%)

of 43 (20.3%)30

Kernel#gem_original_require9 (4.2%)

of 20 (9.4%)

55

Gem.load_plugins0 (0.0%)

of 16 (7.5%)

16

Module#new_constants_in0 (0.0%)

of 16 (7.5%)

31

GemGemPathSearcher#find

0 (0.0%)of 11 (5.2%)

11Array#each

1 (0.5%)of 34 (16.0%)

8

GemGemPathSearcher#initialize

0 (0.0%)of 17 (8.0%)

1

GemSourceIndex#load_gems_in

0 (0.0%)of 15 (7.1%)

15

Object#find0 (0.0%)

of 11 (5.2%)

11

GemSpecification#assign_defaults

2 (0.9%)

2

38

8

Class#new1 (0.5%)

of 19 (9.0%)

17

GemSpecification#initialize

0 (0.0%)of 5 (2.4%)

5

GemConfigFile#initialize

0 (0.0%)of 2 (0.9%)

2

GemVersion#initialize

0 (0.0%)of 2 (0.9%)

2

Gem.find_files1 (0.5%)

of 17 (8.0%)

Gem.searcher0 (0.0%)

of 17 (8.0%)

13

GemGemPathSearcher#find_all

0 (0.0%)of 3 (1.4%)

3

Array#map0 (0.0%)

of 2 (0.9%)

1

17

Mutex#synchronize0 (0.0%)

of 16 (7.5%)

13

1

GemGemPathSearcher#init_gemspecs

0 (0.0%)of 16 (7.5%)

16

GemSourceIndex.from_installed_gems

0 (0.0%)of 17 (8.0%)

GemSourceIndex.from_gems_in

0 (0.0%)of 15 (7.1%)

15

GemSourceIndex.installed_spec_directories

0 (0.0%)of 2 (0.9%)

2

16

Gem.source_index0 (0.0%)

of 16 (7.5%)

16

16

29

Array#collect0 (0.0%)

of 2 (0.9%)

2

Object#local_constant_names0 (0.0%)

of 2 (0.9%)

2

16

Array#reverse_each0 (0.0%)

of 15 (7.1%)

15

1

Time.now6 (2.8%)

6

15

15

GemSourceIndex.load_specification

10 (4.7%)of 15 (7.1%)

15

GemSourceIndex#refresh!

0 (0.0%)of 15 (7.1%)

15

15

7

5

GemGemPathSearcher#matching_file?

0 (0.0%)of 14 (6.6%)

GemGemPathSearcher#matching_files

14 (6.6%)

14

11

11

11

11

ActiveRecordBase.sqlite3_connection

0 (0.0%)of 8 (3.8%)

Object#require_library_or_gem0 (0.0%)

of 8 (3.8%)

8

ActiveRecordConnectionAdapters

ConnectionPool#new_connection0 (0.0%)

of 8 (3.8%)

8

8

Object#silence_warnings0 (0.0%)

of 8 (3.8%)

88

ActiveRecordConnectionAdapters

ConnectionPool#checkout0 (0.0%)

of 5 (2.4%)

ActiveRecordConnectionAdapters

ConnectionPool#checkout_new_connection0 (0.0%)

of 5 (2.4%)

5

Object#loop0 (0.0%)

of 4 (1.9%)

4

5

3

2

Module#class_eval3 (1.4%)

of 4 (1.9%)

1

MonitorMixin#synchronize0 (0.0%)

of 4 (1.9%)

4

4

Array#select0 (0.0%)

of 3 (1.4%)

33 3

2

1

Gem.configuration0 (0.0%)

of 2 (0.9%)

2

Gem.path0 (0.0%)

of 2 (0.9%)

2

GemConfigFile#load_file

0 (0.0%)of 2 (0.9%)

2

2

2

2

GemSpecification#full_gem_path

2 (0.9%)

Object#local_constants2 (0.9%)

2

Thursday, November 11, 2010

Page 127: ZOMG WHY IS THIS CODE SO SLOW

/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/bin/rubyTotal samples: 212Focusing on: 212Dropped nodes with <= 1 abs(samples)Dropped edges with <= 0 samples

Integer#times4 (1.9%)

of 104 (49.1%)

ActiveRecordConnectionAdaptersAbstractAdapter#log

6 (2.8%)of 100 (47.2%)

100

Benchmark.ms80 (37.7%)

of 94 (44.3%)

94

Benchmark.realtime8 (3.8%)

of 15 (7.1%)

15

garbage_collector55 (25.9%)

Object#require5 (2.4%)

of 43 (20.3%)30

Kernel#gem_original_require9 (4.2%)

of 20 (9.4%)

55

Gem.load_plugins0 (0.0%)

of 16 (7.5%)

16

Module#new_constants_in0 (0.0%)

of 16 (7.5%)

31

GemGemPathSearcher#find

0 (0.0%)of 11 (5.2%)

11Array#each

1 (0.5%)of 34 (16.0%)

8

GemGemPathSearcher#initialize

0 (0.0%)of 17 (8.0%)

1

GemSourceIndex#load_gems_in

0 (0.0%)of 15 (7.1%)

15

Object#find0 (0.0%)

of 11 (5.2%)

11

GemSpecification#assign_defaults

2 (0.9%)

2

38

8

Class#new1 (0.5%)

of 19 (9.0%)

17

GemSpecification#initialize

0 (0.0%)of 5 (2.4%)

5

GemConfigFile#initialize

0 (0.0%)of 2 (0.9%)

2

GemVersion#initialize

0 (0.0%)of 2 (0.9%)

2

Gem.find_files1 (0.5%)

of 17 (8.0%)

Gem.searcher0 (0.0%)

of 17 (8.0%)

13

GemGemPathSearcher#find_all

0 (0.0%)of 3 (1.4%)

3

Array#map0 (0.0%)

of 2 (0.9%)

1

17

Mutex#synchronize0 (0.0%)

of 16 (7.5%)

13

1

GemGemPathSearcher#init_gemspecs

0 (0.0%)of 16 (7.5%)

16

GemSourceIndex.from_installed_gems

0 (0.0%)of 17 (8.0%)

GemSourceIndex.from_gems_in

0 (0.0%)of 15 (7.1%)

15

GemSourceIndex.installed_spec_directories

0 (0.0%)of 2 (0.9%)

2

16

Gem.source_index0 (0.0%)

of 16 (7.5%)

16

16

29

Array#collect0 (0.0%)

of 2 (0.9%)

2

Object#local_constant_names0 (0.0%)

of 2 (0.9%)

2

16

Array#reverse_each0 (0.0%)

of 15 (7.1%)

15

1

Time.now6 (2.8%)

6

15

15

GemSourceIndex.load_specification

10 (4.7%)of 15 (7.1%)

15

GemSourceIndex#refresh!

0 (0.0%)of 15 (7.1%)

15

15

7

5

GemGemPathSearcher#matching_file?

0 (0.0%)of 14 (6.6%)

GemGemPathSearcher#matching_files

14 (6.6%)

14

11

11

11

11

ActiveRecordBase.sqlite3_connection

0 (0.0%)of 8 (3.8%)

Object#require_library_or_gem0 (0.0%)

of 8 (3.8%)

8

ActiveRecordConnectionAdapters

ConnectionPool#new_connection0 (0.0%)

of 8 (3.8%)

8

8

Object#silence_warnings0 (0.0%)

of 8 (3.8%)

88

ActiveRecordConnectionAdapters

ConnectionPool#checkout0 (0.0%)

of 5 (2.4%)

ActiveRecordConnectionAdapters

ConnectionPool#checkout_new_connection0 (0.0%)

of 5 (2.4%)

5

Object#loop0 (0.0%)

of 4 (1.9%)

4

5

3

2

Module#class_eval3 (1.4%)

of 4 (1.9%)

1

MonitorMixin#synchronize0 (0.0%)

of 4 (1.9%)

4

4

Array#select0 (0.0%)

of 3 (1.4%)

33 3

2

1

Gem.configuration0 (0.0%)

of 2 (0.9%)

2

Gem.path0 (0.0%)

of 2 (0.9%)

2

GemConfigFile#load_file

0 (0.0%)of 2 (0.9%)

2

2

2

2

GemSpecification#full_gem_path

2 (0.9%)

Object#local_constants2 (0.9%)

2

Thursday, November 11, 2010

Page 128: ZOMG WHY IS THIS CODE SO SLOW

Total: 212 samples 80 37.7% 37.7% 94 44.3% Benchmark.ms 55 25.9% 63.7% 55 25.9% garbage_collector 14 6.6% 70.3% 14 6.6% ::GemPathSearcher#matching_files 10 4.7% 75.0% 15 7.1% ::SourceIndex.load_specification 9 4.2% 79.2% 20 9.4% Kernel#gem_original_require 8 3.8% 83.0% 15 7.1% Benchmark.realtime 6 2.8% 85.8% 100 47.2% ::AbstractAdapter#log 6 2.8% 88.7% 6 2.8% Time.now 5 2.4% 91.0% 43 20.3% Object#require 4 1.9% 92.9% 104 49.1% Integer#times 3 1.4% 94.3% 4 1.9% Module#class_eval 2 0.9% 95.3% 2 0.9% ::Specification#assign_defaults 2 0.9% 96.2% 2 0.9% Gem::Specification#full_gem_path 2 0.9% 97.2% 2 0.9% Object#local_constants

Thursday, November 11, 2010

Page 129: ZOMG WHY IS THIS CODE SO SLOW

ruby-prof

Thursday, November 11, 2010

Page 130: ZOMG WHY IS THIS CODE SO SLOW

Usage

result = RubyProf.profile do ...endprinter = RubyProf::FlatPrinter.new(result)printer.print(STDOUT, 0)

Thursday, November 11, 2010

Page 131: ZOMG WHY IS THIS CODE SO SLOW

n = 1000

Thursday, November 11, 2010

Page 132: ZOMG WHY IS THIS CODE SO SLOW

Rails 3.0 Beta

Thursday, November 11, 2010

Page 133: ZOMG WHY IS THIS CODE SO SLOW

Total: 0.160831

%self total self wait child calls name 28.26 0.15 0.05 0.00 0.10 1000 <::Notifications>#instrument 9.36 0.03 0.02 0.00 0.01 1000 <::Benchmark>#realtime 9.16 0.09 0.01 0.00 0.07 1000 ::Instrumenter#instrument 7.28 0.02 0.01 0.00 0.01 4000 <Class::Time>#now 5.41 0.16 0.01 0.00 0.15 1000 ::AbstractAdapter#log 5.10 0.01 0.01 0.00 0.01 1000 <::Notifications>#instrumenter 2.92 0.00 0.00 0.00 0.00 4000 <Class::Time>#allocate 2.73 0.02 0.00 0.00 0.01 1000 Array#each 2.57 0.03 0.00 0.00 0.03 1000 <Module::Benchmark>#ms 2.57 0.00 0.00 0.00 0.00 4000 Time#initialize 2.55 0.03 0.00 0.00 0.02 1000 Notifications::Fanout#publish 2.45 0.01 0.00 0.00 0.01 1000 LogSubscriber#call 2.37 0.01 0.00 0.00 0.01 1000 ::Fanout::Subscriber#publish 2.04 0.01 0.00 0.00 0.00 1000 LogSubscriber#logger 1.84 0.00 0.00 0.00 0.00 1000 ::Fanout#listeners_for 1.64 0.16 0.00 0.00 0.16 1 Integer#times

Thursday, November 11, 2010

Page 134: ZOMG WHY IS THIS CODE SO SLOW

Rails 2-3-stable

Thursday, November 11, 2010

Page 135: ZOMG WHY IS THIS CODE SO SLOW

Thread ID: 2148237740Total: 0.051336

%self total self wait child calls name 27.00 0.03 0.01 0.00 0.01 1000 <Module::Benchmark>#realtime 23.35 0.05 0.01 0.00 0.04 1000 ::AbstractAdapter#log 11.67 0.01 0.01 0.00 0.00 2000 <Class::Time>#now 7.66 0.03 0.00 0.00 0.03 1000 <Module::Benchmark>#ms 5.37 0.00 0.00 0.00 0.00 1000 ::AbstractAdapter#log_info 5.11 0.05 0.00 0.00 0.05 1 Integer#times 4.52 0.00 0.00 0.00 0.00 2000 <Class::Time>#allocate 3.89 0.00 0.00 0.00 0.00 2000 Time#initialize 3.83 0.00 0.00 0.00 0.00 2000 Time#to_f

Thursday, November 11, 2010

Page 136: ZOMG WHY IS THIS CODE SO SLOW

Methods in Common

• <Class::Time>#now

• <Class::Time>#allocate

Thursday, November 11, 2010

Page 137: ZOMG WHY IS THIS CODE SO SLOW

Time#now

Time#allocate

3.0 Beta 2-3 Stable

4000 2000

4000 2000

n = 1000

Thursday, November 11, 2010

Page 138: ZOMG WHY IS THIS CODE SO SLOW

http://bit.ly/omgslow

Thursday, November 11, 2010

Page 139: ZOMG WHY IS THIS CODE SO SLOW

"It's all fixed!"

Thursday, November 11, 2010

Page 140: ZOMG WHY IS THIS CODE SO SLOW

Wait a few hours...

Thursday, November 11, 2010

Page 141: ZOMG WHY IS THIS CODE SO SLOW

"It's better, but still 2x slower"

Thursday, November 11, 2010

Page 142: ZOMG WHY IS THIS CODE SO SLOW

Post.find(1)

ARel....

find_by_sql()

execute()

log()

Thursday, November 11, 2010

Page 143: ZOMG WHY IS THIS CODE SO SLOW

ARel....

Thursday, November 11, 2010

Page 144: ZOMG WHY IS THIS CODE SO SLOW

Side note:This is when Ryan told me to rewrite.

Thursday, November 11, 2010

Page 145: ZOMG WHY IS THIS CODE SO SLOW

Superficial Improvements

Thursday, November 11, 2010

Page 146: ZOMG WHY IS THIS CODE SO SLOW

LimitedDomain / System

Knowledge

Thursday, November 11, 2010

Page 147: ZOMG WHY IS THIS CODE SO SLOW

VM Tricks

Thursday, November 11, 2010

Page 148: ZOMG WHY IS THIS CODE SO SLOW

See Results Quickly

Thursday, November 11, 2010

Page 149: ZOMG WHY IS THIS CODE SO SLOW

Tapers off Over Time

Thursday, November 11, 2010

Page 150: ZOMG WHY IS THIS CODE SO SLOW

Kow

ledg

e / I

mpr

ovem

ent

TimeImprovements (S) System Knowledge

System Impact

Thursday, November 11, 2010

Page 151: ZOMG WHY IS THIS CODE SO SLOW

attr_*

Thursday, November 11, 2010

Page 152: ZOMG WHY IS THIS CODE SO SLOW

def some_attribute @some_attributeend

# vs

attr_reader :some_attribute

Thursday, November 11, 2010

Page 153: ZOMG WHY IS THIS CODE SO SLOW

0

0.075

0.15

0.225

0.3

0 250000 500000 750000 1000000

y = 1.965E-7x + 0.0002y = 2.934E-7x + 0.0009

bench_method bench_reader

Thursday, November 11, 2010

Page 154: ZOMG WHY IS THIS CODE SO SLOW

case VM_METHOD_TYPE_IVAR: { if (argc != 0) { rb_raise(rb_eArgError, "wrong number of arguments (%d for 0)", argc); } val = rb_attr_get(recv, def->body.attr.id); break;}

attr_reader

Thursday, November 11, 2010

Page 155: ZOMG WHY IS THIS CODE SO SLOW

method callcase VM_METHOD_TYPE_ISEQ: { rb_control_frame_t *reg_cfp; int i;

rb_vm_set_finish_env(th); reg_cfp = th->cfp;

CHECK_STACK_OVERFLOW(reg_cfp, argc + 1);

*reg_cfp->sp++ = recv; for (i = 0; i < argc; i++) { *reg_cfp->sp++ = argv[i]; }

vm_setup_method(th, reg_cfp, recv, argc, blockptr, 0 /* flag */, me); val = vm_exec(th); break;}

Thursday, November 11, 2010

Page 156: ZOMG WHY IS THIS CODE SO SLOW

vm_setup_method

•Check for stack overflow

• Pushing a stack frame

•Copying arguments

Thursday, November 11, 2010

Page 157: ZOMG WHY IS THIS CODE SO SLOW

class Foo attr_reader :some_attribute

def some_attribute? @some_attribute endend

Predicate Methods

Thursday, November 11, 2010

Page 158: ZOMG WHY IS THIS CODE SO SLOW

class Foo attr_reader :some_attribute alias :some_attribute? :some_attributeend

Predicate Methods

Thursday, November 11, 2010

Page 159: ZOMG WHY IS THIS CODE SO SLOW

Hash[] vs inject({})

Thursday, November 11, 2010

Page 160: ZOMG WHY IS THIS CODE SO SLOW

inject({})

some_list.inject({}) do |hash,val| hash[val] = some_transform(val) hashend

Thursday, November 11, 2010

Page 161: ZOMG WHY IS THIS CODE SO SLOW

Hash[]

values = some_list.map { |val| [val, some_transform(val)]}Hash[values]

Thursday, November 11, 2010

Page 162: ZOMG WHY IS THIS CODE SO SLOW

@list.inject({}) do |hash,val| hash[val] = val.length hashend

# vs

Hash[@list.map { |val| [val,val.length] }]

Thursday, November 11, 2010

Page 163: ZOMG WHY IS THIS CODE SO SLOW

0

1.75

3.5

5.25

7

0 250000 500000 750000 1000000

y = 6.17E-6x - 0.0108y = 5.268E-6x - 0.0075

Hash[] inject({})

Thursday, November 11, 2010

Page 164: ZOMG WHY IS THIS CODE SO SLOW

Strangeness

Thursday, November 11, 2010

Page 165: ZOMG WHY IS THIS CODE SO SLOW

def bench_naked_each assert_performance_linear 0.999 do |n| m = nil n.times { @list.each { |v| m = v } } endend

def bench_naked_inject assert_performance_linear 0.999 do |n| n.times { @list.inject { |m,v| m = v } } endend

Thursday, November 11, 2010

Page 166: ZOMG WHY IS THIS CODE SO SLOW

0

0.75

1.5

2.25

3

0 250000 500000 750000 1000000

y = 2.746E-6x - 0.0043y = 1.04E-6x - 0.0016

naked each naked inject

Thursday, November 11, 2010

Page 167: ZOMG WHY IS THIS CODE SO SLOW

TANGENT

Thursday, November 11, 2010

Page 168: ZOMG WHY IS THIS CODE SO SLOW

When to use inject()

Thursday, November 11, 2010

Page 169: ZOMG WHY IS THIS CODE SO SLOW

When one calculation depends

on the previous

Thursday, November 11, 2010

Page 170: ZOMG WHY IS THIS CODE SO SLOW

@list.inject({}) do |hash,val| hash[val] = val.length hashend

# vs

Hash[@list.map { |val| [val,val.length] }]

Thursday, November 11, 2010

Page 171: ZOMG WHY IS THIS CODE SO SLOW

%w{ Foo Bar Baz}.inject(Object) { |klass,string| klass.const_get(string.to_sym)}

Thursday, November 11, 2010

Page 172: ZOMG WHY IS THIS CODE SO SLOW

Proc Activation

Thursday, November 11, 2010

Page 173: ZOMG WHY IS THIS CODE SO SLOW

lambda { ... }

# vs

class Callable def call; ... endend

Thursday, November 11, 2010

Page 174: ZOMG WHY IS THIS CODE SO SLOW

0

0.01

0.02

0.03

0.04

0 25000 50000 75000 100000

lambda method

Thursday, November 11, 2010

Page 175: ZOMG WHY IS THIS CODE SO SLOW

is_a?(Proc)

Thursday, November 11, 2010

Page 176: ZOMG WHY IS THIS CODE SO SLOW

respond_to?(:call)

Thursday, November 11, 2010

Page 177: ZOMG WHY IS THIS CODE SO SLOW

class Callable def call(...) ... endend

Thursday, November 11, 2010

Page 178: ZOMG WHY IS THIS CODE SO SLOW

define_method

Thursday, November 11, 2010

Page 179: ZOMG WHY IS THIS CODE SO SLOW

class Foo def foo; end define_method :bar do; end class_eval %{ def baz; end }end

Thursday, November 11, 2010

Page 180: ZOMG WHY IS THIS CODE SO SLOW

-0.15

0

0.15

0.3

0.45

0.6

0 250000 500000 750000 1000000

method class_eval define_method

Thursday, November 11, 2010

Page 181: ZOMG WHY IS THIS CODE SO SLOW

Explicit Block Parameters

Thursday, November 11, 2010

Page 182: ZOMG WHY IS THIS CODE SO SLOW

class Foo def explicit &block yield end

def implicit yield endend

Thursday, November 11, 2010

Page 183: ZOMG WHY IS THIS CODE SO SLOW

-3.75

0

3.75

7.5

11.25

15

0 250000 500000 750000 1000000

explicit implicit

Thursday, November 11, 2010

Page 184: ZOMG WHY IS THIS CODE SO SLOW

def sometimes_block if block_given? Proc.new.call endend

sometimes_block { puts "hi" }sometimes_block

Thursday, November 11, 2010

Page 185: ZOMG WHY IS THIS CODE SO SLOW

Symbol to Proc

Thursday, November 11, 2010

Page 186: ZOMG WHY IS THIS CODE SO SLOW

@list.map(&:to_i)

# vs

@list.map { |x| x.to_i }

Thursday, November 11, 2010

Page 187: ZOMG WHY IS THIS CODE SO SLOW

-5

1.25

7.5

13.75

20

0 250000 500000 750000 1000000

sym to proc block form

Thursday, November 11, 2010

Page 188: ZOMG WHY IS THIS CODE SO SLOW

-5

1.25

7.5

13.75

20

0 250000 500000 750000 1000000

symbol to proc block method

Thursday, November 11, 2010

Page 189: ZOMG WHY IS THIS CODE SO SLOW

Know Your Audience

Thursday, November 11, 2010

Page 190: ZOMG WHY IS THIS CODE SO SLOW

return value caching

Thursday, November 11, 2010

Page 191: ZOMG WHY IS THIS CODE SO SLOW

def some_method @some_method ||= some_expensive_opend

Thursday, November 11, 2010

Page 192: ZOMG WHY IS THIS CODE SO SLOW

How many times?

Thursday, November 11, 2010

Page 193: ZOMG WHY IS THIS CODE SO SLOW

Can the caller cache?

Thursday, November 11, 2010

Page 194: ZOMG WHY IS THIS CODE SO SLOW

Made our improvements

Thursday, November 11, 2010

Page 195: ZOMG WHY IS THIS CODE SO SLOW

Feeling better!

Thursday, November 11, 2010

Page 196: ZOMG WHY IS THIS CODE SO SLOW

:-DThursday, November 11, 2010

Page 197: ZOMG WHY IS THIS CODE SO SLOW

0

200000

400000

600000

800000

0 25000 50000 75000 100000

before (3.0 beta) after (3.0 beta) Rails 2.3

Thursday, November 11, 2010

Page 198: ZOMG WHY IS THIS CODE SO SLOW

What do we do?

Thursday, November 11, 2010

Page 199: ZOMG WHY IS THIS CODE SO SLOW

We have to go deeper

Thursday, November 11, 2010

Page 200: ZOMG WHY IS THIS CODE SO SLOW

$ git grep 'include Relation' | wc -l 6$ git grep 'def bind' | wc -l 12$

Thursday, November 11, 2010

Page 201: ZOMG WHY IS THIS CODE SO SLOW

Everything is_a Relation

Thursday, November 11, 2010

Page 202: ZOMG WHY IS THIS CODE SO SLOW

Everything Responds to "bind"

Thursday, November 11, 2010

Page 203: ZOMG WHY IS THIS CODE SO SLOW

Everything has a "relation"

Thursday, November 11, 2010

Page 204: ZOMG WHY IS THIS CODE SO SLOW

bind() is recursively called on relation

Thursday, November 11, 2010

Page 205: ZOMG WHY IS THIS CODE SO SLOW

How does it work?Thursday, November 11, 2010

Page 206: ZOMG WHY IS THIS CODE SO SLOW

/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/bin/rubyTotal samples: 3794Focusing on: 3794Dropped nodes with <= 18 abs(samples)Dropped edges with <= 3 samples

Integer#times41 (1.1%)

of 2720 (71.7%)

Object#find48 (1.3%)

of 2718 (71.6%)

2666

SQLite3Statement#get_metadata

14 (0.4%)of 40 (1.1%)

13

Object#find_with_ids71 (1.9%)

of 2717 (71.6%)

2656

Array#each30 (0.8%)

of 459 (12.1%)

12

Object#find_one28 (0.7%)

of 2648 (69.8%)

2646

Object#first12 (0.3%)

of 2432 (64.1%)

2407

Object#where196 (5.2%)

of 275 (7.2%)

182

ArelAttribute#eq

1 (0.0%)of 31 (0.8%)

31

Object#find_first18 (0.5%)

of 2468 (65.1%)

ActiveRecordRelation#to_a

35 (0.9%)of 2312 (60.9%)

2310

Object#limit125 (3.3%)

of 140 (3.7%)

140

2420

Post.find_by_sql97 (2.6%)

of 1065 (28.1%)

1059

Object#arel18 (0.5%)

of 666 (17.6%)

666

Object#to_sql35 (0.9%)

of 627 (16.5%)

551

Object#select_all13 (0.3%)

of 845 (22.3%)

825

Array#collect!1 (0.0%)

of 135 (3.6%)

135

Post.instantiate65 (1.7%)

of 69 (1.8%)

69

Post.connection5 (0.1%)

of 40 (1.1%)

40

Post.sanitize_sql33 (0.9%)

33

836

ActiveRecordConnectionAdapters

SQLiteAdapter#select40 (1.1%)

of 832 (21.9%)

832

garbage_collector840 (22.1%)

ActiveRecordConnectionAdapters

SQLiteAdapter#execute50 (1.3%)

of 759 (20.0%)

759

Array#map13 (0.3%)

of 136 (3.6%)

66

Hash#each27 (0.7%)

of 51 (1.3%)

51

Class#new632 (16.7%)

of 806 (21.2%)

ArelProject#initialize

60 (1.6%)of 149 (3.9%)

149

ArelWhere#initialize

20 (0.5%)of 37 (1.0%)

37

ArelTake#initialize

32 (0.8%)

32

ActiveRecordConnectionAdaptersAbstractAdapter#log

16 (0.4%)of 732 (19.3%)

732

SQLite3Database#execute

49 (1.3%)of 630 (16.6%)

630653

ActiveSupportNotifications

Instrumenter#instrument3 (0.1%)

of 722 (19.0%)

722 659

Time.now31 (0.8%)

31

ActiveSupportNotifications

Fanout#publish7 (0.2%)

of 29 (0.8%)

29

Object#build_arel91 (2.4%)

of 648 (17.1%)

648

371

93

ArelPredicates

Binary#to_sql10 (0.3%)

of 235 (6.2%)

235

Object#build_select12 (0.3%)

of 174 (4.6%)

174

Object#take0 (0.0%)

of 37 (1.0%)

37

SQLite3Database#prepare

18 (0.5%)of 620 (16.3%)

620

Object#map10 (0.3%)

of 178 (4.7%)

166

SQLite3Database#ordered_map_for

52 (1.4%)of 76 (2.0%)

76

SQLite3Statement#columns

8 (0.2%)of 48 (1.3%)

48

ArelSqlCompiler

GenericCompiler#select_sql100 (2.6%)

of 496 (13.1%)

496

ArelSql

Attribute#scalar8 (0.2%)

of 71 (1.9%)

71

Object#compiler3 (0.1%)

of 25 (0.7%)

25

364

238

ArelSqlCompiler

GenericCompiler#build_clauses95 (2.5%)

of 256 (6.7%)

256

Object#from_clauses5 (0.1%)

of 122 (3.2%)

122

12

356

19

Object#each_with_index18 (0.5%)

of 28 (0.7%)

20

54

Object#clone1 (0.0%)

of 39 (1.0%)

24

ArelSql

Engine#connection7 (0.2%)

of 106 (2.8%)

23

Object#where_clauses6 (0.2%)

of 70 (1.8%)

70

Object#group_clauses5 (0.1%)

of 25 (0.7%)

25

ArelAttribute#to_sql

14 (0.4%)of 114 (3.0%)

114

ArelAttribute#format

4 (0.1%)of 110 (2.9%)

110

101

SQLite3Statement#each

50 (1.3%)of 166 (4.4%)

166

Object#project1 (0.0%)

of 159 (4.2%)

159

103

Object#loop13 (0.3%)

of 165 (4.3%)

164 151

158

49

46

Object#bind2 (0.1%)

of 48 (1.3%)

36

15

60

42

14

134

ArelCompound#table_sql

13 (0.3%)of 112 (3.0%)

112

18

ArelSql

WhereCondition#attribute9 (0.2%)

of 82 (2.2%)

82 24

Object#table_sql11 (0.3%)

of 75 (2.0%)

75

30

76

ActiveRecordBase.connection

5 (0.1%)of 99 (2.6%)

99

ActiveRecordBase.retrieve_connection

32 (0.8%)of 94 (2.5%)

94

ActiveRecordConnectionAdapters

ConnectionHandler#retrieve_connection23 (0.6%)

of 96 (2.5%)

ActiveRecordConnectionAdapters

ConnectionHandler#retrieve_connection_pool52 (1.4%)

52

62

ArelSql

Formatter#quote_table_name11 (0.3%)

of 66 (1.7%)

34

ArelSql

Formatter#name_for20 (0.5%)

of 39 (1.0%)

12

ArelSql

Formatter#quote_column_name8 (0.2%)

of 27 (0.7%)

27

28

ArelSql

TableReference#table5 (0.1%)

of 64 (1.7%)

64

ArelSql

Formatter#quote17 (0.4%)

of 39 (1.0%)

39

ArelAttribute#column

8 (0.2%)of 24 (0.6%)

24

ArelCompound#wheres

12 (0.3%)of 64 (1.7%)

64

45

33

Array#collect3 (0.1%)

of 52 (1.4%)

52

ArelValue#bind

2 (0.1%)of 45 (1.2%)

45

32 27

Object#require10 (0.3%)

of 60 (1.6%)54

Object#load_dependency0 (0.0%)

of 32 (0.8%)

60

Kernel#gem_original_require11 (0.3%)

of 28 (0.7%)

53

49

24

46

40

43

Post.retrieve_connection2 (0.1%)

of 35 (0.9%)

35

39

19

ActiveRecordRelation#initialize_copy

38 (1.0%)

38

17

12

37

33

Module#new_constants_in1 (0.0%)

of 32 (0.8%)

52

52

61

30

27

44

26

4

19

22

Thursday, November 11, 2010

Page 207: ZOMG WHY IS THIS CODE SO SLOW

/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/bin/rubyTotal samples: 3794Focusing on: 3794Dropped nodes with <= 18 abs(samples)Dropped edges with <= 3 samples

Integer#times41 (1.1%)

of 2720 (71.7%)

Object#find48 (1.3%)

of 2718 (71.6%)

2666

SQLite3Statement#get_metadata

14 (0.4%)of 40 (1.1%)

13

Object#find_with_ids71 (1.9%)

of 2717 (71.6%)

2656

Array#each30 (0.8%)

of 459 (12.1%)

12

Object#find_one28 (0.7%)

of 2648 (69.8%)

2646

Object#first12 (0.3%)

of 2432 (64.1%)

2407

Object#where196 (5.2%)

of 275 (7.2%)

182

ArelAttribute#eq

1 (0.0%)of 31 (0.8%)

31

Object#find_first18 (0.5%)

of 2468 (65.1%)

ActiveRecordRelation#to_a

35 (0.9%)of 2312 (60.9%)

2310

Object#limit125 (3.3%)

of 140 (3.7%)

140

2420

Post.find_by_sql97 (2.6%)

of 1065 (28.1%)

1059

Object#arel18 (0.5%)

of 666 (17.6%)

666

Object#to_sql35 (0.9%)

of 627 (16.5%)

551

Object#select_all13 (0.3%)

of 845 (22.3%)

825

Array#collect!1 (0.0%)

of 135 (3.6%)

135

Post.instantiate65 (1.7%)

of 69 (1.8%)

69

Post.connection5 (0.1%)

of 40 (1.1%)

40

Post.sanitize_sql33 (0.9%)

33

836

ActiveRecordConnectionAdapters

SQLiteAdapter#select40 (1.1%)

of 832 (21.9%)

832

garbage_collector840 (22.1%)

ActiveRecordConnectionAdapters

SQLiteAdapter#execute50 (1.3%)

of 759 (20.0%)

759

Array#map13 (0.3%)

of 136 (3.6%)

66

Hash#each27 (0.7%)

of 51 (1.3%)

51

Class#new632 (16.7%)

of 806 (21.2%)

ArelProject#initialize

60 (1.6%)of 149 (3.9%)

149

ArelWhere#initialize

20 (0.5%)of 37 (1.0%)

37

ArelTake#initialize

32 (0.8%)

32

ActiveRecordConnectionAdaptersAbstractAdapter#log

16 (0.4%)of 732 (19.3%)

732

SQLite3Database#execute

49 (1.3%)of 630 (16.6%)

630653

ActiveSupportNotifications

Instrumenter#instrument3 (0.1%)

of 722 (19.0%)

722 659

Time.now31 (0.8%)

31

ActiveSupportNotifications

Fanout#publish7 (0.2%)

of 29 (0.8%)

29

Object#build_arel91 (2.4%)

of 648 (17.1%)

648

371

93

ArelPredicates

Binary#to_sql10 (0.3%)

of 235 (6.2%)

235

Object#build_select12 (0.3%)

of 174 (4.6%)

174

Object#take0 (0.0%)

of 37 (1.0%)

37

SQLite3Database#prepare

18 (0.5%)of 620 (16.3%)

620

Object#map10 (0.3%)

of 178 (4.7%)

166

SQLite3Database#ordered_map_for

52 (1.4%)of 76 (2.0%)

76

SQLite3Statement#columns

8 (0.2%)of 48 (1.3%)

48

ArelSqlCompiler

GenericCompiler#select_sql100 (2.6%)

of 496 (13.1%)

496

ArelSql

Attribute#scalar8 (0.2%)

of 71 (1.9%)

71

Object#compiler3 (0.1%)

of 25 (0.7%)

25

364

238

ArelSqlCompiler

GenericCompiler#build_clauses95 (2.5%)

of 256 (6.7%)

256

Object#from_clauses5 (0.1%)

of 122 (3.2%)

122

12

356

19

Object#each_with_index18 (0.5%)

of 28 (0.7%)

20

54

Object#clone1 (0.0%)

of 39 (1.0%)

24

ArelSql

Engine#connection7 (0.2%)

of 106 (2.8%)

23

Object#where_clauses6 (0.2%)

of 70 (1.8%)

70

Object#group_clauses5 (0.1%)

of 25 (0.7%)

25

ArelAttribute#to_sql

14 (0.4%)of 114 (3.0%)

114

ArelAttribute#format

4 (0.1%)of 110 (2.9%)

110

101

SQLite3Statement#each

50 (1.3%)of 166 (4.4%)

166

Object#project1 (0.0%)

of 159 (4.2%)

159

103

Object#loop13 (0.3%)

of 165 (4.3%)

164 151

158

49

46

Object#bind2 (0.1%)

of 48 (1.3%)

36

15

60

42

14

134

ArelCompound#table_sql

13 (0.3%)of 112 (3.0%)

112

18

ArelSql

WhereCondition#attribute9 (0.2%)

of 82 (2.2%)

82 24

Object#table_sql11 (0.3%)

of 75 (2.0%)

75

30

76

ActiveRecordBase.connection

5 (0.1%)of 99 (2.6%)

99

ActiveRecordBase.retrieve_connection

32 (0.8%)of 94 (2.5%)

94

ActiveRecordConnectionAdapters

ConnectionHandler#retrieve_connection23 (0.6%)

of 96 (2.5%)

ActiveRecordConnectionAdapters

ConnectionHandler#retrieve_connection_pool52 (1.4%)

52

62

ArelSql

Formatter#quote_table_name11 (0.3%)

of 66 (1.7%)

34

ArelSql

Formatter#name_for20 (0.5%)

of 39 (1.0%)

12

ArelSql

Formatter#quote_column_name8 (0.2%)

of 27 (0.7%)

27

28

ArelSql

TableReference#table5 (0.1%)

of 64 (1.7%)

64

ArelSql

Formatter#quote17 (0.4%)

of 39 (1.0%)

39

ArelAttribute#column

8 (0.2%)of 24 (0.6%)

24

ArelCompound#wheres

12 (0.3%)of 64 (1.7%)

64

45

33

Array#collect3 (0.1%)

of 52 (1.4%)

52

ArelValue#bind

2 (0.1%)of 45 (1.2%)

45

32 27

Object#require10 (0.3%)

of 60 (1.6%)54

Object#load_dependency0 (0.0%)

of 32 (0.8%)

60

Kernel#gem_original_require11 (0.3%)

of 28 (0.7%)

53

49

24

46

40

43

Post.retrieve_connection2 (0.1%)

of 35 (0.9%)

35

39

19

ActiveRecordRelation#initialize_copy

38 (1.0%)

38

17

12

37

33

Module#new_constants_in1 (0.0%)

of 32 (0.8%)

52

52

61

30

27

44

26

4

19

22

Thursday, November 11, 2010

Page 208: ZOMG WHY IS THIS CODE SO SLOW

Data StructureAnalysis

Thursday, November 11, 2010

Page 209: ZOMG WHY IS THIS CODE SO SLOW

Graphvizgraphviz.org

Thursday, November 11, 2010

Page 210: ZOMG WHY IS THIS CODE SO SLOW

digraph "foo" { node [width=0.375,height=0.25]; N1 [label="hello"]; N2 [label="world"]; N1 -> N2;}

Thursday, November 11, 2010

Page 211: ZOMG WHY IS THIS CODE SO SLOW

hello

world

Thursday, November 11, 2010

Page 212: ZOMG WHY IS THIS CODE SO SLOW

Visitor Pattern

Thursday, November 11, 2010

Page 213: ZOMG WHY IS THIS CODE SO SLOW

class Visitor def accept(object) method = object.class.name.split('::').join('_') send("visit_#{method}", object) endend

Thursday, November 11, 2010

Page 214: ZOMG WHY IS THIS CODE SO SLOW

class Visitor def accept(object) method = object.class.name.split('::').join('_') send("visit_#{method}", object) end

def visit_Arel_Alias(node) # keep track of the node called accept(node.attribute) endend

Thursday, November 11, 2010

Page 215: ZOMG WHY IS THIS CODE SO SLOW

class Visitor def accept(object) method = object.class.name.split('::').join('_') send("visit_#{method}", object) end

def visit_Arel_Alias(node) # keep track of the node called accept(node.attribute) end

def visit_Arel_Table(node) # keep track of the node called accept(node.name) node.columns.each { |c| accept(c) } endend

Thursday, November 11, 2010

Page 216: ZOMG WHY IS THIS CODE SO SLOW

Thursday, November 11, 2010

Page 217: ZOMG WHY IS THIS CODE SO SLOW

Thursday, November 11, 2010

Page 218: ZOMG WHY IS THIS CODE SO SLOW

Linked List

Thursday, November 11, 2010

Page 219: ZOMG WHY IS THIS CODE SO SLOW

Relation Relation Relation Relation

value valuevalue value

Thursday, November 11, 2010

Page 220: ZOMG WHY IS THIS CODE SO SLOW

Relation Relation Relation Relation

value valuevalue value

Thursday, November 11, 2010

Page 221: ZOMG WHY IS THIS CODE SO SLOW

Relation Relation Relation Relation

Bind() + Dup

Bind() + Dup

Bind() + Dup

Bind() + Dup

Thursday, November 11, 2010

Page 222: ZOMG WHY IS THIS CODE SO SLOW

Relation Relation Relation Relation

Bind() + Dup

Bind() + Dup

Bind() + Dup

Bind() + Dup

Bind() + Dup

Bind() + Dup

Bind() + Dup

Bind() + Dup

Bind() + Dup

Bind() + Dup

Thursday, November 11, 2010

Page 223: ZOMG WHY IS THIS CODE SO SLOW

Where Where Where Where

1 = 1 3 = 32 = 2 4 = 4

Thursday, November 11, 2010

Page 224: ZOMG WHY IS THIS CODE SO SLOW

Where Where Where Where

1 = 1 3 = 32 = 2 4 = 4

2 = 2

3 = 3

1 = 1

1 = 1

2 = 21 = 1

Thursday, November 11, 2010

Page 225: ZOMG WHY IS THIS CODE SO SLOW

Big O!

Thursday, November 11, 2010

Page 226: ZOMG WHY IS THIS CODE SO SLOW

OMG

Thursday, November 11, 2010

Page 227: ZOMG WHY IS THIS CODE SO SLOW

ZOMG

Thursday, November 11, 2010

Page 228: ZOMG WHY IS THIS CODE SO SLOW

Mathematical Representation

Thursday, November 11, 2010

Page 229: ZOMG WHY IS THIS CODE SO SLOW

0

1.25

2.5

3.75

5

0 2.25 4.5 6.75 9

y = 2

Thursday, November 11, 2010

Page 230: ZOMG WHY IS THIS CODE SO SLOW

0

1.25

2.5

3.75

5

1 4.5 8 11.5 15

y = log(n)

Thursday, November 11, 2010

Page 231: ZOMG WHY IS THIS CODE SO SLOW

0

2.25

4.5

6.75

9

0 2.25 4.5 6.75 9

y = x

Thursday, November 11, 2010

Page 232: ZOMG WHY IS THIS CODE SO SLOW

-10

0

10

20

30

40

1 4.5 8 11.5 15

y = n log(n)

Thursday, November 11, 2010

Page 233: ZOMG WHY IS THIS CODE SO SLOW

0

50

100

150

200

0 3.75 7.5 11.25 15

y = n^2

Thursday, November 11, 2010

Page 234: ZOMG WHY IS THIS CODE SO SLOW

Finding Big O

•Give input

•Measure output

• Plot Results

Thursday, November 11, 2010

Page 235: ZOMG WHY IS THIS CODE SO SLOW

ARel's Big O

0

12.5

25

37.5

50

0 2.25 4.5 6.75 9

objects and funcalls

Thursday, November 11, 2010

Page 236: ZOMG WHY IS THIS CODE SO SLOW

ARel's Big O

0

12.5

25

37.5

50

0 2.25 4.5 6.75 9

objects and funcalls

Thursday, November 11, 2010

Page 237: ZOMG WHY IS THIS CODE SO SLOW

ARel's Big O

0

12.5

25

37.5

50

0 2.25 4.5 6.75 9

objects and funcalls

Thursday, November 11, 2010

Page 238: ZOMG WHY IS THIS CODE SO SLOW

ARel's Big O

0

12.5

25

37.5

50

0 2.25 4.5 6.75 9

objects and funcalls

Thursday, November 11, 2010

Page 239: ZOMG WHY IS THIS CODE SO SLOW

ARel's Big O

0

12.5

25

37.5

50

0 2.25 4.5 6.75 9

objects and funcalls

Thursday, November 11, 2010

Page 240: ZOMG WHY IS THIS CODE SO SLOW

Thursday, November 11, 2010

Page 241: ZOMG WHY IS THIS CODE SO SLOW

Thursday, November 11, 2010

Page 242: ZOMG WHY IS THIS CODE SO SLOW

ActiveRecord/Arel takes over 2

minutes to generate a pseudo-complex

SQL query.http://bit.ly/omgslow2

Thursday, November 11, 2010

Page 243: ZOMG WHY IS THIS CODE SO SLOW

Deep Improvements

Thursday, November 11, 2010

Page 244: ZOMG WHY IS THIS CODE SO SLOW

Kow

ledg

e / I

mpr

ovem

ent

TimeImprovements (S) System Knowledge

System Impact

Thursday, November 11, 2010

Page 245: ZOMG WHY IS THIS CODE SO SLOW

AST + Visitor

Thursday, November 11, 2010

Page 246: ZOMG WHY IS THIS CODE SO SLOW

O(n)

Thursday, November 11, 2010

Page 247: ZOMG WHY IS THIS CODE SO SLOW

Should I rewrite?

•Clear solution

• Tests are numerous (Rails)

• Public API is limited

Thursday, November 11, 2010

Page 248: ZOMG WHY IS THIS CODE SO SLOW

YES

Thursday, November 11, 2010

Page 249: ZOMG WHY IS THIS CODE SO SLOW

6 Weeks Later...

Thursday, November 11, 2010

Page 250: ZOMG WHY IS THIS CODE SO SLOW

ARel Today

Thursday, November 11, 2010

Page 251: ZOMG WHY IS THIS CODE SO SLOW

Data Sheet

•O(n)

• 6 Weeks to Rewrite

• 2x faster (for simple queries)

• Adapter Specific code is DRY

Thursday, November 11, 2010

Page 252: ZOMG WHY IS THIS CODE SO SLOW

flog (before)

2533.1: flog total 6.8: flog/method average

116.6: OracleCompiler#select_sql 78.0: PostgreSQLCompiler#select_sql 64.9: main#none 59.4: GenericCompiler#insert_sql 52.4: Join#joins

Thursday, November 11, 2010

Page 253: ZOMG WHY IS THIS CODE SO SLOW

flog (after)

1864.6: flog total 6.5: flog/method average

81.4: main#none 75.9: Dot#none 59.1: Oracle# lib/arel/visitors/oracle.rb:6 54.0: ToSql#lib/arel/visitors/to_sql.rb:31 51.6: ToSql#none

Thursday, November 11, 2010

Page 254: ZOMG WHY IS THIS CODE SO SLOW

flay (before)

Total score (lower is better) = 684

12 complaints

Thursday, November 11, 2010

Page 255: ZOMG WHY IS THIS CODE SO SLOW

flay (after)

Total score (lower is better) = 420

7 complaints

Thursday, November 11, 2010

Page 256: ZOMG WHY IS THIS CODE SO SLOW

Post.where("id = 1").to_dot

Thursday, November 11, 2010

Page 257: ZOMG WHY IS THIS CODE SO SLOW

Arel::Nodes::SelectStatement

Array

cores

NilClass

offset limit

Array

orders

Arel::Nodes::SelectCore

0

Arel::Table

froms

Array

projections

Array

wheres

String posts

name

Arel::Nodes::SqlLiteral "posts".*

0

Arel::Nodes::Grouping

0

Arel::Nodes::SqlLiteral id = 1

expr

Thursday, November 11, 2010

Page 258: ZOMG WHY IS THIS CODE SO SLOW

ARel Tomorrow

Thursday, November 11, 2010

Page 259: ZOMG WHY IS THIS CODE SO SLOW

Conclusion

Thursday, November 11, 2010

Page 260: ZOMG WHY IS THIS CODE SO SLOW

AKA:Things I've Learned

Thursday, November 11, 2010

Page 261: ZOMG WHY IS THIS CODE SO SLOW

Kow

ledg

e / I

mpr

ovem

ent

TimeImprovements (S) System Knowledge Improvements (D)

System Impact

Thursday, November 11, 2010

Page 262: ZOMG WHY IS THIS CODE SO SLOW

When Should I Rewrite?

Thursday, November 11, 2010

Page 263: ZOMG WHY IS THIS CODE SO SLOW

Rewrite Timeline

Thursday, November 11, 2010

Page 264: ZOMG WHY IS THIS CODE SO SLOW

Rewrite Timeline

Thursday, November 11, 2010

Page 265: ZOMG WHY IS THIS CODE SO SLOW

We emphasizethe artof Code

Thursday, November 11, 2010

Page 266: ZOMG WHY IS THIS CODE SO SLOW

We should not forgetthe Science

Thursday, November 11, 2010

Page 267: ZOMG WHY IS THIS CODE SO SLOW

LearnThe Specific

Thursday, November 11, 2010

Page 268: ZOMG WHY IS THIS CODE SO SLOW

But EmbraceThe Generic

Thursday, November 11, 2010

Page 270: ZOMG WHY IS THIS CODE SO SLOW

Thanks @ebiltwin

Thursday, November 11, 2010

Page 271: ZOMG WHY IS THIS CODE SO SLOW

Thank you!

Thursday, November 11, 2010

Page 272: ZOMG WHY IS THIS CODE SO SLOW

One More Thing...

Thursday, November 11, 2010

Page 273: ZOMG WHY IS THIS CODE SO SLOW

It's RubyConf 10!

Thursday, November 11, 2010

Page 274: ZOMG WHY IS THIS CODE SO SLOW

Give Ryan a Kiss!<3

Thursday, November 11, 2010

Page 275: ZOMG WHY IS THIS CODE SO SLOW

Thursday, November 11, 2010

Page 276: ZOMG WHY IS THIS CODE SO SLOW

♥Thursday, November 11, 2010

Page 277: ZOMG WHY IS THIS CODE SO SLOW

Questions?

Thursday, November 11, 2010