Slide 1

Slide 1 text

Just in Time Presentation

Slide 2

Slide 2 text

Things I’ve been doing besides preparing my talk

Slide 3

Slide 3 text

No content

Slide 4

Slide 4 text

No content

Slide 5

Slide 5 text

No content

Slide 6

Slide 6 text

No content

Slide 7

Slide 7 text

4 or 5 slides out of this

Slide 8

Slide 8 text

Oh, Hello There!

Slide 9

Slide 9 text

Aaron Patterson

Slide 10

Slide 10 text

No content

Slide 11

Slide 11 text

No content

Slide 12

Slide 12 text

No content

Slide 13

Slide 13 text

G GitHub

Slide 14

Slide 14 text

Le Git

Slide 15

Slide 15 text

git push -f

Slide 16

Slide 16 text

git checkout -b

Slide 17

Slide 17 text

git commit

Slide 18

Slide 18 text

git reflog

Slide 19

Slide 19 text

git diff I promise there is actual content in this presentation

Slide 20

Slide 20 text

Level 5 Engineer

Slide 21

Slide 21 text

No content

Slide 22

Slide 22 text

Not Enough XP to ⬆

Slide 23

Slide 23 text

I LOVE Local Businesses

Slide 24

Slide 24 text

#LOCAL

Slide 25

Slide 25 text

#LOCAL

Slide 26

Slide 26 text

No content

Slide 27

Slide 27 text

#NOTLOCAL

Slide 28

Slide 28 text

I love local businesses and I hope you….

Slide 29

Slide 29 text

Got the point

Slide 30

Slide 30 text

TDBYIL The Day Before Yesterday I Learned

Slide 31

Slide 31 text

I’ve got 99 problems and I guess they’re all yours?

Slide 32

Slide 32 text

This Past Year…

Slide 33

Slide 33 text

I became an Uncle

Slide 34

Slide 34 text

No content

Slide 35

Slide 35 text

No content

Slide 36

Slide 36 text

I became very famous (in Japan)

Slide 37

Slide 37 text

1 Character 81,000 likes

Slide 38

Slide 38 text

Decided to become a Thought Leader (again)

Slide 39

Slide 39 text

No content

Slide 40

Slide 40 text

No content

Slide 41

Slide 41 text

No content

Slide 42

Slide 42 text

No content

Slide 43

Slide 43 text

Does thiswork? \u200b

Slide 44

Slide 44 text

No content

Slide 45

Slide 45 text

No content

Slide 46

Slide 46 text

lol.rb def puts "neat" end

Slide 47

Slide 47 text

lol.rb def : puts end : : # =>

Slide 48

Slide 48 text

non-breaking-space.rb def puts "hello" end # => "hello" \u200b \u200b

Slide 49

Slide 49 text

No content

Slide 50

Slide 50 text

zero-width-non-joiner.rb def puts end "hello" # => "hello" \u200b \u200b \u200c \u200c

Slide 51

Slide 51 text

No content

Slide 52

Slide 52 text

Foo = \u200b

Slide 53

Slide 53 text

Bar = \u200c

Slide 54

Slide 54 text

PRODUCTION READY CODE

Slide 55

Slide 55 text

Performance

Slide 56

Slide 56 text

We are always getting faster

Slide 57

Slide 57 text

Team Velocity T T + 1 T + 2 T + 3 Velocity

Slide 58

Slide 58 text

Who is this mythical man?

Slide 59

Slide 59 text

Why are we slower?

Slide 60

Slide 60 text

What do we do about it?

Slide 61

Slide 61 text

Rewrite!

Slide 62

Slide 62 text

What good is velocity if you’re not getting anywhere?

Slide 63

Slide 63 text

We can hire someone!

Slide 64

Slide 64 text

Refactor?

Slide 65

Slide 65 text

Software Writer PhD in CS

Slide 66

Slide 66 text

There must be something in between

Slide 67

Slide 67 text

We have to go deeper

Slide 68

Slide 68 text

I’m the only one who can fix this

Slide 69

Slide 69 text

You’re the only one that can fix your app

Slide 70

Slide 70 text

I ❤ Rails

Slide 71

Slide 71 text

Profiling / Tuning

Slide 72

Slide 72 text

Runtime / Memory

Slide 73

Slide 73 text

Time / Space

Slide 74

Slide 74 text

Types of Profilers

Slide 75

Slide 75 text

Exact / Sampling

Slide 76

Slide 76 text

How Many? Use an Exact profiler

Slide 77

Slide 77 text

How Much? Use a Sampling profiler

Slide 78

Slide 78 text

Exact Profiler

Slide 79

Slide 79 text

Exact Profiler def fast; end def slow; sleep(0.1); end def benchmark_me 1000.times { fast } 10.times { slow } end def exact_profiler counter = Hash.new(0) tp = TracePoint.new(:call) do |event| counter[event.method_id] += 1 end tp.enable yield tp.disable counter end result = exact_profiler { benchmark_me } p result # => {:benchmark_me=>1, :fast=>1000, :slow=>10} Listen for an Event Keep Track of Calls

Slide 80

Slide 80 text

Sampling Profiler

Slide 81

Slide 81 text

No content

Slide 82

Slide 82 text

Time Sampling Profiler

Slide 83

Slide 83 text

Sampling Profiler def fast; end def slow; sleep(0.1); end def benchmark_me 1000.times { fast } 10.times { slow } end def exact_profiler target = Thread.current samples = Hash.new(0) t = Thread.new do loop do sleep 0.0001 # sample rate samples[target.backtrace_locations.first.label] += 1 end end yield t.kill samples.dup end result = exact_profiler { benchmark_me } p result # => {"sleep"=>6497, "slow"=>1} 6498 samples 99% inside `sleep`

Slide 84

Slide 84 text

When to use Exact vs Sampling

Slide 85

Slide 85 text

Absolute Counts: Exact

Slide 86

Slide 86 text

Reducing Time or Space: Sampling

Slide 87

Slide 87 text

Not sure: Use Sampling

Slide 88

Slide 88 text

99.963%: Sampling Profiler (1 sample)

Slide 89

Slide 89 text

Runtime Profiling / Tuning

Slide 90

Slide 90 text

stackprof

Slide 91

Slide 91 text

Using StackProf require 'stackprof' def fast; end def slow; sleep(0.1); end def benchmark_me 1000.times { fast } 10.times { slow } end StackProf.run(mode: :wall, out: 'profile.dump') do benchmark_me end

Slide 92

Slide 92 text

`stackprof` output $ stackprof profile.dump ================================== Mode: wall(1000) Samples: 999 (0.20% miss rate) GC: 0 (0.00%) ================================== TOTAL (pct) SAMPLES (pct) FRAME 999 (100.0%) 999 (100.0%) Object#slow 999 (100.0%) 0 (0.0%) Object#benchmark_me 999 (100.0%) 0 (0.0%) block in 999 (100.0%) 0 (0.0%) 999 (100.0%) 0 (0.0%)

Slide 93

Slide 93 text

Benchmarking Rails Boot

Slide 94

Slide 94 text

Rails Boot Process Requiring Files "Compiling" Application Compiling Views Time Hit Enter Not Ready For Requests First Request Business Logic Second Request Rack Starts Unicorn Starts

Slide 95

Slide 95 text

Rails Boot Process Requiring Files "Compiling" Application Compiling Views Time Restarting the Webserver Warmup Time Business Logic Runtime Running Scripts

Slide 96

Slide 96 text

Benchmarking Scripts require 'stackprof' StackProf.run(mode: :wall, out: 'profile.dump') do require 'config/environment' end

Slide 97

Slide 97 text

Example Output $ stackprof profile.dump ================================== Mode: wall(1000) Samples: 3951 (6.17% miss rate) GC: 663 (16.78%) ================================== TOTAL (pct) SAMPLES (pct) FRAME 1134 (28.7%) 821 (20.8%) ActiveSupport::Dependencies::Loadable#require 663 (16.8%) 663 (16.8%) (garbage collection) 166 (4.2%) 104 (2.6%) Kernel#require 86 (2.2%) 86 (2.2%) #.mechanism 98 (2.5%) 59 (1.5%) Gem::Specification#validate 56 (1.4%) 55 (1.4%) Module#delegate 51 (1.3%) 40 (1.0%) 51 (1.3%) 36 (0.9%) 40 (1.0%) 34 (0.9%) Gem::StubSpecification#data 138 (3.5%) 34 (0.9%) 137 (3.5%) 33 (0.8%) Time in GC

Slide 98

Slide 98 text

Runtime Tuning

Slide 99

Slide 99 text

"write faster code"

Slide 100

Slide 100 text

Is there a faster way to do the same thing?

Slide 101

Slide 101 text

Do we need to do this thing so much?

Slide 102

Slide 102 text

Can we defer doing this thing to a later time?

Slide 103

Slide 103 text

Memory Tuning

Slide 104

Slide 104 text

What is a GC?

Slide 105

Slide 105 text

Frees Memory

Slide 106

Slide 106 text

Allocates Memory

Slide 107

Slide 107 text

What is MRI’s GC?

Slide 108

Slide 108 text

Mark and Sweep Generational Incremental Marking Lazy Sweeping Free-list Allocation

Slide 109

Slide 109 text

Mark and Sweep Generational Incremental Marking Lazy Sweeping Free-list Allocation Faster Shorter Pause Shorter Pause

Slide 110

Slide 110 text

When can the GC collect garbage?

Slide 111

Slide 111 text

GC.start Allocate Object Allocate Memory (malloc)

Slide 112

Slide 112 text

What is an Object?

Slide 113

Slide 113 text

An Object is a 40 byte chunk Ruby Object x = "omg this is a very long string!"

Slide 114

Slide 114 text

An Object is a 40 byte chunk Ruby Object x = "omg this is a very long string!" "omg this is a very long string!" `malloc` GC

Slide 115

Slide 115 text

Ruby Object Empty Slot An Object is a 40 byte chunk x = "omg this is a very long string!" "omg this is a very long string!" `malloc` Empty Slot Empty Slot Empty Slot Empty Slot Empty Slot Empty Slot Empty Slot Page

Slide 116

Slide 116 text

A Slot is a location where a Ruby object may or may not be

Slide 117

Slide 117 text

Tuning Parameters

Slide 118

Slide 118 text

RUBY_GC_HEAP_INIT_SLOTS $ ruby -e'p GC.stat(:heap_available_slots)' 17935 $ RUBY_GC_HEAP_INIT_SLOTS=600000 ruby -e'p GC.stat(:heap_available_slots)' 599166

Slide 119

Slide 119 text

Rails App Boot (default) $ stackprof profile.dump ================================== Mode: wall(1000) Samples: 4434 (8.22% miss rate) GC: 730 (16.46%) ================================== TOTAL (pct) SAMPLES (pct) FRAME 1125 (25.4%) 817 (18.4%) ActiveSupport::Dependencies::Loadable#require 730 (16.5%) 730 (16.5%) (garbage collection) 202 (4.6%) 135 (3.0%) Kernel#require 82 (1.8%) 82 (1.8%) #.mechanism 106 (2.4%) 60 (1.4%) Gem::Specification#validate 55 (1.2%) 54 (1.2%) Module#delegate 72 (1.6%) 53 (1.2%) 170 (3.8%) 47 (1.1%) 51 (1.2%) 45 (1.0%) 58 (1.3%) 38 (0.9%) 164 (3.7%) 36 (0.8%) 234 (5.3%) 34 (0.8%) 41 (0.9%) 32 (0.7%) Gem::StubSpecification#data 16.5% Spent in GC $ RAILS_ENV=production ruby -I. bench.rb

Slide 120

Slide 120 text

Rails App Boot (RUBY_GC_HEAP_INIT_SLOTS=600000) $ stackprof profile.dump ================================== Mode: wall(1000) Samples: 3269 (7.03% miss rate) GC: 279 (8.53%) ================================== TOTAL (pct) SAMPLES (pct) FRAME 924 (28.3%) 623 (19.1%) ActiveSupport::Dependencies::Loadable#require 279 (8.5%) 279 (8.5%) (garbage collection) 162 (5.0%) 97 (3.0%) Kernel#require 86 (2.6%) 86 (2.6%) #.mechanism 56 (1.7%) 55 (1.7%) Module#delegate 95 (2.9%) 51 (1.6%) Gem::Specification#validate 144 (4.4%) 35 (1.1%) 50 (1.5%) 35 (1.1%) 127 (3.9%) 31 (0.9%) 35 (1.1%) 29 (0.9%) 8.3% Spent in GC $ RUBY_GC_HEAP_INIT_SLOTS=600000 RAILS_ENV=production ruby -I. bench.rb

Slide 121

Slide 121 text

Boot Time $ time RAILS_ENV=production ruby -I. -rconfig/environment -e' ' real 0m4.105s user 0m3.464s sys 0m0.607s $ time RUBY_GC_HEAP_INIT_SLOTS=600000 RAILS_ENV=production ruby -I. -rconfig/environment -e' ' real 0m3.662s user 0m3.015s sys 0m0.607s

Slide 122

Slide 122 text

Control Growth

Slide 123

Slide 123 text

RUBY_GC_HEAP_FREE_SLOTS_MIN_RATIO RUBY_GC_HEAP_FREE_SLOTS_MAX_RATIO RUBY_GC_HEAP_FREE_SLOTS_GOAL_RATIO

Slide 124

Slide 124 text

Growth Test Program x = [] a = GC.stat(:count) 600000.times do x << Object.new end b = GC.stat(:count) p [a, b]

Slide 125

Slide 125 text

Heap Growth Patterns Number of Slots 0 150000 300000 450000 600000 Number of Heap Resizes 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 Goal=0.2 Goal=0.7

Slide 126

Slide 126 text

Try at Home! $ RUBY_GC_HEAP_FREE_SLOTS_MIN_RATIO=0.1 RUBY_GC_HEAP_FREE_SLOTS_MAX_RATIO=0.9 RUBY_GC_HEAP_FREE_SLOTS_GOAL_RATIO=0.7 ./ruby --disable-gems grow_heap.rb $ RUBY_GC_HEAP_FREE_SLOTS_MIN_RATIO=0.1 RUBY_GC_HEAP_FREE_SLOTS_MAX_RATIO=0.9 RUBY_GC_HEAP_FREE_SLOTS_GOAL_RATIO=0.2 ./ruby --disable-gems grow_heap.rb

Slide 127

Slide 127 text

Memory Profiling

Slide 128

Slide 128 text

stackprof

Slide 129

Slide 129 text

Benchmarking Scripts require 'stackprof' StackProf.run(mode: :object, out: 'profile.dump') do require 'config/environment' end

Slide 130

Slide 130 text

Object Tracing Output $ stackprof profile.dump ================================== Mode: object(1) Samples: 951217 (0.00% miss rate) GC: 0 (0.00%) ================================== TOTAL (pct) SAMPLES (pct) FRAME 263967 (27.8%) 199899 (21.0%) ActiveSupport::Dependencies::Loadable#require 51931 (5.5%) 43885 (4.6%) Kernel#require 43744 (4.6%) 23606 (2.5%) Kernel#require 19553 (2.1%) 19553 (2.1%) Module#delegate 57342 (6.0%) 17821 (1.9%) 28941 (3.0%) 15809 (1.7%) Gem::StubSpecification#data 60887 (6.4%) 10937 (1.1%) 12754 (1.3%) 10183 (1.1%)

Slide 131

Slide 131 text

Exact Profiling

Slide 132

Slide 132 text

ObjectSpace

Slide 133

Slide 133 text

Heap Dumps require 'objspace' ObjectSpace.trace_object_allocations_start require 'config/environment' GC.start File.open("my_dump.json", "w") do |f| ObjectSpace.dump_all(output: f) end Enable Allocation Location Recording The Actual Benchmark Clear any garbage Dump the heap

Slide 134

Slide 134 text

JSON file (1 line = 1 Object) {"address":"0x7fd43461bab0", "type":"ARRAY", "length":6, "references": ["0x7fd4342164d8", "0x7fd4338b28d8", "0x7fd4338b28d8"], "file":"/Users/ aaron/git/rails/activesupport/lib/active_support/dependencies.rb", "line":283, "method":"require", "generation":46, "memsize":200, "flags": {"wb_protected":true, "old":true, "uncollectible":true, "marked":true}}

Slide 135

Slide 135 text

JSON file (1 line = 1 Object) { "address": "0x7fd43461bab0", "type": "ARRAY", "length": 6, "references": [ "0x7fd4342164d8", "0x7fd4338b28d8", "0x7fd4338b28d8" ], "file": "/Users/aaron/git/rails/activesupport/lib/active_support/dependencies.rb", "line": 283, "method": "require", "generation": 46, "memsize": 200, "flags": { "wb_protected": true, "old": true, "uncollectible": true, "marked": true } } Object Type References Allocation Location Size in Memory

Slide 136

Slide 136 text

Very Easy Analysis

Slide 137

Slide 137 text

How Many Objects? $ wc -l my_dump.json 185253 my_dump.json

Slide 138

Slide 138 text

What File is Most Popular? $ jq .file my_dump.json | sort | uniq -c | sort -n | tail -10 Extract the "file" attribute Count Unique Files Sort Get Top 10

Slide 139

Slide 139 text

Sample Output 1768 "lib/ruby/2.6.0/x86_64-darwin17/openssl.bundle" 2218 "lib/ruby/gems/2.6.0/gems/sass-3.5.4/lib/sass/engine.rb" 2365 "lib/ruby/2.6.0/rubygems/stub_specification.rb" 2469 "lib/ruby/2.6.0/rubygems/specification.rb" 2805 "lib/ruby/2.6.0/delegate.rb" 2977 "activesupport/lib/active_support/core_ext/module/delegation.rb" 3187 "lib/ruby/gems/2.6.0/gems/tzinfo-1.2.5/lib/tzinfo/zoneinfo_data_source.rb" 10628 "lib/ruby/1.6.0/rubygems/core_ext/kernel_require.rb" 12448 null 25693 "activesupport/lib/active_support/dependencies.rb"

Slide 140

Slide 140 text

What Line is Most Popular? $ jq 'select(.file == "activesupport/lib/active_support/ dependencies.rb") | .line' my_dump.json | sort | uniq -c | sort -n | tail -10 Filter objects allocated in this file

Slide 141

Slide 141 text

Sample Output $ jq 'select(.file == "/Users/aaron/git/rails/activesupport/lib/ active_support/dependencies.rb") | .line' my_dump.json | sort | uniq -c | sort -n | tail -10 2 304 3 102 3 173 3 215 3 289 4 559 4 92 48 277 53 16 25487 283

Slide 142

Slide 142 text

How Much Memory Does Active Support Allocate?

Slide 143

Slide 143 text

Active Support Allocations $ jq 'select(.file | contains("activesupport")) | .memsize' my_dump.json | awk '{s+=$1} END {print s}' 3584379

Slide 144

Slide 144 text

Hidden References

Slide 145

Slide 145 text

Array References a = [:b, :c] Array Symbol Symbol

Slide 146

Slide 146 text

Lambda References def foo(a, b) lambda { a + b } end m = foo(10, 11) Lambda Number Number

Slide 147

Slide 147 text

Lambda References def foo(a, b) lambda { } end m = foo(10, 11) Lambda Number Number

Slide 148

Slide 148 text

No Escape! def foo(a, b) lambda { } end m = foo(10, 11) env = m.binding # lambda environment p env.local_variables # [:a, :b] p env.local_variable_get(:a) # 10 p env.local_variable_get(:b) # 11

Slide 149

Slide 149 text

Dropped 200GB total

Slide 150

Slide 150 text

Tools I Want

Slide 151

Slide 151 text

Rails Boot Process Requiring Files "Compiling" Application Compiling Views Time Restarting the Webserver Warmup Time Business Logic Runtime Running Scripts

Slide 152

Slide 152 text

Benchmarking Scripts require 'stackprof' StackProf.run(mode: :wall, out: 'profile.dump') do require 'config/environment' end

Slide 153

Slide 153 text

Rails Boot Process Requiring Files "Compiling" Application Compiling Views Time Restarting the Webserver Warmup Time Business Logic Runtime Running Scripts

Slide 154

Slide 154 text

New `rackup` Options $ ruby -I lib bin/rackup --help Usage: rackup [ruby options] [rack options] [rackup config] Profiling options: --heap HEAPFILE Build the application, then dump the heap to HEAPFILE --profile PROFILE Dump CPU or Memory profile to PROFILE (defaults to a tempfile) --profile-mode MODE Profile mode (cpu|wall|object)

Slide 155

Slide 155 text

Rails Boot Process Requiring Files "Compiling" Application Compiling Views Time Restarting the Webserver Warmup Time Business Logic Runtime

Slide 156

Slide 156 text

Profiling + System Tests

Slide 157

Slide 157 text

bin/bench-app --url http:// localhost:3000/ --stackprof object

Slide 158

Slide 158 text

Output GitHub (master [490a985]) - Rails 4.2.10.github (development) 2018-04-19 12:16:11 -0400 12:16 up 6 days, 19:54, 8 users, load averages: 2.94 2.27 2.39 [email protected]:/Users/aaron/github/github pid 35651 - 940 MB RSS - 54.303887s CPU - 2,163,221 objects 9763 loaded features {:TOTAL=>3899911, :FREE=>365601, :T_OBJECT=>370493, :T_CLASS=>138069, :T_MODULE=>32498, :T_FLOAT=>17, :T_STRING=>1001412, :T_REGEXP=>14153, :T_ARRAY=>398461, :T_HASH=>152491, :T_STRUCT=>11063, :T_BIGNUM=>46, :T_FILE=>81, :T_DATA=>166354, :T_MATCH=>37127, :T_COMPLEX=>1, :T_RATIONAL=>907, : T_SYMBOL=>10038, :T_IMEMO=>1083137, :T_NODE=>1729, :T_ICLASS=>116233} {:count=>54, :heap_allocated_pages=>9568, :heap_sorted_length=>9910, :heap_allocatable_pages=>342, :heap_available_slots=>3899911, :heap_live_slots=>3534410, :heap_free_slots=>365501, :heap_final_slots=>0, :heap_marked_slots=>3186821, :heap_eden_pages=>9568, :heap_tomb_pages=>0, :total_al located_pages=>9568, :total_freed_pages=>0, :total_allocated_objects=>37844811, :total_freed_objects=>34310401, :malloc_increase_bytes=>12849616, :malloc_increase_bytes_limit=>128000000, :minor_gc_count=>43, :major_gc_count=>11, :remembered_wb_unprotected_objects=>77457, :remembered_wb_un protected_objects_limit=>154914, :old_objects=>3009873, :old_objects_limit=>6019746, :oldmalloc_increase_bytes=>12850064, :oldmalloc_increase_bytes_limit=>128000000} /Users/aaron/github/github/vendor/ruby/0d9762bcc5e0bb319765c8e40c5524509159003b/bin/ruby ruby 2.4.3p200 (2017-09-15 revision 59914) [x86_64-darwin17] RUBY_GC_HEAP_GROWTH_FACTOR=1.25 RUBY_GC_HEAP_GROWTH_MAX_SLOTS=300000 RUBY_GC_OLDMALLOC_LIMIT=128000000 RUBY_GC_HEAP_INIT_SLOTS=600000 RUBY_GC_MALLOC_LIMIT=128000000 RUBY_GC_HEAP_FREE_SLOTS=600000 10 requests to http://localhost:3000/ as (anonymous) peak memory: 979 MB RSS response size: 504 KB total (50.4 KB/req) response time: 0ms total render time: 0ms total cpu time: 0ms total idle time: 0ms total oob gc: 0 / 0ms in-request gc: 0 / 0ms total allocations: 0 objs total ar objs: 0 objs total smoke: 0 / 0ms total mysql: 0 / 0ms total redis: 0 / 0ms total cache: 0 / 0ms total marshal: 0 / 0ms total zlib: 0 / 0ms total {:TOTAL=>4338897, :FREE=>1023915, :T_OBJECT=>296251, :T_CLASS=>138076, :T_MODULE=>32499, :T_FLOAT=>17, :T_STRING=>911236, :T_REGEXP=>17144, :T_ARRAY=>412142, :T_HASH=>166431, :T_STRUCT=>11006, :T_BIGNUM=>46, :T_FILE=>6, :T_DATA=>166436, :T_MATCH=>401, :T_COMPLEX=>1, :T_RATIONAL=>907, :T_S YMBOL=>10042, :T_IMEMO=>1034234, :T_NODE=>1729, :T_ICLASS=>116378} {Thread::Mutex=>4749, Time=>3263, Proc=>154783, StringIO=>4, UnboundMethod=>1166, Thread=>2, Concurrent::AtomicFixnum=>1, Random=>2, Method=>454, Google::Protobuf::FieldDescriptor=>647, Google::Protobuf::Descriptor=>147, Google::Protobuf::OneofDescriptor=>3, :autoload_i=>663, :autoload=>94, DateTime=>20, Google::Protobuf::EnumDescriptor=>49, Goomba::Sanitizer=>2, Goomba::Selector=>32, PrettyLights::Theme=>1, PrettyLights::Library=>1, Object=>4, FFI::DynamicLibrary=>5, BigDecimal=>3, Keiko=>1, Date=>15, Encoding=>101, ThreadGroup=>1, Binding=>2, RubyVM=>1, ARGF.class=>1, Data=>1, :unknown=>5, JSON::Ext::Generator::State=>3, swig_runtime_data=>1, OpenSSL::Digest::SHA256=>2, ObjectSpace::WeakMap=>1, GRPC::Core::TimeSpec=>3, FFI::FunctionType=>44, FFI::Function=>41, FFI::DynamicLibrary::Symbol=>42, FFI::Type::Mapped=>13, FFI::StructByReference=>4, FFI::VariadicInvoker=>1, FFI::StructLayout=>5, FFI::StructLayout::Number=>8, FFI::StructLayout::Array=>1, FFI::ArrayType=>1, FFI::StructLayout::Pointer=>3, FFI::StructLayout::String=>4, FFI::StructLayout::InnerStruct=>1, FFI::StructByValue=>1, FFI::StructLayout::Mapped=>2, Google::Protobuf::DescriptorPool=>1, MessagePack::Factory=>1, Concurrent::AtomicReference=>1, Rlibmemcached::MemcachedSt=>1, OpenSSL::PKey::EC::Group=>1, OpenSSL::X509::Store=>1, OpenSSL::PKey::DH=>2, RE2::Regexp=>1, FFI::Pointer=>1, FFI::Type::Builtin=>21, OpenSSL::Cipher=>1} {:count=>60, :heap_allocated_pages=>10645, :heap_sorted_length=>10645, :heap_allocatable_pages=>0, :heap_available_slots=>4338897, :heap_live_slots=>3315218, :heap_free_slots=>1023679, :heap_final_slots=>0, :heap_marked_slots=>3314982, :heap_eden_pages=>10645, :heap_tomb_pages=>0, :total_ allocated_pages=>10645, :total_freed_pages=>0, :total_allocated_objects=>42922679, :total_freed_objects=>39607461, :malloc_increase_bytes=>5792, :malloc_increase_bytes_limit=>128000000, :minor_gc_count=>48, :major_gc_count=>12, :remembered_wb_unprotected_objects=>77656, :remembered_wb_unp rotected_objects_limit=>155312, :old_objects=>3144841, :old_objects_limit=>6289682, :oldmalloc_increase_bytes=>6240, :oldmalloc_increase_bytes_limit=>128000000} 3314982 live, 1023915 free slots 979 MB RSS Stackprof results captured in: tmp/stackprof_4.2.10.github_20180419121610.prof

Slide 159

Slide 159 text

13mil objects / req

Slide 160

Slide 160 text

300k objects / req

Slide 161

Slide 161 text

No content

Slide 162

Slide 162 text

Make Performance Easy

Slide 163

Slide 163 text

Make Rails Scalable by Default

Slide 164

Slide 164 text

Make Your Team Scalable by Default

Slide 165

Slide 165 text

One More Story

Slide 166

Slide 166 text

No content

Slide 167

Slide 167 text

Crap Data

Slide 168

Slide 168 text

Data I acquired (crap data) -100 925 1950 2975 4000 Time 2017-01-23 15:53:51 2017-01-23 15:53:56 2017-01-23 15:54:01 2017-01-23 15:54:06 2017-01-23 15:54:11 2017-01-23 15:54:16 2017-01-23 15:54:21 2017-01-23 15:54:26 2017-01-23 15:54:31 2017-01-23 15:54:37 2017-01-23 15:54:42 2017-01-23 15:54:47 2017-01-23 15:54:52 2017-01-23 15:54:57 2017-01-23 15:55:02 2017-01-23 15:55:07 2017-01-23 15:55:12 2017-01-23 15:55:17 2017-01-23 15:55:22 2017-01-23 15:55:27 2017-01-23 15:55:32

Slide 169

Slide 169 text

40min later…

Slide 170

Slide 170 text

Raspberry Pi + Motion Sensor

Slide 171

Slide 171 text

Litter Box

Slide 172

Slide 172 text

I made this Weight (g) -100 925 1950 2975 4000 Time 2017-01-23 15:53:51 2017-01-23 15:53:56 2017-01-23 15:54:01 2017-01-23 15:54:06 2017-01-23 15:54:11 2017-01-23 15:54:16 2017-01-23 15:54:21 2017-01-23 15:54:26 2017-01-23 15:54:31 2017-01-23 15:54:37 2017-01-23 15:54:42 2017-01-23 15:54:47 2017-01-23 15:54:52 2017-01-23 15:54:57 2017-01-23 15:55:02 2017-01-23 15:55:07 2017-01-23 15:55:12 2017-01-23 15:55:17 2017-01-23 15:55:22 2017-01-23 15:55:27 2017-01-23 15:55:32 Cat Enters Cat Leaves

Slide 173

Slide 173 text

~100g

Slide 174

Slide 174 text

(Literally Crap Data)

Slide 175

Slide 175 text

No content

Slide 176

Slide 176 text

Home Automation!

Slide 177

Slide 177 text

No content

Slide 178

Slide 178 text

No content

Slide 179

Slide 179 text

No content

Slide 180

Slide 180 text

Reed Switch

Slide 181

Slide 181 text

No content

Slide 182

Slide 182 text

Tilt Sw itch Z-Wave Sensor

Slide 183

Slide 183 text

On Position Tilt Sw itch Z-Wave Sensor

Slide 184

Slide 184 text

Off Position Tilt Sw itch Z-Wave Sensor

Slide 185

Slide 185 text

No content

Slide 186

Slide 186 text

No content

Slide 187

Slide 187 text

No content

Slide 188

Slide 188 text

Next Step: Facebook Integration

Slide 189

Slide 189 text

No content

Slide 190

Slide 190 text

Thank You!