Slide 1

Slide 1 text

vroom ruby, vroom @k0ws1k github.com/kowsik

Slide 2

Slide 2 text

about me former CTO @mudynamics now CTO @blitz_io rubyist since 2006 led a team to build a 250K LoC commercial, non- web-app codebase

Slide 3

Slide 3 text

@mudynamics commercial fuzzer on steroids first version in C++ second version was ruby bindings over C++ VALUE pointers and rb_scan_args() rb_gc_mark() and rb_gc_start() third version was pure ruby with C ext profit!

Slide 4

Slide 4 text

fuzzing https:/ /github.com/rails/rails/issues/5228

Slide 5

Slide 5 text

fuzzing methodical fault injection into http, spdy, soap, json, xml, you name it automated -ve rspec hdd - hacker driven development broke/hacked a lot of things printers, browsers, web apps, voip gateways, video servers, IM servers speed of execution was super important

Slide 6

Slide 6 text

ruby clean and beautiful, outside and inside <3 principle of least surprise extensions in C almost like writing ruby rb_raise, rb_call, etc 1.8.7 interpreter “purer” than 1.9.2 the VM complexifies the code paths harder to do code walkthroughs

Slide 7

Slide 7 text

languages are neither slow or fast interpreter implementation trade-offs matter optimizations and gotchas comes down to “big oh”

Slide 8

Slide 8 text

big oh you prolly seen O(1), O(logn), O(n), O(n2) things that make you go doh when you get it majority of performance issues poor choice of data structures algorithms capped speed of light => don’t blame rails that it’s slow

Slide 9

Slide 9 text

big-oh in figs 0 10 20 30 40 1 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31 33 35 37 39 O(1) O(logn) O(n) O(n^2)

Slide 10

Slide 10 text

little things

Slide 11

Slide 11 text

gem install t command line twitter - very cool, but... in --version 0.6.2 `time t` => 1.34s oh really, but why?

Slide 12

Slide 12 text

hacking t vi bin/t line #4 p $LOADED_FEATURES.size; exit 1 `t` => 433 Hmm, lots of dependencies, but still ruby -e ‘p $LOADED_FEATURES.class’ => Array

Slide 13

Slide 13 text

load.c#rb_feature_p features = get_loaded_features(); for (i = 0; i < RARRAY_LEN(features); ++i) { v = RARRAY_PTR(features)[i]; f = StringValuePtr(v); if ((n = RSTRING_LEN(v)) < len) continue; if (strncmp(f, feature, len) != 0) {

Slide 14

Slide 14 text

$LOADED_FEATURES .0s 7.5s 15.0s 22.5s 30.0s 1 10 100 1000 10000 100000 1000000 $LOADED_FEATURES

Slide 15

Slide 15 text

rails startup time gem install rails rails new foobar vi config/routes.rb p $LOADED_FEATURES.size => 784 watch this as you build a real app

Slide 16

Slide 16 text

medium things

Slide 17

Slide 17 text

@blitz_io polyglot distributed app that makes load testing a fun sport capacity planning, sizing, scalability questions sinatra, jQuery, backbone.js, couchdb, redis & C++ recently experimenting with dynamodb running on all 7 regions of AWS so you can say => send me 10K users from singapore integrations with new relic, copper egg & scoutapp

Slide 18

Slide 18 text

@blitz_io

Slide 19

Slide 19 text

early days no redis just yet before filter for cookie -> session before do @account = @db.get session[:id] end couchdb gets hammered for static assets doh!

Slide 20

Slide 20 text

self ddos first architecture filtered _changes with couchdb 10’s of engines worldwide huge self-ddos on each sprint/rush couchdb engines

Slide 21

Slide 21 text

ddos mitigation switch to redis for queuing, couchdb for persistence BRPOPLPUSH is atomic, O(1) and light-weight completed jobs move from redis to couchdb dropped UI response time from ~750ms to < 20ms

Slide 22

Slide 22 text

bigger things

Slide 23

Slide 23 text

ObjectSpace Number of objects and GC hiccups Big Oh remember? github.com/kowsik/vroom vroom-blitz.herokuapp.com /gc /gc_count Explicit GC every 10 seconds

Slide 24

Slide 24 text

GC hiccups Rails app from a @blitz_io customer

Slide 25

Slide 25 text

Concurrency vs Hit-rate hit-rate is number of requests/second not the same as average response time! concurrency is number of open sockets aka simultaneous users single threaded sinatra has a concurrency of one!

Slide 26

Slide 26 text

hit-rate vroom-ruby.herokuapp.com/sync?delay=1000 get '/sync' do delay = params[:delay].to_i rescue 0 sleep(delay/1000.0) unless delay.zero? "#{delay} ms" end expect hit-rate of 1/second and average response time of 1 second blitz => -p 1-1:60

Slide 27

Slide 27 text

concurrency what happens if we increase concurrency? blitz => -p 1-10:60

Slide 28

Slide 28 text

let’s make it async async behaves like a load-balanced cluster aget '/async' do delay = params[:delay].to_i rescue 0 EM.add_timer(delay/1000.0) do body "#{delay} ms" end end each request still takes 1 second but you gain concurrency because of multiplexing => hit-rate is no longer 1/second

Slide 29

Slide 29 text

connection pools vroom-ruby.herokuapp.com/pool?delay=1000 uses a thread pool size of 10 8 lane highway becoming 1 lane leading to congestion only observable at concurrencies > pool size blitz => -p 1-10:10,10-10:10,10-50:10,50-50:60

Slide 30

Slide 30 text

redis in @blitz_io engine registration write-through cache job scheduling API throttling but redis is a data structure server big oh with all its might

Slide 31

Slide 31 text

redis doh’s Lists - LINDEX, LINSERT, LREM => O(n) Sets - SDIFF, SDIFFSTORE, SUNION, SUNIONSTORE => O(n) Sets - SINTER, SINTERSTORE => O(n*m)

Slide 32

Slide 32 text

wrapping up performance is a fun sport slowness usually has reasons check data-structures check algorithms just takes some experience to spot the problems and it’s not always rails

Slide 33

Slide 33 text

questions? @k0ws1k @blitz_io