Slide 1

Slide 1 text

Tracing your way through ruby Elise Huard @elise_huard Baruco 2012 Saturday, 8 September 12

Slide 2

Slide 2 text

99% of problems standard errors Saturday, 8 September 12

Slide 3

Slide 3 text

undefined method `to_str' for nil:NilClass wrong number of arguments(3 for 0) (ArgumentError) No such file or directory - records.csv (Errno::ENOENT) Saturday, 8 September 12

Slide 4

Slide 4 text

Saturday, 8 September 12

Slide 5

Slide 5 text

Tracing the hell out of your ruby Saturday, 8 September 12

Slide 6

Slide 6 text

DTrace Saturday, 8 September 12

Slide 7

Slide 7 text

Producer: Probes Saturday, 8 September 12

Slide 8

Slide 8 text

probes.d provider ruby { probe function__entry(const char *, const char *, const char *, int); (...) probe gc__begin(); probe gc__end(); (...) } https://github.com/tenderlove/ruby/tree/probes Saturday, 8 September 12

Slide 9

Slide 9 text

probes.h #define RUBY_DTRACE_FUNCTION_ENTRY(arg0, arg1, arg2, arg3) \ do { \ __asm__ volatile(".reference " RUBY_DTRACE_TYPEDEFS); \ __dtrace_probe$ruby$function__entry$v1$63686172202a $63686172202a$63686172202a$696e74(arg0, arg1, arg2, arg3); \ __asm__ volatile(".reference " RUBY_DTRACE_STABILITY); \ } while (0) #define RUBY_DTRACE_FUNCTION_ENTRY_ENABLED() \ (...) Saturday, 8 September 12

Slide 10

Slide 10 text

Ruby C code if (RUBY_DTRACE_FUNCTION_ENTRY_ENABLED()) { const char * classname = rb_class2name(klass); const char * methodname = rb_id2name(id); const char * filename = rb_sourcefile(); if (classname && methodname && filename) { RUBY_DTRACE_FUNCTION_ENTRY( classname, methodname, filename, rb_sourceline()); } } Saturday, 8 September 12

Slide 11

Slide 11 text

On the system dtrace -l dtrace -lP ruby Saturday, 8 September 12

Slide 12

Slide 12 text

Consumer: D language Saturday, 8 September 12

Slide 13

Slide 13 text

Let’s start simple ruby*:::function-entry { printf("-> %s::%s (%s:%d)\n", copyinstr(arg0), copyinstr(arg1), copyinstr(arg2), arg3); } Saturday, 8 September 12

Slide 14

Slide 14 text

Ruby C code if (RUBY_DTRACE_FUNCTION_ENTRY_ENABLED()) { const char * classname = rb_class2name(klass); const char * methodname = rb_id2name(id); const char * filename = rb_sourcefile(); if (classname && methodname && filename) { RUBY_DTRACE_FUNCTION_ENTRY( classname, methodname, filename, rb_sourceline()); } } Saturday, 8 September 12

Slide 15

Slide 15 text

➜ baruco-2012 sudo dtrace -q -s simple.d -p 70239 -> Class::now (/usr/local/lib/ruby/2.0.0/webrick/utils.rb:177) -> Time::initialize (/usr/local/lib/ruby/2.0.0/webrick/utils.rb: 177) -> Fixnum::+ (/usr/local/lib/ruby/2.0.0/webrick/utils.rb:177) -> Hash::keys (/usr/local/lib/ruby/2.0.0/webrick/utils.rb:178) -> Array::each (/usr/local/lib/ruby/2.0.0/webrick/utils.rb:178) -> Kernel::sleep (/usr/local/lib/ruby/2.0.0/webrick/utils.rb:186) -> Class::now (/usr/local/lib/ruby/2.0.0/webrick/utils.rb:177) -> Time::initialize (/usr/local/lib/ruby/2.0.0/webrick/utils.rb: 177) -> Fixnum::+ (/usr/local/lib/ruby/2.0.0/webrick/utils.rb:177) Saturday, 8 September 12

Slide 16

Slide 16 text

thread-local variables #pragma D option quiet ruby*:::gc-begin { self->gstart = timestamp; } ruby*:::gc-end / self->gstart != NULL / { printf("GC time %d\n",timestamp - self->gstart); } Saturday, 8 September 12

Slide 17

Slide 17 text

thread-local variables #pragma D option quiet ruby*:::gc-begin { self->gstart = timestamp; } ruby*:::gc-end / self->gstart != NULL / { printf("GC time %d\n",timestamp - self->gstart); } Saturday, 8 September 12

Slide 18

Slide 18 text

➜ baruco-2012 sudo dtrace -s gc_time.d -p 73340 GC time 24788699 GC time 20332615 GC time 88187 GC time 116567 GC time 29605 GC time 31248 GC time 29645 GC time 21863365 Saturday, 8 September 12

Slide 19

Slide 19 text

Aggregate #pragma D option aggsortrev ruby*:::function-entry { @[copyinstr(arg0), copyinstr(arg1)] = count(); } Saturday, 8 September 12

Slide 20

Slide 20 text

➜ baruco-2012 sudo dtrace -s aggregate.d -p 73340 ^C Module to_s 4883 Kernel inspect 4868 StringScanner scan 685 Proc call 430 Hash []= 421 Symbol == 298 Array each 232 Kernel hash 211 Class new 204 String sub 189 Rack::Lint::Assertion assert 188 Saturday, 8 September 12

Slide 21

Slide 21 text

Aggregate #pragma D option quiet ruby*:::gc-begin { self->gstart = timestamp; } ruby*:::gc-end / self->gstart != NULL / { @length = quantize(timestamp - self->gstart); } Saturday, 8 September 12

Slide 22

Slide 22 text

Aggregate #pragma D option quiet ruby*:::gc-begin { self->gstart = timestamp; } ruby*:::gc-end / self->gstart != NULL / { @length = quantize(timestamp - self->gstart); } Saturday, 8 September 12

Slide 23

Slide 23 text

➜ baruco-2012 sudo dtrace -s aggregate_q.d -p 73340 ^C value ------------- Distribution ------------- count 65536 | 0 131072 |@@ 1 262144 |@@@@@@@@@@@@@@ 6 524288 |@@@@@@@@@@@@ 5 1048576 |@@@@@@@ 3 2097152 |@@@@@ 2 4194304 | 0 Saturday, 8 September 12

Slide 24

Slide 24 text

count sum avg min max stddev lquantize quantize Saturday, 8 September 12

Slide 25

Slide 25 text

Tools based on dtrace Saturday, 8 September 12

Slide 26

Slide 26 text

dtruss: syscalls (strace) Saturday, 8 September 12

Slide 27

Slide 27 text

iosnoop Saturday, 8 September 12

Slide 28

Slide 28 text

execsnoop: executing programs Saturday, 8 September 12

Slide 29

Slide 29 text

Instruments Saturday, 8 September 12

Slide 30

Slide 30 text

Saturday, 8 September 12

Slide 31

Slide 31 text

Saturday, 8 September 12

Slide 32

Slide 32 text

JRuby ➜ baruco-2012 sudo dtrace -ln 'hotspot*:::gc-begin' ➜ baruco-2012 sudo dtrace -ln 'hotspot*:::thread-start' http://www.solarisinternals.com/wiki/index.php/ DTrace_Topics_Java#Listing_Probes Saturday, 8 September 12

Slide 33

Slide 33 text

Sometimes ... Saturday, 8 September 12

Slide 34

Slide 34 text

Saturday, 8 September 12

Slide 35

Slide 35 text

Thanks Gracies Gracias Elise Huard @elise_huard Baruco 2012 Saturday, 8 September 12