SlideShare une entreprise Scribd logo
1  sur  94
Télécharger pour lire hors ligne
DEBUGGING RUBY
    Aman Gupta
      @tmm1


        http://tinyurl.com/eyfast
AS RUBYISTS, WE'VE SEEN...
nasty bugs
ejpphoto (flickr)
fatboyke (flickr)
                    code
memory bloat
37prime (flickr)
THIS TALK IS ABOUT...




TOOLS TO FIX THESE ISSUES.
TOOLS FOR LINUX.




                        lsof
                      strace
                      ltrace
pleeker (flickr)
TOOLS FOR C CODE.




                       perftools
                         gdb
booddin (flickr)
TOOLS FOR NETWORKS.




                         tcpdump
                           ngrep
pascal.charest (flickr)
TOOLS FOR CPU USAGE.




                      perftools
                     perftools.rb
marksze (flickr)
TOOLS FOR MEMORY USAGE.




                  bleak_house
                     gdb.rb
kgrocki (flickr)     memprof
IGNORE THE FINE PRINT



mayu (flickr)           delgrossodotcom (flickr)
LSOF
   list open files


lsof -nPp <pid>
lsof -nPp <pid>
-n
Inhibits the conversion of network numbers to host names.

-P
Inhibits the conversion of port numbers to names for network files


   FD    TYPE   NAME                                             json
  cwd     DIR   /var/www/myapp                               memcached
  txt     REG   /usr/bin/ruby                                   mysql
  mem     REG   /json-1.1.9/ext/json/ext/generator.so           http
  mem     REG   /json-1.1.9/ext/json/ext/parser.so
  mem     REG   /memcached-0.17.4/lib/rlibmemcached.so
  mem     REG   /mysql-2.8.1/lib/mysql_api.so
    0u    CHR   /dev/null
    1w    REG   /usr/local/nginx/logs/error.log
    2w    REG   /usr/local/nginx/logs/error.log
    3u   IPv4   10.8.85.66:33326->10.8.85.68:3306 (ESTABLISHED)
   10u   IPv4   10.8.85.66:33327->10.8.85.68:3306 (ESTABLISHED)
   11u   IPv4   127.0.0.1:58273->127.0.0.1:11211 (ESTABLISHED)
   12u    REG   /tmp/RackMultipart.28957.0
   33u   IPv4   174.36.83.42:37466->69.63.180.21:80 (ESTABLISHED)
STRACE
    trace system calls and signals


      strace -cp <pid>
strace -ttTp <pid> -o <file>
strace -cp <pid>
-c
Count time, calls, and errors for each system call and report a
summary on program exit.

-p pid
Attach to the process with the process ID pid and begin tracing.


% time     seconds usecs/call      calls    errors syscall
------ ----------- ----------- --------- --------- ----------------
 50.39    0.000064           0      1197       592 read
 34.65    0.000044           0       609           writev
 14.96    0.000019           0      1226           epoll_ctl
  0.00    0.000000           0         4           close
  0.00    0.000000           0         1           select
  0.00    0.000000           0         4           socket
  0.00    0.000000           0         4         4 connect
  0.00    0.000000           0      1057           epoll_wait
------ ----------- ----------- --------- --------- ----------------
100.00    0.000127                  4134       596 total
strace -ttTp <pid> -o <file>
-t
Prefix each line of the trace with the time of day.

-tt
If given twice, the time printed will include the microseconds.

-T
Show the time spent in system calls.

-o filename
Write the trace output to the file filename rather than to stderr.

epoll_wait(9, {{EPOLLIN, {u32=68841296, u64=68841296}}}, 4096, 50) = 1 <0.033109>
accept(10, {sin_port=38313, sin_addr="127.0.0.1"}, [1226]) = 22 <0.000014>
fcntl(22, F_GETFL) = 0x2 (flags O_RDWR) <0.000007>
fcntl(22, F_SETFL, O_RDWR|O_NONBLOCK) = 0 <0.000008>
setsockopt(22, SOL_TCP, TCP_NODELAY, [1], 4) = 0 <0.000008>
accept(10, 0x7fff5d9c07d0, [1226]) = -1 EAGAIN <0.000014>
epoll_ctl(9, EPOLL_CTL_ADD, 22, {EPOLLIN, {u32=108750368, u64=108750368}}) = 0 <0.000009>
epoll_wait(9, {{EPOLLIN, {u32=108750368, u64=108750368}}}, 4096, 50) = 1 <0.000007>
read(22, "GET / HTTP/1.1r"..., 16384) = 772 <0.000012>
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0 <0.000007>
poll([{fd=5, events=POLLIN|POLLPRI}], 1, 0) = 0 (Timeout) <0.000008>
write(5, "1000000-0003SELECT * FROM `table`"..., 56) = 56 <0.000023>
read(5, "25101,20x234m"..., 16384) = 284 <1.300897>
http client connection
                                   read 772 bytes


read(22, "GET / HTTP/1.1r"..., 16384) = 772 <0.0012>




       incoming http request
                                        took 0.0012s
mysql connection
                     write sql query to db


write(5, "SELECT * FROM `table`"..., 56) = 56 <0.0023>
read(5, "25101,20x234m"..., 16384) = 284 <1.30>



           read query
            response
                                             slow query
stracing ruby: SIGVTALRM
    --- SIGVTALRM (Virtual   timer expired) @ 0 (0) ---
    rt_sigreturn(0x1a)        = 2207807 <0.000009>
    --- SIGVTALRM (Virtual   timer expired) @ 0 (0) ---
    rt_sigreturn(0x1a)        = 0 <0.000009>
    --- SIGVTALRM (Virtual   timer expired) @ 0 (0) ---
    rt_sigreturn(0x1a)        = 140734552062624 <0.000009>
    --- SIGVTALRM (Virtual   timer expired) @ 0 (0) ---
    rt_sigreturn(0x1a)        = 140734552066688 <0.000009>
    --- SIGVTALRM (Virtual   timer expired) @ 0 (0) ---
    rt_sigreturn(0x1a)        = 11333952 <0.000008>
    --- SIGVTALRM (Virtual   timer expired) @ 0 (0) ---
    rt_sigreturn(0x1a)        = 0 <0.000009>
    --- SIGVTALRM (Virtual   timer expired) @ 0 (0) ---
    rt_sigreturn(0x1a)        = 1 <0.000010>
    --- SIGVTALRM (Virtual   timer expired) @ 0 (0) ---


• ruby 1.8 uses signals to schedule its green threads
• process receives a SIGVTALRM signal every 10ms
stracing ruby: sigprocmask
% time     seconds usecs/call      calls    errors syscall
------ ----------- ----------- --------- --------- ----------------
100.00    0.326334           0   3568567           rt_sigprocmask
  0.00    0.000000           0         9           read
  0.00    0.000000           0        10           open
  0.00    0.000000           0        10           close
  0.00    0.000000           0         9           fstat
  0.00    0.000000           0        25           mmap
------ ----------- ----------- --------- --------- ----------------
100.00    0.326334               3568685         0 total



  • debian/redhat compile ruby with --enable-pthread
  • uses a native thread timer for SIGVTALRM
  • causes excessive calls to sigprocmask: 30% slowdown!
TCPDUMP
   dump traffic on a network


tcpdump -i eth0 -s 0 -nqA
    tcp dst port 3306
tcpdump -i <eth> -s <len> -nqA <expr>
  tcpdump -i <eth> -w <file> <expr>
-i <eth>
Network interface.

-s <len>
Snarf len bytes of data from each packet.

-n
Don't convert addresses (host addresses, port numbers) to names.

-q
Quiet output.   Print less protocol information.

-A
Print each packet (minus its link level header) in ASCII.

-w <file>
Write the raw packets to file rather than printing them out.

<expr>
libpcap expression, for example:
  tcp src port 80
  tcp dst port 3306
tcp dst port 80
19:52:20.216294 IP 24.203.197.27.40105 >
174.37.48.236.80: tcp 438
E...*.@.l.%&.....%0....POx..%s.oP.......
GET /poll_images/cld99erh0/logo.png HTTP/1.1
Accept: */*
Referer: http://apps.facebook.com/realpolls/?
_fb_q=1
tcp dst port 3306
19:51:06.501632 IP 10.8.85.66.50443 >
10.8.85.68.3306: tcp 98
E..."K@.@.Yy
.UB
.UD.....z....L............
GZ.y3b..[......W....
SELECT * FROM `votes` WHERE (`poll_id` =
72621) LIMIT 1
tcpdump -w <file>
PERFTOOLS
     google's performance tools


CPUPROFILE=/tmp/myprof ./myapp
  pprof ./myapp /tmp/myprof
wget http://google-perftools.googlecode.com/files/google-
perftools-1.6.tar.gz                                 download
tar zxvf google-perftools-1.6.tar.gz
cd google-perftools-1.6

./configure --prefix=/opt
make                                                 compile
sudo make install

# for linux
export LD_PRELOAD=/opt/lib/libprofiler.so            setup

# for osx
export DYLD_INSERT_LIBRARIES=/opt/lib/libprofiler.dylib

CPUPROFILE=/tmp/ruby.prof ruby -e'                   profile
  5_000_000.times{ "hello world" }
'

pprof `which ruby` --text /tmp/ruby.prof             report
pprof ruby                pprof ruby
 ruby.prof --text           ruby.prof --gif
Total: 103 samples
    95 92.2% rb_yield_0
   103 100.0% rb_eval
    12 11.7% gc_sweep
    52 50.5% rb_str_new3
     3   2.9% obj_free
   103 100.0% int_dotimes
    12 11.7% gc_mark
Profiling MRI
                  • 10% of production
                     VM time spent in
                     rb_str_sub_bang
                  • String#sub!
                  • called from
                     Time.parse


return   unless   str.sub!(/A(d{1,2})/, '')
return   unless   str.sub!(/A( d|d{1,2})/, '')
return   unless   str.sub!(/A( d|d{1,2})/, '')
return   unless   str.sub!(/A(d{1,3})/, '')
return   unless   str.sub!(/A(d{1,2})/, '')
return   unless   str.sub!(/A(d{1,2})/, '')
Profiling EM + threads
           Total: 3763 samples
            2764 73.5% catch_timer
             989 26.3% memcpy
               3   0.1% st_lookup
               2   0.1% rb_thread_schedule
               1   0.0% rb_eval
               1   0.0% rb_newobj
               1   0.0% rb_gc_force_recycle


           • known issue: EM+threads =
            slow
           • memcpy??
           • thread context switches copy
            the stack w/ memcpy
           • EM allocates huge buffer on
            the stack
           • solution: move buffer to the
            heap
PERFTOOLS.RB
   perftools for ruby code


pprof.rb /tmp/myrbprof

                 github.com/tmm1/perftools.rb
gem install perftools.rb

RUBYOPT="-r`gem which perftools | tail -1`"
CPUPROFILE=/tmp/myrbprof
ruby myapp.rb

pprof.rb /tmp/myrbprof --text
pprof.rb /tmp/myrbprof --gif > /tmp/myrbprof.gif
require 'sinatra'
                       $ ab -c 1 -n 50 http://127.0.0.1:4567/compute
                       $ ab -c 1 -n 50 http://127.0.0.1:4567/sleep
get '/sleep' do
  sleep 0.25
  'done'                          • Sampling profiler:
end
                                    • 232 samples total
get '/compute' do                   • 83 samples were in /compute
  proc{ |n|
    a,b=0,1                         • 118 samples had /compute on
                                       the stack but were in
    n.times{ a,b = b,a+b }             another function
    b
  }.call(10_000)                    • /compute accounts for 50%
  'done'                               of process, but only 35% of
                                       time was in /compute itself
end

== Sinatra has ended his set (crowd applauds)
PROFILE: interrupts/evictions/bytes = 232/0/2152

Total: 232 samples
      83 35.8% 35.8%        118   50.9% Sinatra::Application#GET /compute
      56 24.1% 59.9%         56   24.1% garbage_collector
      35 15.1% 75.0%        113   48.7% Integer#times
CPUPROFILE_REALTIME=1
                         CPUPROFILE=app.prof
CPUPROFILE=app-rt.prof
redis-rb bottleneck
why is rubygems slow?
faster
      bundle
      install
• 23% spent in
  Gem::Version#<=>
• simple patch to rubygems
  improved overall install
  performance by 15%
• http://gist.github.com/
  458185
CPUPROFILE_OBJECTS=1
CPUPROFILE=app-objs.prof

• object allocation profiler
  mode built-in
• 1 sample = 1 object
  created
• Time parsing is both
  CPU and object
  allocation intensive
• using mysql2 moves
  this to C
LTRACE
        trace library calls


      ltrace -cp <pid>
ltrace -ttTp <pid> -o <file>
ltrace -c ruby threaded_em.rb
         % time     seconds usecs/call      calls       function
         ------ ----------- ----------- --------- --------------------
          48.65   11.741295         617     19009 memcpy
          30.16    7.279634         831      8751 longjmp
           9.78    2.359889         135     17357 _setjmp
           8.91    2.150565         285      7540 malloc
           1.10    0.265946          20     13021 memset
           0.81    0.195272          19     10105 __ctype_b_loc
           0.35    0.084575          19      4361 strcmp
           0.19    0.046163          19      2377 strlen
           0.03    0.006272          23       265 realloc
         ------ ----------- ----------- --------- --------------------
         100.00   24.134999                 82999 total


  ltrace -ttT -e memcpy ruby threaded_em.rb
01:24:48.769408 --- SIGVTALRM (Virtual timer expired) ---
01:24:48.769616 memcpy(0x1216000, "", 1086328)   = 0x1216000 <0.000578>
01:24:48.770555 memcpy(0x6e32670, "240&343v", 1086328) = 0x6e32670 <0.000418>

01:24:49.899414 --- SIGVTALRM (Virtual timer expired) ---
01:24:49.899490 memcpy(0x1320000, "", 1082584)   = 0x1320000 <0.000628>
01:24:49.900474 memcpy(0x6e32670, "", 1086328) = 0x6e32670 <0.000479>
LTRACE/LIBDL
  trace dlopen’d library calls

ltrace -F <conf> -bg -x
   <symbol> -p <pid>

             github.com/ice799/ltrace/tree/libdl
ltrace -F <conf> -b -g -x <sym>
-b
Ignore signals.

-g
Ignore libraries linked at compile time.

-F <conf>
Read prototypes from config file.

-x <sym>
Trace calls to the function sym.

-s <num>
Show first num bytes of string args.


-F ltrace.conf
int mysql_real_query(addr,string,ulong);
void garbage_collect(void);
int memcached_set(addr,string,ulong,string,ulong);
ltrace -x garbage_collect
19:08:06.436926   garbage_collect()   =   <void>   <0.221679>
19:08:15.329311   garbage_collect()   =   <void>   <0.187546>
19:08:17.662149   garbage_collect()   =   <void>   <0.199200>
19:08:20.486655   garbage_collect()   =   <void>   <0.205864>
19:08:25.102302   garbage_collect()   =   <void>   <0.214295>
19:08:35.552337   garbage_collect()   =   <void>   <0.189172>
ltrace -x mysql_real_query
mysql_real_query(0x1c9e0500,   "SET NAMES 'UTF8'", 16)         =   0   <0.000324>
mysql_real_query(0x1c9e0500,   "SET SQL_AUTO_IS_NULL=0", 22)   =   0   <0.000322>
mysql_real_query(0x19c7a500,   "SELECT * FROM `users`", 21)    =   0   <1.206506>
mysql_real_query(0x1c9e0500,   "COMMIT", 6)                    =   0   <0.000181>
ltrace -x memcached_set
memcached_set(0x15d46b80,   "Status:33",   21,   "004b",   366)   =   0   <0.01116>
memcached_set(0x15d46b80,   "Status:96",   21,   "004b",   333)   =   0   <0.00224>
memcached_set(0x15d46b80,   "Status:57",   21,   "004b",   298)   =   0   <0.01850>
memcached_set(0x15d46b80,   "Status:10",   21,   "004b",   302)   =   0   <0.00530>
memcached_set(0x15d46b80,   "Status:67",   21,   "004b",   318)   =   0   <0.00291>
memcached_set(0x15d46b80,   "Status:02",   21,   "004b",   299)   =   0   <0.00658>
memcached_set(0x15d46b80,   "Status:34",   21,   "004b",   264)   =   0   <0.00243>
GDB
 the GNU debugger


gdb <executable>
gdb attach <pid>
Debugging Ruby Segfaults
 test_segv.rb:4: [BUG] Segmentation fault
 ruby 1.8.7 (2008-08-11 patchlevel 72) [i686-darwin9.7.0]

                             def test
  #include "ruby.h"            require 'segv'
                               4.times do
  VALUE                          Dir.chdir '/tmp' do
  segv()                           Hash.new{ segv }[0]
  {                              end
    VALUE array[1];            end
    array[1000000] = NULL;   end
    return Qnil;
  }                          sleep 10
                             test()
  void
  Init_segv()
  {
    rb_define_method(rb_cObject, "segv", segv, 0);
  }
1. Attach to running process
 $ ps aux | grep ruby
 joe 23611 0.0 0.1      25424   7540 S Dec01 0:00 ruby test_segv.rb

 $ sudo gdb ruby 23611
 Attaching to program: ruby, process 23611
 0x00007fa5113c0c93 in nanosleep () from /lib/libc.so.6
 (gdb) c
 Continuing.

 Program received signal SIGBUS, Bus error.
 segv () at segv.c:7
 7	   array[1000000] = NULL;


2. Use a coredump
 Process.setrlimit Process::RLIMIT_CORE, 300*1024*1024
 $ sudo mkdir /cores
 $ sudo chmod 777 /cores
 $ sudo sysctl kernel.core_pattern=/cores/%e.core.%s.%p.%t

 $ sudo gdb ruby /cores/ruby.core.6.23611.1259781224
def test
  require 'segv'
  4.times do
    Dir.chdir '/tmp' do
       Hash.new{ segv }[0]
    end
  end     (gdb) where
end       #0 segv () at segv.c:7
          #1 0x000000000041f2be in    call_cfunc () at eval.c:5727
test()    ...
          #13 0x000000000043ba8c in   rb_hash_default () at hash.c:521
          ...
          #19 0x000000000043b92a in   rb_hash_aref () at hash.c:429
          ...
          #26 0x00000000004bb7bc in   chdir_yield () at dir.c:728
          #27 0x000000000041d8d7 in   rb_ensure () at eval.c:5528
          #28 0x00000000004bb93a in   dir_s_chdir () at dir.c:816
          ...
          #35 0x000000000041c444 in   rb_yield () at eval.c:5142
          #36 0x0000000000450690 in   int_dotimes () at numeric.c:2834
          ...
          #48 0x0000000000412a90 in   ruby_run () at eval.c:1678
          #49 0x000000000041014e in   main () at main.c:48
GDB.RB
  gdb with MRI hooks


gem install gdb.rb
   gdb.rb <pid>
                  github.com/tmm1/gdb.rb
(gdb) ruby eval 1+2
3

(gdb) ruby eval Thread.current
#<Thread:0x1d630 run>

(gdb) ruby eval Thread.list.size
8
(gdb) ruby threads list
0x15890 main thread THREAD_STOPPED    WAIT_JOIN(0x19ef4)
0x19ef4      thread THREAD_STOPPED    WAIT_TIME(57.10s)
0x19e34      thread THREAD_STOPPED    WAIT_FD(5)
0x19dc4      thread THREAD_STOPPED    WAIT_NONE
0x19dc8      thread THREAD_STOPPED    WAIT_NONE
0x19dcc      thread THREAD_STOPPED    WAIT_NONE
0x22668      thread THREAD_STOPPED    WAIT_NONE
0x1d630 curr thread THREAD_RUNNABLE   WAIT_NONE
(gdb) ruby objects
  HEAPS            8
  SLOTS      1686252
  LIVE        893327 (52.98%)
  FREE        792925 (47.02%)

  scope         1641   (0.18%)
  regexp        2255   (0.25%)
  data          3539   (0.40%)
  class         3680   (0.41%)
  hash          6196   (0.69%)
  object        8785   (0.98%)
  array        13850   (1.55%)
  string      105350   (11.79%)
  node        742346   (83.10%)
(gdb) ruby objects strings
      140 u'lib'
      158 u'0'
      294 u'n'
      619 u''

    30503 unique strings
  3187435 bytes
def test
  require 'segv'
  4.times do
    Dir.chdir '/tmp' do
       Hash.new{ segv }[0]
    end
  end
end
            (gdb) ruby threads
test()
             0xa3e000 main curr thread THREAD_RUNNABLE WAIT_NONE
                   node_vcall     segv in test_segv.rb:5
                   node_call      test in test_segv.rb:5
                   node_call      call in test_segv.rb:5
                   node_call      default in test_segv.rb:5
                   node_call      [] in test_segv.rb:5
                   node_call      test in test_segv.rb:4
                   node_call      chdir in test_segv.rb:4
                   node_call      test in test_segv.rb:3
                   node_call      times in test_segv.rb:3
                   node_vcall     test in test_segv.rb:9
rails_warden leak
(gdb) ruby objects classes
    1197 MIME::Type
    2657 NewRelic::MetricSpec
    2719 TZInfo::TimezoneTransitionInfo
    4124 Warden::Manager
    4124 MethodOverrideForAll
    4124 AccountMiddleware
    4124 Rack::Cookies
    4125 ActiveRecord::ConnectionAdapters::ConnectionManagement
    4125 ActionController::Session::CookieStore
    4125 ActionController::Failsafe
    4125 ActionController::ParamsParser
    4125 Rack::Lock
    4125 ActionController::Dispatcher
    4125 ActiveRecord::QueryCache
    4125 ActiveSupport::MessageVerifier
    4125 Rack::Head


middleware chain leaking per request
mongrel sleeper thread
0x16814c00          thread THREAD_STOPPED    WAIT_TIME(0.47) 1522 bytes
      node_fcall    sleep in lib/mongrel/configurator.rb:285
      node_fcall    run in lib/mongrel/configurator.rb:285
      node_fcall    loop in lib/mongrel/configurator.rb:285
      node_call     run in lib/mongrel/configurator.rb:285
      node_call     initialize in lib/mongrel/configurator.rb:285
      node_call     new in lib/mongrel/configurator.rb:285
      node_call     run in bin/mongrel_rails:128
      node_call     run in lib/mongrel/command.rb:212
      node_call     run in bin/mongrel_rails:281
      node_fcall    (unknown) in bin/mongrel_rails:19


def run
  @listeners.each {|name,s|
    s.run
  }


  $mongrel_sleeper_thread = Thread.new { loop { sleep 1 } }
end
god memory leaks
(gdb) ruby objects arrays    43   God::Process
 elements instances          43   God::Watch
    94310 3                  43   God::Driver
    94311 3                  43   God::DriverEventQueue
    94314 2                  43   God::Conditions::MemoryUsage
    94316 1                  43   God::Conditions::ProcessRunning
                             43   God::Behaviors::CleanPidFile
     5369 arrays             45   Process::Status
  2863364 member elements    86   God::Metric
                            327   God::System::SlashProcPoller
many arrays with            327   God::System::Process
 90k+ elements!             406   God::DriverEvent



  5 separate god leaks fixed by Eric
   Lindvall with the help of gdb.rb!
MEMPROF
   a heap visualizer for ruby


  gem install memprof
open http://memprof.com
                     github.com/ice799/memprof
memprof features
• memprof.track

• memprof.dump

• memprof.dump_all

• memprof.com
Memprof.track{
                100.times{ "abc" }
                100.times{ 1.23 + 1 }
                100.times{ Module.new }
              }

              100       file.rb:2:String
              100       file.rb:3:Float
              100       file.rb:4:Module

• like   bleak_house, but for a given block of code
• use Memprof::Middleware       in your webapps to run track
 per request
memprof features
• memprof.track

• memprof.dump

• memprof.dump_all

• memprof.com
Memprof.dump{
        strings                  }
                                   "hello" + "world"




{
    "_id": "0x19c610",        memory address of object
    "file": "file.rb",        file and line where string
    "line": 2,
                              was created
    "type": "string",
    "class": "0x1ba7f0",      address of the class
    "class_name": "String",   “String”

    "length": 10,             length and contents
    "data": "helloworld"      of this string instance
}
arrays
                                        Memprof.dump{
                                          [
                                            1,
                                            :b,
{
    "_id": "0x19c5c0",
                                            2.2,
                                            "d"
    "class": "0x1b0d18",                  ]
    "class_name": "Array",              }

    "length": 4,
    "data": [
      1,                     integers and symbols are
      ":b",                  stored in the array itself
        "0x19c750",          floats and strings are
        "0x19c598"           separate ruby objects
    ]
}
hashes
                                        Memprof.dump{
                                          {
                                            :a => 1,
                                            "b" => 2.2
{                                         }
    "_id": "0x19c598",                  }
    "type": "hash",
    "class": "0x1af170",
    "class_name": "Hash",

    "default": null,           no default proc
    "length": 2,
    "data": [
      [ ":a", 1 ],
                               hash entries as key/value
      [ "0xc728", "0xc750" ]   pairs
    ]
}
classes
                                   Memprof.dump{
                                     class Hello
                                       @@var=1
                                       Const=2
{                                      def world() end
    "_id": "0x19c408",
                                     end
    "type": "class",               }
    "name": "Hello",
    "super": "0x1bfa48",       superclass object reference
    "super_name": "Object",

    "ivars": {                 class variables and constants
       "@@var":   1,           are stored in the instance
       "Const":   2
    },                         variable table
    "methods":    {
       "world":   "0x19c318"   references to method objects
    }
}
memprof features
• memprof.track

• memprof.dump

• memprof.dump_all

• memprof.com
Memprof.dump_all("myapp_heap.json")
• dump    out every single live object as json

• one   per line to specified file


• analyze     via

  • jsawk/grep

  • mongodb/couchdb

  • custom      ruby scripts

  • libyajl   + Boost Graph Library
memprof features
• memprof.track

• memprof.dump

• memprof.dump_all

• memprof.com
memprof.com
a web-based heap visualizer and leak analyzer
plugging a leak in rails3
• in dev mode, rails3 is leaking 10mb per request

let’s use memprof to find it!

  # in environment.rb
  require `gem which memprof/signal`.strip
plugging a leak
   in rails3
 send the app some
 requests so it leaks
 $ ab -c 1 -n 30
 http://localhost:3000/


 tell memprof to dump
 out the entire heap to
 json
 $ memprof
   --pid <pid>
   --name <dump name>
   --key <api key>
2519 classes
  30 copies of
TestController

                 mongo query for all
                 TestController classes



                 details for one copy of
                 TestController
find references to object




 “leak” is on line 178



holding references
 to all controllers
• In development mode, Rails reloads all your
  application code on every request
• ActionView::Partials::PartialRenderer is caching
  partials used by each controller as an optimization
• But.. it ends up holding a reference to every single
  reloaded version of those controllers
MORE* MEMPROF
          FEATURES
• memprof.trace

• memprof::tracer




                    * currently under development
config.middleware.use(Memprof::Tracer)

{
    "time": 4.3442,              total time for request

    "rails": {                   rails controller/action
       "controller": "test",
       "action": "index"
    },

    "request": {               request env info
       "REQUEST_PATH": "/test",
       "REQUEST_METHOD": "GET"
    },
config.middleware.use(Memprof::Tracer)



 "mysql": {
    "queries": 3,        3 mysql queries
    "time": 0.00109302
 },

 "gc": {
    "calls": 8,          8 calls to GC
    "time": 2.04925      2 secs spent in GC
 },
config.middleware.use(Memprof::Tracer)
    "objects": {
      "created": 3911103,    3 million objs created
      "types": {
        "none": 1168831,     1 million method calls
        "object": 1127,      object instances
        "float": 627,
        "string": 1334637,   lots of strings
        "array": 609313,     lots of arrays
        "hash": 3676,
        "match": 70211       regexp matches
      }
    }
}
RACK-PERFTOOLS
 rack middleware for perftools.rb


    gem install rack-
   perftools_profiler
            github.com/bhb/rack-perftools_profiler
require 'rack/perftools_profiler'
                config.middleware.insert(
                  0,
                  Rack::PerftoolsProfiler,
                  :default_printer => 'gif'
                )

$   curl   http://localhost:3000/__start__
$   curl   http://localhost:3000/home
$   curl   http://localhost:3000/about
$   curl   http://localhost:3000/__stop__

$ curl http://localhost:3000/__data__ -o profile.gif
$ curl http://localhost:3000/__data__?printer=text -o profile.txt

$ curl "http://localhost:3000/home?profile=true&times=10"
    -o 10_requests_to_homepage.gif
TOOLS MAKE
DEBUGGING EASIER.
LEARN THESE TOOLS.
                  USE THESE TOOLS.




yujie (flickr)
EY CASE STUDY
• Example   of Professional Services engagement

• Interested?   http://tinyurl.com/eyfast




                          http://tinyurl.com/eyfast
LSOF
15u    IPv4    TCP ->10.243.63.80:11211 (ESTABLISHED)
20u    IPv4    TCP ->10.243.63.80:11211 (ESTABLISHED)
23u    IPv4    TCP ->10.243.63.80:11211 (ESTABLISHED)
                       multiple connections to memcached
                                         via different drivers

 18r     DIR    /shared/public/javascripts/packaged
 19r     DIR    /shared/public/javascripts/packaged
 22r     DIR    /shared/public/javascripts/packaged
                        multiple open handles to javascript
                                        assets directories
STRACE
% time     seconds     calls   syscall
------ ----------- ---------   ---------
 26.28    0.054178      8731   read
 25.81    0.053216    316519   stat
 20.37    0.041993         1   clone
 15.83    0.032648     11034   getdents
  3.54    0.007309     10326   write

                40% of kernel time querying
                                  filesystem
LTRACE
mysql_query("SELECT   * FROM tags WHERE id = 9129")
mysql_query("SELECT   * FROM tags WHERE id = 9129")
mysql_query("SELECT   * FROM tag_info WHERE tag_id
= 9129")
mysql_query("SELECT   * FROM tags WHERE id = 9129")
mysql_query("SELECT   * FROM tags WHERE id = 9129")
mysql_query("SELECT   * FROM tags WHERE id = 9129")

                       common queries repeated multiple
                                times during a request
GDB.RB
(gdb) ruby objects

  HEAPS           10
  SLOTS      4450607
  LIVE       2006769 (45.09%)
  FREE       2443838 (54.91%) large ruby heap

  hash         12939   (0.64%)    numerous 'node'
  array        38007   (1.89%)    objects- required
  object       47633   (2.37%)    libraries and plugins
  string      234205   (11.67%)   that are no longer in
  node       1637926   (81.62%)   use
PERFTOOLS.RB



majority of ruby process' time on
CPU spent in garbage collection
MEMPROF



wide distribution of response times




       expensive controller actions creating
       many millions of objects per request
MEMPROF




          37% of
          response time
          attributed to
          garbage
          collection
BEFORE
Time taken for tests:     20.156 seconds
Complete requests:        100
Requests per second:      4.96 [#/sec] (mean)
Time per request:         201.555 [ms] (mean)


                  AFTER
Time taken for tests:      8.100 seconds
Complete requests:         100
Requests per second:       12.35 [#/sec] (mean)
Time per request:          81.000 [ms] (mean)

     2.5x improvement in throughput after addressing
                 some of these issues and tuning GC
QUESTIONS?
     Aman Gupta
       @tmm1

 http://scr.bi/debuggingruby

Contenu connexe

Tendances

Deploying Prometheus stacks with Juju
Deploying Prometheus stacks with JujuDeploying Prometheus stacks with Juju
Deploying Prometheus stacks with JujuJ.J. Ciarlante
 
Solaris Kernel Debugging V1.0
Solaris Kernel Debugging V1.0Solaris Kernel Debugging V1.0
Solaris Kernel Debugging V1.0Jarod Wang
 
Tracing MariaDB server with bpftrace - MariaDB Server Fest 2021
Tracing MariaDB server with bpftrace - MariaDB Server Fest 2021Tracing MariaDB server with bpftrace - MariaDB Server Fest 2021
Tracing MariaDB server with bpftrace - MariaDB Server Fest 2021Valeriy Kravchuk
 
A little systemtap
A little systemtapA little systemtap
A little systemtapyang bingwu
 
David container security-with_falco
David container security-with_falcoDavid container security-with_falco
David container security-with_falcoLorenzo David
 
Performance Analysis Tools for Linux Kernel
Performance Analysis Tools for Linux KernelPerformance Analysis Tools for Linux Kernel
Performance Analysis Tools for Linux Kernellcplcp1
 
計算機性能の限界点とその考え方
計算機性能の限界点とその考え方計算機性能の限界点とその考え方
計算機性能の限界点とその考え方Naoto MATSUMOTO
 
Kernel Recipes 2017: Performance Analysis with BPF
Kernel Recipes 2017: Performance Analysis with BPFKernel Recipes 2017: Performance Analysis with BPF
Kernel Recipes 2017: Performance Analysis with BPFBrendan Gregg
 
Linux Tracing Superpowers by Eugene Pirogov
Linux Tracing Superpowers by Eugene PirogovLinux Tracing Superpowers by Eugene Pirogov
Linux Tracing Superpowers by Eugene PirogovPivorak MeetUp
 
True stories on the analysis of network activity using Python
True stories on the analysis of network activity using PythonTrue stories on the analysis of network activity using Python
True stories on the analysis of network activity using Pythondelimitry
 
SSL Failing, Sharing, and Scheduling
SSL Failing, Sharing, and SchedulingSSL Failing, Sharing, and Scheduling
SSL Failing, Sharing, and SchedulingDavid Evans
 
Kernel Recipes 2019 - Hunting and fixing bugs all over the Linux kernel
Kernel Recipes 2019 - Hunting and fixing bugs all over the Linux kernelKernel Recipes 2019 - Hunting and fixing bugs all over the Linux kernel
Kernel Recipes 2019 - Hunting and fixing bugs all over the Linux kernelAnne Nicolas
 
BPF / XDP 8월 세미나 KossLab
BPF / XDP 8월 세미나 KossLabBPF / XDP 8월 세미나 KossLab
BPF / XDP 8월 세미나 KossLabTaeung Song
 
Практический опыт профайлинга и оптимизации производительности Ruby-приложений
Практический опыт профайлинга и оптимизации производительности Ruby-приложенийПрактический опыт профайлинга и оптимизации производительности Ruby-приложений
Практический опыт профайлинга и оптимизации производительности Ruby-приложенийOlga Lavrentieva
 
ch6-pv2-device-drivers
ch6-pv2-device-driversch6-pv2-device-drivers
ch6-pv2-device-driversyushiang fu
 
Fosscon 2012 firewall workshop
Fosscon 2012 firewall workshopFosscon 2012 firewall workshop
Fosscon 2012 firewall workshopjvehent
 
370410176 moshell-commands
370410176 moshell-commands370410176 moshell-commands
370410176 moshell-commandsnanker phelge
 

Tendances (20)

Deploying Prometheus stacks with Juju
Deploying Prometheus stacks with JujuDeploying Prometheus stacks with Juju
Deploying Prometheus stacks with Juju
 
Solaris Kernel Debugging V1.0
Solaris Kernel Debugging V1.0Solaris Kernel Debugging V1.0
Solaris Kernel Debugging V1.0
 
Osol Pgsql
Osol PgsqlOsol Pgsql
Osol Pgsql
 
Tracing MariaDB server with bpftrace - MariaDB Server Fest 2021
Tracing MariaDB server with bpftrace - MariaDB Server Fest 2021Tracing MariaDB server with bpftrace - MariaDB Server Fest 2021
Tracing MariaDB server with bpftrace - MariaDB Server Fest 2021
 
Pledge in OpenBSD
Pledge in OpenBSDPledge in OpenBSD
Pledge in OpenBSD
 
A little systemtap
A little systemtapA little systemtap
A little systemtap
 
David container security-with_falco
David container security-with_falcoDavid container security-with_falco
David container security-with_falco
 
Performance Analysis Tools for Linux Kernel
Performance Analysis Tools for Linux KernelPerformance Analysis Tools for Linux Kernel
Performance Analysis Tools for Linux Kernel
 
Rac introduction
Rac introductionRac introduction
Rac introduction
 
計算機性能の限界点とその考え方
計算機性能の限界点とその考え方計算機性能の限界点とその考え方
計算機性能の限界点とその考え方
 
Kernel Recipes 2017: Performance Analysis with BPF
Kernel Recipes 2017: Performance Analysis with BPFKernel Recipes 2017: Performance Analysis with BPF
Kernel Recipes 2017: Performance Analysis with BPF
 
Linux Tracing Superpowers by Eugene Pirogov
Linux Tracing Superpowers by Eugene PirogovLinux Tracing Superpowers by Eugene Pirogov
Linux Tracing Superpowers by Eugene Pirogov
 
True stories on the analysis of network activity using Python
True stories on the analysis of network activity using PythonTrue stories on the analysis of network activity using Python
True stories on the analysis of network activity using Python
 
SSL Failing, Sharing, and Scheduling
SSL Failing, Sharing, and SchedulingSSL Failing, Sharing, and Scheduling
SSL Failing, Sharing, and Scheduling
 
Kernel Recipes 2019 - Hunting and fixing bugs all over the Linux kernel
Kernel Recipes 2019 - Hunting and fixing bugs all over the Linux kernelKernel Recipes 2019 - Hunting and fixing bugs all over the Linux kernel
Kernel Recipes 2019 - Hunting and fixing bugs all over the Linux kernel
 
BPF / XDP 8월 세미나 KossLab
BPF / XDP 8월 세미나 KossLabBPF / XDP 8월 세미나 KossLab
BPF / XDP 8월 세미나 KossLab
 
Практический опыт профайлинга и оптимизации производительности Ruby-приложений
Практический опыт профайлинга и оптимизации производительности Ruby-приложенийПрактический опыт профайлинга и оптимизации производительности Ruby-приложений
Практический опыт профайлинга и оптимизации производительности Ruby-приложений
 
ch6-pv2-device-drivers
ch6-pv2-device-driversch6-pv2-device-drivers
ch6-pv2-device-drivers
 
Fosscon 2012 firewall workshop
Fosscon 2012 firewall workshopFosscon 2012 firewall workshop
Fosscon 2012 firewall workshop
 
370410176 moshell-commands
370410176 moshell-commands370410176 moshell-commands
370410176 moshell-commands
 

En vedette

Debugging Ruby
Debugging RubyDebugging Ruby
Debugging RubyAman Gupta
 
Rubinius @ RubyAndRails2010
Rubinius @ RubyAndRails2010Rubinius @ RubyAndRails2010
Rubinius @ RubyAndRails2010Dirkjan Bussink
 
Debugging Ruby (Aman Gupta)
Debugging Ruby (Aman Gupta)Debugging Ruby (Aman Gupta)
Debugging Ruby (Aman Gupta)MongoSF
 
OpenSource Hardware -Debian Way
OpenSource Hardware -Debian WayOpenSource Hardware -Debian Way
OpenSource Hardware -Debian WaySiji Sunny
 
Operating OPNFV
Operating OPNFVOperating OPNFV
Operating OPNFVOPNFV
 
OpenStack@Mini-Deb Conf'16 Mumbai
OpenStack@Mini-Deb Conf'16 MumbaiOpenStack@Mini-Deb Conf'16 Mumbai
OpenStack@Mini-Deb Conf'16 MumbaiAkanksha Agrawal
 
Your first patch to OpenStack
Your first patch to OpenStackYour first patch to OpenStack
Your first patch to OpenStackopenstackindia
 
Copr HD OpenStack Day India
Copr HD OpenStack Day IndiaCopr HD OpenStack Day India
Copr HD OpenStack Day Indiaopenstackindia
 
Deploying openstack using ansible
Deploying openstack using ansibleDeploying openstack using ansible
Deploying openstack using ansibleopenstackindia
 
The OpenStack Contribution Workflow
The OpenStack Contribution WorkflowThe OpenStack Contribution Workflow
The OpenStack Contribution Workflowopenstackindia
 
Your first patch to open stack
Your first patch to open stackYour first patch to open stack
Your first patch to open stackAkanksha Agrawal
 
Guts & OpenStack migration
Guts & OpenStack migrationGuts & OpenStack migration
Guts & OpenStack migrationopenstackindia
 
OpenStack Storage Buddy Ceph
OpenStack Storage Buddy CephOpenStack Storage Buddy Ceph
OpenStack Storage Buddy Cephopenstackindia
 
Introduction to tempest
Introduction to tempest Introduction to tempest
Introduction to tempest openstackindia
 
Pgcon2012 ori-20120224
Pgcon2012 ori-20120224Pgcon2012 ori-20120224
Pgcon2012 ori-20120224Manabu Ori
 
Ryu with OpenFlow 1.3, Traffic Monitor
Ryu with OpenFlow 1.3, Traffic MonitorRyu with OpenFlow 1.3, Traffic Monitor
Ryu with OpenFlow 1.3, Traffic Monitorjieun kim
 
20150509 unix v6로 배우는 커널의 원리와 구조 3 김지은
20150509 unix v6로 배우는 커널의 원리와 구조 3 김지은20150509 unix v6로 배우는 커널의 원리와 구조 3 김지은
20150509 unix v6로 배우는 커널의 원리와 구조 3 김지은jieun kim
 
Who carries your container? Zun or Magnum?
Who carries your container? Zun or Magnum?Who carries your container? Zun or Magnum?
Who carries your container? Zun or Magnum?Madhuri Kumari
 

En vedette (20)

Debugging Ruby
Debugging RubyDebugging Ruby
Debugging Ruby
 
Rubinius @ RubyAndRails2010
Rubinius @ RubyAndRails2010Rubinius @ RubyAndRails2010
Rubinius @ RubyAndRails2010
 
Debugging Ruby (Aman Gupta)
Debugging Ruby (Aman Gupta)Debugging Ruby (Aman Gupta)
Debugging Ruby (Aman Gupta)
 
OpenSource Hardware -Debian Way
OpenSource Hardware -Debian WayOpenSource Hardware -Debian Way
OpenSource Hardware -Debian Way
 
Operating OPNFV
Operating OPNFVOperating OPNFV
Operating OPNFV
 
OpenStack@Mini-Deb Conf'16 Mumbai
OpenStack@Mini-Deb Conf'16 MumbaiOpenStack@Mini-Deb Conf'16 Mumbai
OpenStack@Mini-Deb Conf'16 Mumbai
 
Your first patch to OpenStack
Your first patch to OpenStackYour first patch to OpenStack
Your first patch to OpenStack
 
Copr HD OpenStack Day India
Copr HD OpenStack Day IndiaCopr HD OpenStack Day India
Copr HD OpenStack Day India
 
Deploying openstack using ansible
Deploying openstack using ansibleDeploying openstack using ansible
Deploying openstack using ansible
 
The OpenStack Contribution Workflow
The OpenStack Contribution WorkflowThe OpenStack Contribution Workflow
The OpenStack Contribution Workflow
 
Your first patch to open stack
Your first patch to open stackYour first patch to open stack
Your first patch to open stack
 
Open stack qa and tempest
Open stack qa and tempestOpen stack qa and tempest
Open stack qa and tempest
 
Guts & OpenStack migration
Guts & OpenStack migrationGuts & OpenStack migration
Guts & OpenStack migration
 
OpenStack Storage Buddy Ceph
OpenStack Storage Buddy CephOpenStack Storage Buddy Ceph
OpenStack Storage Buddy Ceph
 
Introduction to tempest
Introduction to tempest Introduction to tempest
Introduction to tempest
 
Pgcon2012 ori-20120224
Pgcon2012 ori-20120224Pgcon2012 ori-20120224
Pgcon2012 ori-20120224
 
Ryu with OpenFlow 1.3, Traffic Monitor
Ryu with OpenFlow 1.3, Traffic MonitorRyu with OpenFlow 1.3, Traffic Monitor
Ryu with OpenFlow 1.3, Traffic Monitor
 
20150509 unix v6로 배우는 커널의 원리와 구조 3 김지은
20150509 unix v6로 배우는 커널의 원리와 구조 3 김지은20150509 unix v6로 배우는 커널의 원리와 구조 3 김지은
20150509 unix v6로 배우는 커널의 원리와 구조 3 김지은
 
Who carries your container? Zun or Magnum?
Who carries your container? Zun or Magnum?Who carries your container? Zun or Magnum?
Who carries your container? Zun or Magnum?
 
OPNFV & OpenStack
OPNFV & OpenStackOPNFV & OpenStack
OPNFV & OpenStack
 

Similaire à Debugging Ruby Systems

Reverse engineering Swisscom's Centro Grande Modem
Reverse engineering Swisscom's Centro Grande ModemReverse engineering Swisscom's Centro Grande Modem
Reverse engineering Swisscom's Centro Grande ModemCyber Security Alliance
 
Linux 系統管理與安全:進階系統管理系統防駭與資訊安全
Linux 系統管理與安全:進階系統管理系統防駭與資訊安全Linux 系統管理與安全:進階系統管理系統防駭與資訊安全
Linux 系統管理與安全:進階系統管理系統防駭與資訊安全維泰 蔡
 
A little systemtap
A little systemtapA little systemtap
A little systemtapyang bingwu
 
hacking-embedded-devices.pptx
hacking-embedded-devices.pptxhacking-embedded-devices.pptx
hacking-embedded-devices.pptxssuserfcf43f
 
DUG'20: 12 - DAOS in Lenovo’s HPC Innovation Center
DUG'20: 12 - DAOS in Lenovo’s HPC Innovation CenterDUG'20: 12 - DAOS in Lenovo’s HPC Innovation Center
DUG'20: 12 - DAOS in Lenovo’s HPC Innovation CenterAndrey Kudryavtsev
 
Velocity 2017 Performance analysis superpowers with Linux eBPF
Velocity 2017 Performance analysis superpowers with Linux eBPFVelocity 2017 Performance analysis superpowers with Linux eBPF
Velocity 2017 Performance analysis superpowers with Linux eBPFBrendan Gregg
 
Open Source Systems Performance
Open Source Systems PerformanceOpen Source Systems Performance
Open Source Systems PerformanceBrendan Gregg
 
USENIX ATC 2017 Performance Superpowers with Enhanced BPF
USENIX ATC 2017 Performance Superpowers with Enhanced BPFUSENIX ATC 2017 Performance Superpowers with Enhanced BPF
USENIX ATC 2017 Performance Superpowers with Enhanced BPFBrendan Gregg
 
pstack, truss etc to understand deeper issues in Oracle database
pstack, truss etc to understand deeper issues in Oracle databasepstack, truss etc to understand deeper issues in Oracle database
pstack, truss etc to understand deeper issues in Oracle databaseRiyaj Shamsudeen
 
Performance Tuning EC2 Instances
Performance Tuning EC2 InstancesPerformance Tuning EC2 Instances
Performance Tuning EC2 InstancesBrendan Gregg
 
Crash_Report_Mechanism_In_Tizen
Crash_Report_Mechanism_In_TizenCrash_Report_Mechanism_In_Tizen
Crash_Report_Mechanism_In_TizenLex Yu
 
Oracle Basics and Architecture
Oracle Basics and ArchitectureOracle Basics and Architecture
Oracle Basics and ArchitectureSidney Chen
 
Introduction to cloudforecast
Introduction to cloudforecastIntroduction to cloudforecast
Introduction to cloudforecastMasahiro Nagano
 
Building an Automated Behavioral Malware Analysis Environment using Free and ...
Building an Automated Behavioral Malware Analysis Environment using Free and ...Building an Automated Behavioral Malware Analysis Environment using Free and ...
Building an Automated Behavioral Malware Analysis Environment using Free and ...Jim Clausing
 
OSSNA 2017 Performance Analysis Superpowers with Linux BPF
OSSNA 2017 Performance Analysis Superpowers with Linux BPFOSSNA 2017 Performance Analysis Superpowers with Linux BPF
OSSNA 2017 Performance Analysis Superpowers with Linux BPFBrendan Gregg
 
Feb14 successful development
Feb14 successful developmentFeb14 successful development
Feb14 successful developmentConnor McDonald
 

Similaire à Debugging Ruby Systems (20)

Reverse engineering Swisscom's Centro Grande Modem
Reverse engineering Swisscom's Centro Grande ModemReverse engineering Swisscom's Centro Grande Modem
Reverse engineering Swisscom's Centro Grande Modem
 
Linux 系統管理與安全:進階系統管理系統防駭與資訊安全
Linux 系統管理與安全:進階系統管理系統防駭與資訊安全Linux 系統管理與安全:進階系統管理系統防駭與資訊安全
Linux 系統管理與安全:進階系統管理系統防駭與資訊安全
 
A little systemtap
A little systemtapA little systemtap
A little systemtap
 
hacking-embedded-devices.pptx
hacking-embedded-devices.pptxhacking-embedded-devices.pptx
hacking-embedded-devices.pptx
 
DUG'20: 12 - DAOS in Lenovo’s HPC Innovation Center
DUG'20: 12 - DAOS in Lenovo’s HPC Innovation CenterDUG'20: 12 - DAOS in Lenovo’s HPC Innovation Center
DUG'20: 12 - DAOS in Lenovo’s HPC Innovation Center
 
Velocity 2017 Performance analysis superpowers with Linux eBPF
Velocity 2017 Performance analysis superpowers with Linux eBPFVelocity 2017 Performance analysis superpowers with Linux eBPF
Velocity 2017 Performance analysis superpowers with Linux eBPF
 
Open Source Systems Performance
Open Source Systems PerformanceOpen Source Systems Performance
Open Source Systems Performance
 
USENIX ATC 2017 Performance Superpowers with Enhanced BPF
USENIX ATC 2017 Performance Superpowers with Enhanced BPFUSENIX ATC 2017 Performance Superpowers with Enhanced BPF
USENIX ATC 2017 Performance Superpowers with Enhanced BPF
 
pstack, truss etc to understand deeper issues in Oracle database
pstack, truss etc to understand deeper issues in Oracle databasepstack, truss etc to understand deeper issues in Oracle database
pstack, truss etc to understand deeper issues in Oracle database
 
Performance Tuning EC2 Instances
Performance Tuning EC2 InstancesPerformance Tuning EC2 Instances
Performance Tuning EC2 Instances
 
Crash_Report_Mechanism_In_Tizen
Crash_Report_Mechanism_In_TizenCrash_Report_Mechanism_In_Tizen
Crash_Report_Mechanism_In_Tizen
 
Kernel crashdump
Kernel crashdumpKernel crashdump
Kernel crashdump
 
Oracle Basics and Architecture
Oracle Basics and ArchitectureOracle Basics and Architecture
Oracle Basics and Architecture
 
Introduction to cloudforecast
Introduction to cloudforecastIntroduction to cloudforecast
Introduction to cloudforecast
 
Building an Automated Behavioral Malware Analysis Environment using Free and ...
Building an Automated Behavioral Malware Analysis Environment using Free and ...Building an Automated Behavioral Malware Analysis Environment using Free and ...
Building an Automated Behavioral Malware Analysis Environment using Free and ...
 
A22 Introduction to DTrace by Kyle Hailey
A22 Introduction to DTrace by Kyle HaileyA22 Introduction to DTrace by Kyle Hailey
A22 Introduction to DTrace by Kyle Hailey
 
SOFA Tutorial
SOFA TutorialSOFA Tutorial
SOFA Tutorial
 
OSSNA 2017 Performance Analysis Superpowers with Linux BPF
OSSNA 2017 Performance Analysis Superpowers with Linux BPFOSSNA 2017 Performance Analysis Superpowers with Linux BPF
OSSNA 2017 Performance Analysis Superpowers with Linux BPF
 
Hacking the swisscom modem
Hacking the swisscom modemHacking the swisscom modem
Hacking the swisscom modem
 
Feb14 successful development
Feb14 successful developmentFeb14 successful development
Feb14 successful development
 

Plus de Engine Yard

Engine Yard Partner Program 2014
Engine Yard Partner Program 2014Engine Yard Partner Program 2014
Engine Yard Partner Program 2014Engine Yard
 
Getting Started with PHP on Engine Yard Cloud
Getting Started with PHP on Engine Yard CloudGetting Started with PHP on Engine Yard Cloud
Getting Started with PHP on Engine Yard CloudEngine Yard
 
Engine Yard Cloud Architecture Enhancements
Engine Yard Cloud Architecture EnhancementsEngine Yard Cloud Architecture Enhancements
Engine Yard Cloud Architecture EnhancementsEngine Yard
 
6 tips for improving ruby performance
6 tips for improving ruby performance6 tips for improving ruby performance
6 tips for improving ruby performanceEngine Yard
 
Simplifying PCI on a PaaS Environment
Simplifying PCI on a PaaS EnvironmentSimplifying PCI on a PaaS Environment
Simplifying PCI on a PaaS EnvironmentEngine Yard
 
The Tao of Documentation
The Tao of DocumentationThe Tao of Documentation
The Tao of DocumentationEngine Yard
 
Innovate Faster in the Cloud with a Platform as a Service
Innovate Faster in the Cloud with a Platform as a ServiceInnovate Faster in the Cloud with a Platform as a Service
Innovate Faster in the Cloud with a Platform as a ServiceEngine Yard
 
Introduction to Ruby
Introduction to RubyIntroduction to Ruby
Introduction to RubyEngine Yard
 
JRuby: Enhancing Java Developers Lives
JRuby: Enhancing Java Developers LivesJRuby: Enhancing Java Developers Lives
JRuby: Enhancing Java Developers LivesEngine Yard
 
High Performance Ruby: Evented vs. Threaded
High Performance Ruby: Evented vs. ThreadedHigh Performance Ruby: Evented vs. Threaded
High Performance Ruby: Evented vs. ThreadedEngine Yard
 
Release Early & Release Often: Reducing Deployment Friction
Release Early & Release Often: Reducing Deployment FrictionRelease Early & Release Often: Reducing Deployment Friction
Release Early & Release Often: Reducing Deployment FrictionEngine Yard
 
JRuby Jam Session
JRuby Jam Session JRuby Jam Session
JRuby Jam Session Engine Yard
 
Rubinius and Ruby | A Love Story
Rubinius and Ruby | A Love Story Rubinius and Ruby | A Love Story
Rubinius and Ruby | A Love Story Engine Yard
 
Rails Antipatterns | Open Session with Chad Pytel
Rails Antipatterns | Open Session with Chad Pytel Rails Antipatterns | Open Session with Chad Pytel
Rails Antipatterns | Open Session with Chad Pytel Engine Yard
 
JRuby: Apples and Oranges
JRuby: Apples and OrangesJRuby: Apples and Oranges
JRuby: Apples and OrangesEngine Yard
 
Developing a Language
Developing a LanguageDeveloping a Language
Developing a LanguageEngine Yard
 
Everything Rubinius
Everything RubiniusEverything Rubinius
Everything RubiniusEngine Yard
 
Rails Hosting and the Woes
Rails Hosting and the WoesRails Hosting and the Woes
Rails Hosting and the WoesEngine Yard
 

Plus de Engine Yard (19)

Engine Yard Partner Program 2014
Engine Yard Partner Program 2014Engine Yard Partner Program 2014
Engine Yard Partner Program 2014
 
Getting Started with PHP on Engine Yard Cloud
Getting Started with PHP on Engine Yard CloudGetting Started with PHP on Engine Yard Cloud
Getting Started with PHP on Engine Yard Cloud
 
Engine Yard Cloud Architecture Enhancements
Engine Yard Cloud Architecture EnhancementsEngine Yard Cloud Architecture Enhancements
Engine Yard Cloud Architecture Enhancements
 
6 tips for improving ruby performance
6 tips for improving ruby performance6 tips for improving ruby performance
6 tips for improving ruby performance
 
Simplifying PCI on a PaaS Environment
Simplifying PCI on a PaaS EnvironmentSimplifying PCI on a PaaS Environment
Simplifying PCI on a PaaS Environment
 
The Tao of Documentation
The Tao of DocumentationThe Tao of Documentation
The Tao of Documentation
 
Innovate Faster in the Cloud with a Platform as a Service
Innovate Faster in the Cloud with a Platform as a ServiceInnovate Faster in the Cloud with a Platform as a Service
Innovate Faster in the Cloud with a Platform as a Service
 
Introduction to Ruby
Introduction to RubyIntroduction to Ruby
Introduction to Ruby
 
JRuby: Enhancing Java Developers Lives
JRuby: Enhancing Java Developers LivesJRuby: Enhancing Java Developers Lives
JRuby: Enhancing Java Developers Lives
 
High Performance Ruby: Evented vs. Threaded
High Performance Ruby: Evented vs. ThreadedHigh Performance Ruby: Evented vs. Threaded
High Performance Ruby: Evented vs. Threaded
 
Release Early & Release Often: Reducing Deployment Friction
Release Early & Release Often: Reducing Deployment FrictionRelease Early & Release Often: Reducing Deployment Friction
Release Early & Release Often: Reducing Deployment Friction
 
JRuby Jam Session
JRuby Jam Session JRuby Jam Session
JRuby Jam Session
 
Rubinius and Ruby | A Love Story
Rubinius and Ruby | A Love Story Rubinius and Ruby | A Love Story
Rubinius and Ruby | A Love Story
 
Rails Antipatterns | Open Session with Chad Pytel
Rails Antipatterns | Open Session with Chad Pytel Rails Antipatterns | Open Session with Chad Pytel
Rails Antipatterns | Open Session with Chad Pytel
 
JRuby: Apples and Oranges
JRuby: Apples and OrangesJRuby: Apples and Oranges
JRuby: Apples and Oranges
 
Developing a Language
Developing a LanguageDeveloping a Language
Developing a Language
 
Geemus
GeemusGeemus
Geemus
 
Everything Rubinius
Everything RubiniusEverything Rubinius
Everything Rubinius
 
Rails Hosting and the Woes
Rails Hosting and the WoesRails Hosting and the Woes
Rails Hosting and the Woes
 

Dernier

Abdul Kader Baba- Managing Cybersecurity Risks and Compliance Requirements i...
Abdul Kader Baba- Managing Cybersecurity Risks  and Compliance Requirements i...Abdul Kader Baba- Managing Cybersecurity Risks  and Compliance Requirements i...
Abdul Kader Baba- Managing Cybersecurity Risks and Compliance Requirements i...itnewsafrica
 
Testing tools and AI - ideas what to try with some tool examples
Testing tools and AI - ideas what to try with some tool examplesTesting tools and AI - ideas what to try with some tool examples
Testing tools and AI - ideas what to try with some tool examplesKari Kakkonen
 
[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality Assurance[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality AssuranceInflectra
 
Microsoft 365 Copilot: How to boost your productivity with AI – Part one: Ado...
Microsoft 365 Copilot: How to boost your productivity with AI – Part one: Ado...Microsoft 365 Copilot: How to boost your productivity with AI – Part one: Ado...
Microsoft 365 Copilot: How to boost your productivity with AI – Part one: Ado...Nikki Chapple
 
Top 10 Hubspot Development Companies in 2024
Top 10 Hubspot Development Companies in 2024Top 10 Hubspot Development Companies in 2024
Top 10 Hubspot Development Companies in 2024TopCSSGallery
 
The State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptxThe State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptxLoriGlavin3
 
QCon London: Mastering long-running processes in modern architectures
QCon London: Mastering long-running processes in modern architecturesQCon London: Mastering long-running processes in modern architectures
QCon London: Mastering long-running processes in modern architecturesBernd Ruecker
 
Glenn Lazarus- Why Your Observability Strategy Needs Security Observability
Glenn Lazarus- Why Your Observability Strategy Needs Security ObservabilityGlenn Lazarus- Why Your Observability Strategy Needs Security Observability
Glenn Lazarus- Why Your Observability Strategy Needs Security Observabilityitnewsafrica
 
A Framework for Development in the AI Age
A Framework for Development in the AI AgeA Framework for Development in the AI Age
A Framework for Development in the AI AgeCprime
 
Email Marketing Automation for Bonterra Impact Management (fka Social Solutio...
Email Marketing Automation for Bonterra Impact Management (fka Social Solutio...Email Marketing Automation for Bonterra Impact Management (fka Social Solutio...
Email Marketing Automation for Bonterra Impact Management (fka Social Solutio...Jeffrey Haguewood
 
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxDigital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxLoriGlavin3
 
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxThe Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxLoriGlavin3
 
React Native vs Ionic - The Best Mobile App Framework
React Native vs Ionic - The Best Mobile App FrameworkReact Native vs Ionic - The Best Mobile App Framework
React Native vs Ionic - The Best Mobile App FrameworkPixlogix Infotech
 
Modern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
Modern Roaming for Notes and Nomad – Cheaper Faster Better StrongerModern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
Modern Roaming for Notes and Nomad – Cheaper Faster Better Strongerpanagenda
 
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxThe Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxLoriGlavin3
 
Tampa BSides - The No BS SOC (slides from April 6, 2024 talk)
Tampa BSides - The No BS SOC (slides from April 6, 2024 talk)Tampa BSides - The No BS SOC (slides from April 6, 2024 talk)
Tampa BSides - The No BS SOC (slides from April 6, 2024 talk)Mark Simos
 
Potential of AI (Generative AI) in Business: Learnings and Insights
Potential of AI (Generative AI) in Business: Learnings and InsightsPotential of AI (Generative AI) in Business: Learnings and Insights
Potential of AI (Generative AI) in Business: Learnings and InsightsRavi Sanghani
 
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxA Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxLoriGlavin3
 
Zeshan Sattar- Assessing the skill requirements and industry expectations for...
Zeshan Sattar- Assessing the skill requirements and industry expectations for...Zeshan Sattar- Assessing the skill requirements and industry expectations for...
Zeshan Sattar- Assessing the skill requirements and industry expectations for...itnewsafrica
 
Emixa Mendix Meetup 11 April 2024 about Mendix Native development
Emixa Mendix Meetup 11 April 2024 about Mendix Native developmentEmixa Mendix Meetup 11 April 2024 about Mendix Native development
Emixa Mendix Meetup 11 April 2024 about Mendix Native developmentPim van der Noll
 

Dernier (20)

Abdul Kader Baba- Managing Cybersecurity Risks and Compliance Requirements i...
Abdul Kader Baba- Managing Cybersecurity Risks  and Compliance Requirements i...Abdul Kader Baba- Managing Cybersecurity Risks  and Compliance Requirements i...
Abdul Kader Baba- Managing Cybersecurity Risks and Compliance Requirements i...
 
Testing tools and AI - ideas what to try with some tool examples
Testing tools and AI - ideas what to try with some tool examplesTesting tools and AI - ideas what to try with some tool examples
Testing tools and AI - ideas what to try with some tool examples
 
[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality Assurance[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality Assurance
 
Microsoft 365 Copilot: How to boost your productivity with AI – Part one: Ado...
Microsoft 365 Copilot: How to boost your productivity with AI – Part one: Ado...Microsoft 365 Copilot: How to boost your productivity with AI – Part one: Ado...
Microsoft 365 Copilot: How to boost your productivity with AI – Part one: Ado...
 
Top 10 Hubspot Development Companies in 2024
Top 10 Hubspot Development Companies in 2024Top 10 Hubspot Development Companies in 2024
Top 10 Hubspot Development Companies in 2024
 
The State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptxThe State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptx
 
QCon London: Mastering long-running processes in modern architectures
QCon London: Mastering long-running processes in modern architecturesQCon London: Mastering long-running processes in modern architectures
QCon London: Mastering long-running processes in modern architectures
 
Glenn Lazarus- Why Your Observability Strategy Needs Security Observability
Glenn Lazarus- Why Your Observability Strategy Needs Security ObservabilityGlenn Lazarus- Why Your Observability Strategy Needs Security Observability
Glenn Lazarus- Why Your Observability Strategy Needs Security Observability
 
A Framework for Development in the AI Age
A Framework for Development in the AI AgeA Framework for Development in the AI Age
A Framework for Development in the AI Age
 
Email Marketing Automation for Bonterra Impact Management (fka Social Solutio...
Email Marketing Automation for Bonterra Impact Management (fka Social Solutio...Email Marketing Automation for Bonterra Impact Management (fka Social Solutio...
Email Marketing Automation for Bonterra Impact Management (fka Social Solutio...
 
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxDigital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
 
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxThe Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
 
React Native vs Ionic - The Best Mobile App Framework
React Native vs Ionic - The Best Mobile App FrameworkReact Native vs Ionic - The Best Mobile App Framework
React Native vs Ionic - The Best Mobile App Framework
 
Modern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
Modern Roaming for Notes and Nomad – Cheaper Faster Better StrongerModern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
Modern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
 
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxThe Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
 
Tampa BSides - The No BS SOC (slides from April 6, 2024 talk)
Tampa BSides - The No BS SOC (slides from April 6, 2024 talk)Tampa BSides - The No BS SOC (slides from April 6, 2024 talk)
Tampa BSides - The No BS SOC (slides from April 6, 2024 talk)
 
Potential of AI (Generative AI) in Business: Learnings and Insights
Potential of AI (Generative AI) in Business: Learnings and InsightsPotential of AI (Generative AI) in Business: Learnings and Insights
Potential of AI (Generative AI) in Business: Learnings and Insights
 
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxA Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
 
Zeshan Sattar- Assessing the skill requirements and industry expectations for...
Zeshan Sattar- Assessing the skill requirements and industry expectations for...Zeshan Sattar- Assessing the skill requirements and industry expectations for...
Zeshan Sattar- Assessing the skill requirements and industry expectations for...
 
Emixa Mendix Meetup 11 April 2024 about Mendix Native development
Emixa Mendix Meetup 11 April 2024 about Mendix Native developmentEmixa Mendix Meetup 11 April 2024 about Mendix Native development
Emixa Mendix Meetup 11 April 2024 about Mendix Native development
 

Debugging Ruby Systems

  • 1. DEBUGGING RUBY Aman Gupta @tmm1 http://tinyurl.com/eyfast
  • 6. THIS TALK IS ABOUT... TOOLS TO FIX THESE ISSUES.
  • 7. TOOLS FOR LINUX. lsof strace ltrace pleeker (flickr)
  • 8. TOOLS FOR C CODE. perftools gdb booddin (flickr)
  • 9. TOOLS FOR NETWORKS. tcpdump ngrep pascal.charest (flickr)
  • 10. TOOLS FOR CPU USAGE. perftools perftools.rb marksze (flickr)
  • 11. TOOLS FOR MEMORY USAGE. bleak_house gdb.rb kgrocki (flickr) memprof
  • 12. IGNORE THE FINE PRINT mayu (flickr) delgrossodotcom (flickr)
  • 13. LSOF list open files lsof -nPp <pid>
  • 14. lsof -nPp <pid> -n Inhibits the conversion of network numbers to host names. -P Inhibits the conversion of port numbers to names for network files FD TYPE NAME json cwd DIR /var/www/myapp memcached txt REG /usr/bin/ruby mysql mem REG /json-1.1.9/ext/json/ext/generator.so http mem REG /json-1.1.9/ext/json/ext/parser.so mem REG /memcached-0.17.4/lib/rlibmemcached.so mem REG /mysql-2.8.1/lib/mysql_api.so 0u CHR /dev/null 1w REG /usr/local/nginx/logs/error.log 2w REG /usr/local/nginx/logs/error.log 3u IPv4 10.8.85.66:33326->10.8.85.68:3306 (ESTABLISHED) 10u IPv4 10.8.85.66:33327->10.8.85.68:3306 (ESTABLISHED) 11u IPv4 127.0.0.1:58273->127.0.0.1:11211 (ESTABLISHED) 12u REG /tmp/RackMultipart.28957.0 33u IPv4 174.36.83.42:37466->69.63.180.21:80 (ESTABLISHED)
  • 15. STRACE trace system calls and signals strace -cp <pid> strace -ttTp <pid> -o <file>
  • 16. strace -cp <pid> -c Count time, calls, and errors for each system call and report a summary on program exit. -p pid Attach to the process with the process ID pid and begin tracing. % time seconds usecs/call calls errors syscall ------ ----------- ----------- --------- --------- ---------------- 50.39 0.000064 0 1197 592 read 34.65 0.000044 0 609 writev 14.96 0.000019 0 1226 epoll_ctl 0.00 0.000000 0 4 close 0.00 0.000000 0 1 select 0.00 0.000000 0 4 socket 0.00 0.000000 0 4 4 connect 0.00 0.000000 0 1057 epoll_wait ------ ----------- ----------- --------- --------- ---------------- 100.00 0.000127 4134 596 total
  • 17. strace -ttTp <pid> -o <file> -t Prefix each line of the trace with the time of day. -tt If given twice, the time printed will include the microseconds. -T Show the time spent in system calls. -o filename Write the trace output to the file filename rather than to stderr. epoll_wait(9, {{EPOLLIN, {u32=68841296, u64=68841296}}}, 4096, 50) = 1 <0.033109> accept(10, {sin_port=38313, sin_addr="127.0.0.1"}, [1226]) = 22 <0.000014> fcntl(22, F_GETFL) = 0x2 (flags O_RDWR) <0.000007> fcntl(22, F_SETFL, O_RDWR|O_NONBLOCK) = 0 <0.000008> setsockopt(22, SOL_TCP, TCP_NODELAY, [1], 4) = 0 <0.000008> accept(10, 0x7fff5d9c07d0, [1226]) = -1 EAGAIN <0.000014> epoll_ctl(9, EPOLL_CTL_ADD, 22, {EPOLLIN, {u32=108750368, u64=108750368}}) = 0 <0.000009> epoll_wait(9, {{EPOLLIN, {u32=108750368, u64=108750368}}}, 4096, 50) = 1 <0.000007> read(22, "GET / HTTP/1.1r"..., 16384) = 772 <0.000012> rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0 <0.000007> poll([{fd=5, events=POLLIN|POLLPRI}], 1, 0) = 0 (Timeout) <0.000008> write(5, "1000000-0003SELECT * FROM `table`"..., 56) = 56 <0.000023> read(5, "25101,20x234m"..., 16384) = 284 <1.300897>
  • 18. http client connection read 772 bytes read(22, "GET / HTTP/1.1r"..., 16384) = 772 <0.0012> incoming http request took 0.0012s
  • 19. mysql connection write sql query to db write(5, "SELECT * FROM `table`"..., 56) = 56 <0.0023> read(5, "25101,20x234m"..., 16384) = 284 <1.30> read query response slow query
  • 20. stracing ruby: SIGVTALRM --- SIGVTALRM (Virtual timer expired) @ 0 (0) --- rt_sigreturn(0x1a) = 2207807 <0.000009> --- SIGVTALRM (Virtual timer expired) @ 0 (0) --- rt_sigreturn(0x1a) = 0 <0.000009> --- SIGVTALRM (Virtual timer expired) @ 0 (0) --- rt_sigreturn(0x1a) = 140734552062624 <0.000009> --- SIGVTALRM (Virtual timer expired) @ 0 (0) --- rt_sigreturn(0x1a) = 140734552066688 <0.000009> --- SIGVTALRM (Virtual timer expired) @ 0 (0) --- rt_sigreturn(0x1a) = 11333952 <0.000008> --- SIGVTALRM (Virtual timer expired) @ 0 (0) --- rt_sigreturn(0x1a) = 0 <0.000009> --- SIGVTALRM (Virtual timer expired) @ 0 (0) --- rt_sigreturn(0x1a) = 1 <0.000010> --- SIGVTALRM (Virtual timer expired) @ 0 (0) --- • ruby 1.8 uses signals to schedule its green threads • process receives a SIGVTALRM signal every 10ms
  • 21. stracing ruby: sigprocmask % time seconds usecs/call calls errors syscall ------ ----------- ----------- --------- --------- ---------------- 100.00 0.326334 0 3568567 rt_sigprocmask 0.00 0.000000 0 9 read 0.00 0.000000 0 10 open 0.00 0.000000 0 10 close 0.00 0.000000 0 9 fstat 0.00 0.000000 0 25 mmap ------ ----------- ----------- --------- --------- ---------------- 100.00 0.326334 3568685 0 total • debian/redhat compile ruby with --enable-pthread • uses a native thread timer for SIGVTALRM • causes excessive calls to sigprocmask: 30% slowdown!
  • 22. TCPDUMP dump traffic on a network tcpdump -i eth0 -s 0 -nqA tcp dst port 3306
  • 23. tcpdump -i <eth> -s <len> -nqA <expr> tcpdump -i <eth> -w <file> <expr> -i <eth> Network interface. -s <len> Snarf len bytes of data from each packet. -n Don't convert addresses (host addresses, port numbers) to names. -q Quiet output. Print less protocol information. -A Print each packet (minus its link level header) in ASCII. -w <file> Write the raw packets to file rather than printing them out. <expr> libpcap expression, for example: tcp src port 80 tcp dst port 3306
  • 24. tcp dst port 80 19:52:20.216294 IP 24.203.197.27.40105 > 174.37.48.236.80: tcp 438 E...*.@.l.%&.....%0....POx..%s.oP....... GET /poll_images/cld99erh0/logo.png HTTP/1.1 Accept: */* Referer: http://apps.facebook.com/realpolls/? _fb_q=1
  • 25. tcp dst port 3306 19:51:06.501632 IP 10.8.85.66.50443 > 10.8.85.68.3306: tcp 98 E..."K@.@.Yy .UB .UD.....z....L............ GZ.y3b..[......W.... SELECT * FROM `votes` WHERE (`poll_id` = 72621) LIMIT 1
  • 27. PERFTOOLS google's performance tools CPUPROFILE=/tmp/myprof ./myapp pprof ./myapp /tmp/myprof
  • 28. wget http://google-perftools.googlecode.com/files/google- perftools-1.6.tar.gz download tar zxvf google-perftools-1.6.tar.gz cd google-perftools-1.6 ./configure --prefix=/opt make compile sudo make install # for linux export LD_PRELOAD=/opt/lib/libprofiler.so setup # for osx export DYLD_INSERT_LIBRARIES=/opt/lib/libprofiler.dylib CPUPROFILE=/tmp/ruby.prof ruby -e' profile 5_000_000.times{ "hello world" } ' pprof `which ruby` --text /tmp/ruby.prof report
  • 29. pprof ruby pprof ruby ruby.prof --text ruby.prof --gif Total: 103 samples 95 92.2% rb_yield_0 103 100.0% rb_eval 12 11.7% gc_sweep 52 50.5% rb_str_new3 3 2.9% obj_free 103 100.0% int_dotimes 12 11.7% gc_mark
  • 30. Profiling MRI • 10% of production VM time spent in rb_str_sub_bang • String#sub! • called from Time.parse return unless str.sub!(/A(d{1,2})/, '') return unless str.sub!(/A( d|d{1,2})/, '') return unless str.sub!(/A( d|d{1,2})/, '') return unless str.sub!(/A(d{1,3})/, '') return unless str.sub!(/A(d{1,2})/, '') return unless str.sub!(/A(d{1,2})/, '')
  • 31. Profiling EM + threads Total: 3763 samples 2764 73.5% catch_timer 989 26.3% memcpy 3 0.1% st_lookup 2 0.1% rb_thread_schedule 1 0.0% rb_eval 1 0.0% rb_newobj 1 0.0% rb_gc_force_recycle • known issue: EM+threads = slow • memcpy?? • thread context switches copy the stack w/ memcpy • EM allocates huge buffer on the stack • solution: move buffer to the heap
  • 32. PERFTOOLS.RB perftools for ruby code pprof.rb /tmp/myrbprof github.com/tmm1/perftools.rb
  • 33. gem install perftools.rb RUBYOPT="-r`gem which perftools | tail -1`" CPUPROFILE=/tmp/myrbprof ruby myapp.rb pprof.rb /tmp/myrbprof --text pprof.rb /tmp/myrbprof --gif > /tmp/myrbprof.gif
  • 34. require 'sinatra' $ ab -c 1 -n 50 http://127.0.0.1:4567/compute $ ab -c 1 -n 50 http://127.0.0.1:4567/sleep get '/sleep' do sleep 0.25 'done' • Sampling profiler: end • 232 samples total get '/compute' do • 83 samples were in /compute proc{ |n| a,b=0,1 • 118 samples had /compute on the stack but were in n.times{ a,b = b,a+b } another function b }.call(10_000) • /compute accounts for 50% 'done' of process, but only 35% of time was in /compute itself end == Sinatra has ended his set (crowd applauds) PROFILE: interrupts/evictions/bytes = 232/0/2152 Total: 232 samples 83 35.8% 35.8% 118 50.9% Sinatra::Application#GET /compute 56 24.1% 59.9% 56 24.1% garbage_collector 35 15.1% 75.0% 113 48.7% Integer#times
  • 35. CPUPROFILE_REALTIME=1 CPUPROFILE=app.prof CPUPROFILE=app-rt.prof
  • 38. faster bundle install • 23% spent in Gem::Version#<=> • simple patch to rubygems improved overall install performance by 15% • http://gist.github.com/ 458185
  • 39. CPUPROFILE_OBJECTS=1 CPUPROFILE=app-objs.prof • object allocation profiler mode built-in • 1 sample = 1 object created • Time parsing is both CPU and object allocation intensive • using mysql2 moves this to C
  • 40. LTRACE trace library calls ltrace -cp <pid> ltrace -ttTp <pid> -o <file>
  • 41. ltrace -c ruby threaded_em.rb % time seconds usecs/call calls function ------ ----------- ----------- --------- -------------------- 48.65 11.741295 617 19009 memcpy 30.16 7.279634 831 8751 longjmp 9.78 2.359889 135 17357 _setjmp 8.91 2.150565 285 7540 malloc 1.10 0.265946 20 13021 memset 0.81 0.195272 19 10105 __ctype_b_loc 0.35 0.084575 19 4361 strcmp 0.19 0.046163 19 2377 strlen 0.03 0.006272 23 265 realloc ------ ----------- ----------- --------- -------------------- 100.00 24.134999 82999 total ltrace -ttT -e memcpy ruby threaded_em.rb 01:24:48.769408 --- SIGVTALRM (Virtual timer expired) --- 01:24:48.769616 memcpy(0x1216000, "", 1086328) = 0x1216000 <0.000578> 01:24:48.770555 memcpy(0x6e32670, "240&343v", 1086328) = 0x6e32670 <0.000418> 01:24:49.899414 --- SIGVTALRM (Virtual timer expired) --- 01:24:49.899490 memcpy(0x1320000, "", 1082584) = 0x1320000 <0.000628> 01:24:49.900474 memcpy(0x6e32670, "", 1086328) = 0x6e32670 <0.000479>
  • 42. LTRACE/LIBDL trace dlopen’d library calls ltrace -F <conf> -bg -x <symbol> -p <pid> github.com/ice799/ltrace/tree/libdl
  • 43. ltrace -F <conf> -b -g -x <sym> -b Ignore signals. -g Ignore libraries linked at compile time. -F <conf> Read prototypes from config file. -x <sym> Trace calls to the function sym. -s <num> Show first num bytes of string args. -F ltrace.conf int mysql_real_query(addr,string,ulong); void garbage_collect(void); int memcached_set(addr,string,ulong,string,ulong);
  • 44. ltrace -x garbage_collect 19:08:06.436926 garbage_collect() = <void> <0.221679> 19:08:15.329311 garbage_collect() = <void> <0.187546> 19:08:17.662149 garbage_collect() = <void> <0.199200> 19:08:20.486655 garbage_collect() = <void> <0.205864> 19:08:25.102302 garbage_collect() = <void> <0.214295> 19:08:35.552337 garbage_collect() = <void> <0.189172>
  • 45. ltrace -x mysql_real_query mysql_real_query(0x1c9e0500, "SET NAMES 'UTF8'", 16) = 0 <0.000324> mysql_real_query(0x1c9e0500, "SET SQL_AUTO_IS_NULL=0", 22) = 0 <0.000322> mysql_real_query(0x19c7a500, "SELECT * FROM `users`", 21) = 0 <1.206506> mysql_real_query(0x1c9e0500, "COMMIT", 6) = 0 <0.000181>
  • 46. ltrace -x memcached_set memcached_set(0x15d46b80, "Status:33", 21, "004b", 366) = 0 <0.01116> memcached_set(0x15d46b80, "Status:96", 21, "004b", 333) = 0 <0.00224> memcached_set(0x15d46b80, "Status:57", 21, "004b", 298) = 0 <0.01850> memcached_set(0x15d46b80, "Status:10", 21, "004b", 302) = 0 <0.00530> memcached_set(0x15d46b80, "Status:67", 21, "004b", 318) = 0 <0.00291> memcached_set(0x15d46b80, "Status:02", 21, "004b", 299) = 0 <0.00658> memcached_set(0x15d46b80, "Status:34", 21, "004b", 264) = 0 <0.00243>
  • 47. GDB the GNU debugger gdb <executable> gdb attach <pid>
  • 48. Debugging Ruby Segfaults test_segv.rb:4: [BUG] Segmentation fault ruby 1.8.7 (2008-08-11 patchlevel 72) [i686-darwin9.7.0] def test #include "ruby.h" require 'segv' 4.times do VALUE Dir.chdir '/tmp' do segv() Hash.new{ segv }[0] { end VALUE array[1]; end array[1000000] = NULL; end return Qnil; } sleep 10 test() void Init_segv() { rb_define_method(rb_cObject, "segv", segv, 0); }
  • 49. 1. Attach to running process $ ps aux | grep ruby joe 23611 0.0 0.1 25424 7540 S Dec01 0:00 ruby test_segv.rb $ sudo gdb ruby 23611 Attaching to program: ruby, process 23611 0x00007fa5113c0c93 in nanosleep () from /lib/libc.so.6 (gdb) c Continuing. Program received signal SIGBUS, Bus error. segv () at segv.c:7 7 array[1000000] = NULL; 2. Use a coredump Process.setrlimit Process::RLIMIT_CORE, 300*1024*1024 $ sudo mkdir /cores $ sudo chmod 777 /cores $ sudo sysctl kernel.core_pattern=/cores/%e.core.%s.%p.%t $ sudo gdb ruby /cores/ruby.core.6.23611.1259781224
  • 50. def test require 'segv' 4.times do Dir.chdir '/tmp' do Hash.new{ segv }[0] end end (gdb) where end #0 segv () at segv.c:7 #1 0x000000000041f2be in call_cfunc () at eval.c:5727 test() ... #13 0x000000000043ba8c in rb_hash_default () at hash.c:521 ... #19 0x000000000043b92a in rb_hash_aref () at hash.c:429 ... #26 0x00000000004bb7bc in chdir_yield () at dir.c:728 #27 0x000000000041d8d7 in rb_ensure () at eval.c:5528 #28 0x00000000004bb93a in dir_s_chdir () at dir.c:816 ... #35 0x000000000041c444 in rb_yield () at eval.c:5142 #36 0x0000000000450690 in int_dotimes () at numeric.c:2834 ... #48 0x0000000000412a90 in ruby_run () at eval.c:1678 #49 0x000000000041014e in main () at main.c:48
  • 51. GDB.RB gdb with MRI hooks gem install gdb.rb gdb.rb <pid> github.com/tmm1/gdb.rb
  • 52. (gdb) ruby eval 1+2 3 (gdb) ruby eval Thread.current #<Thread:0x1d630 run> (gdb) ruby eval Thread.list.size 8
  • 53. (gdb) ruby threads list 0x15890 main thread THREAD_STOPPED WAIT_JOIN(0x19ef4) 0x19ef4 thread THREAD_STOPPED WAIT_TIME(57.10s) 0x19e34 thread THREAD_STOPPED WAIT_FD(5) 0x19dc4 thread THREAD_STOPPED WAIT_NONE 0x19dc8 thread THREAD_STOPPED WAIT_NONE 0x19dcc thread THREAD_STOPPED WAIT_NONE 0x22668 thread THREAD_STOPPED WAIT_NONE 0x1d630 curr thread THREAD_RUNNABLE WAIT_NONE
  • 54. (gdb) ruby objects HEAPS 8 SLOTS 1686252 LIVE 893327 (52.98%) FREE 792925 (47.02%) scope 1641 (0.18%) regexp 2255 (0.25%) data 3539 (0.40%) class 3680 (0.41%) hash 6196 (0.69%) object 8785 (0.98%) array 13850 (1.55%) string 105350 (11.79%) node 742346 (83.10%)
  • 55. (gdb) ruby objects strings 140 u'lib' 158 u'0' 294 u'n' 619 u'' 30503 unique strings 3187435 bytes
  • 56. def test require 'segv' 4.times do Dir.chdir '/tmp' do Hash.new{ segv }[0] end end end (gdb) ruby threads test() 0xa3e000 main curr thread THREAD_RUNNABLE WAIT_NONE node_vcall segv in test_segv.rb:5 node_call test in test_segv.rb:5 node_call call in test_segv.rb:5 node_call default in test_segv.rb:5 node_call [] in test_segv.rb:5 node_call test in test_segv.rb:4 node_call chdir in test_segv.rb:4 node_call test in test_segv.rb:3 node_call times in test_segv.rb:3 node_vcall test in test_segv.rb:9
  • 57. rails_warden leak (gdb) ruby objects classes 1197 MIME::Type 2657 NewRelic::MetricSpec 2719 TZInfo::TimezoneTransitionInfo 4124 Warden::Manager 4124 MethodOverrideForAll 4124 AccountMiddleware 4124 Rack::Cookies 4125 ActiveRecord::ConnectionAdapters::ConnectionManagement 4125 ActionController::Session::CookieStore 4125 ActionController::Failsafe 4125 ActionController::ParamsParser 4125 Rack::Lock 4125 ActionController::Dispatcher 4125 ActiveRecord::QueryCache 4125 ActiveSupport::MessageVerifier 4125 Rack::Head middleware chain leaking per request
  • 58. mongrel sleeper thread 0x16814c00 thread THREAD_STOPPED WAIT_TIME(0.47) 1522 bytes node_fcall sleep in lib/mongrel/configurator.rb:285 node_fcall run in lib/mongrel/configurator.rb:285 node_fcall loop in lib/mongrel/configurator.rb:285 node_call run in lib/mongrel/configurator.rb:285 node_call initialize in lib/mongrel/configurator.rb:285 node_call new in lib/mongrel/configurator.rb:285 node_call run in bin/mongrel_rails:128 node_call run in lib/mongrel/command.rb:212 node_call run in bin/mongrel_rails:281 node_fcall (unknown) in bin/mongrel_rails:19 def run @listeners.each {|name,s| s.run } $mongrel_sleeper_thread = Thread.new { loop { sleep 1 } } end
  • 59. god memory leaks (gdb) ruby objects arrays 43 God::Process elements instances 43 God::Watch 94310 3 43 God::Driver 94311 3 43 God::DriverEventQueue 94314 2 43 God::Conditions::MemoryUsage 94316 1 43 God::Conditions::ProcessRunning 43 God::Behaviors::CleanPidFile 5369 arrays 45 Process::Status 2863364 member elements 86 God::Metric 327 God::System::SlashProcPoller many arrays with 327 God::System::Process 90k+ elements! 406 God::DriverEvent 5 separate god leaks fixed by Eric Lindvall with the help of gdb.rb!
  • 60. MEMPROF a heap visualizer for ruby gem install memprof open http://memprof.com github.com/ice799/memprof
  • 61. memprof features • memprof.track • memprof.dump • memprof.dump_all • memprof.com
  • 62. Memprof.track{ 100.times{ "abc" } 100.times{ 1.23 + 1 } 100.times{ Module.new } } 100 file.rb:2:String 100 file.rb:3:Float 100 file.rb:4:Module • like bleak_house, but for a given block of code • use Memprof::Middleware in your webapps to run track per request
  • 63. memprof features • memprof.track • memprof.dump • memprof.dump_all • memprof.com
  • 64. Memprof.dump{ strings } "hello" + "world" { "_id": "0x19c610", memory address of object "file": "file.rb", file and line where string "line": 2, was created "type": "string", "class": "0x1ba7f0", address of the class "class_name": "String", “String” "length": 10, length and contents "data": "helloworld" of this string instance }
  • 65. arrays Memprof.dump{ [ 1, :b, { "_id": "0x19c5c0", 2.2, "d" "class": "0x1b0d18", ] "class_name": "Array", } "length": 4, "data": [ 1, integers and symbols are ":b", stored in the array itself "0x19c750", floats and strings are "0x19c598" separate ruby objects ] }
  • 66. hashes Memprof.dump{ { :a => 1, "b" => 2.2 { } "_id": "0x19c598", } "type": "hash", "class": "0x1af170", "class_name": "Hash", "default": null, no default proc "length": 2, "data": [ [ ":a", 1 ], hash entries as key/value [ "0xc728", "0xc750" ] pairs ] }
  • 67. classes Memprof.dump{ class Hello @@var=1 Const=2 { def world() end "_id": "0x19c408", end "type": "class", } "name": "Hello", "super": "0x1bfa48", superclass object reference "super_name": "Object", "ivars": { class variables and constants "@@var": 1, are stored in the instance "Const": 2 }, variable table "methods": { "world": "0x19c318" references to method objects } }
  • 68. memprof features • memprof.track • memprof.dump • memprof.dump_all • memprof.com
  • 69. Memprof.dump_all("myapp_heap.json") • dump out every single live object as json • one per line to specified file • analyze via • jsawk/grep • mongodb/couchdb • custom ruby scripts • libyajl + Boost Graph Library
  • 70. memprof features • memprof.track • memprof.dump • memprof.dump_all • memprof.com
  • 71. memprof.com a web-based heap visualizer and leak analyzer
  • 72. plugging a leak in rails3 • in dev mode, rails3 is leaking 10mb per request let’s use memprof to find it! # in environment.rb require `gem which memprof/signal`.strip
  • 73. plugging a leak in rails3 send the app some requests so it leaks $ ab -c 1 -n 30 http://localhost:3000/ tell memprof to dump out the entire heap to json $ memprof --pid <pid> --name <dump name> --key <api key>
  • 74. 2519 classes 30 copies of TestController mongo query for all TestController classes details for one copy of TestController
  • 75. find references to object “leak” is on line 178 holding references to all controllers
  • 76. • In development mode, Rails reloads all your application code on every request • ActionView::Partials::PartialRenderer is caching partials used by each controller as an optimization • But.. it ends up holding a reference to every single reloaded version of those controllers
  • 77. MORE* MEMPROF FEATURES • memprof.trace • memprof::tracer * currently under development
  • 78. config.middleware.use(Memprof::Tracer) { "time": 4.3442, total time for request "rails": { rails controller/action "controller": "test", "action": "index" }, "request": { request env info "REQUEST_PATH": "/test", "REQUEST_METHOD": "GET" },
  • 79. config.middleware.use(Memprof::Tracer) "mysql": { "queries": 3, 3 mysql queries "time": 0.00109302 }, "gc": { "calls": 8, 8 calls to GC "time": 2.04925 2 secs spent in GC },
  • 80. config.middleware.use(Memprof::Tracer) "objects": { "created": 3911103, 3 million objs created "types": { "none": 1168831, 1 million method calls "object": 1127, object instances "float": 627, "string": 1334637, lots of strings "array": 609313, lots of arrays "hash": 3676, "match": 70211 regexp matches } } }
  • 81. RACK-PERFTOOLS rack middleware for perftools.rb gem install rack- perftools_profiler github.com/bhb/rack-perftools_profiler
  • 82. require 'rack/perftools_profiler' config.middleware.insert( 0, Rack::PerftoolsProfiler, :default_printer => 'gif' ) $ curl http://localhost:3000/__start__ $ curl http://localhost:3000/home $ curl http://localhost:3000/about $ curl http://localhost:3000/__stop__ $ curl http://localhost:3000/__data__ -o profile.gif $ curl http://localhost:3000/__data__?printer=text -o profile.txt $ curl "http://localhost:3000/home?profile=true&times=10" -o 10_requests_to_homepage.gif
  • 84. LEARN THESE TOOLS. USE THESE TOOLS. yujie (flickr)
  • 85. EY CASE STUDY • Example of Professional Services engagement • Interested? http://tinyurl.com/eyfast http://tinyurl.com/eyfast
  • 86. LSOF 15u IPv4 TCP ->10.243.63.80:11211 (ESTABLISHED) 20u IPv4 TCP ->10.243.63.80:11211 (ESTABLISHED) 23u IPv4 TCP ->10.243.63.80:11211 (ESTABLISHED) multiple connections to memcached via different drivers 18r DIR /shared/public/javascripts/packaged 19r DIR /shared/public/javascripts/packaged 22r DIR /shared/public/javascripts/packaged multiple open handles to javascript assets directories
  • 87. STRACE % time seconds calls syscall ------ ----------- --------- --------- 26.28 0.054178 8731 read 25.81 0.053216 316519 stat 20.37 0.041993 1 clone 15.83 0.032648 11034 getdents 3.54 0.007309 10326 write 40% of kernel time querying filesystem
  • 88. LTRACE mysql_query("SELECT * FROM tags WHERE id = 9129") mysql_query("SELECT * FROM tags WHERE id = 9129") mysql_query("SELECT * FROM tag_info WHERE tag_id = 9129") mysql_query("SELECT * FROM tags WHERE id = 9129") mysql_query("SELECT * FROM tags WHERE id = 9129") mysql_query("SELECT * FROM tags WHERE id = 9129") common queries repeated multiple times during a request
  • 89. GDB.RB (gdb) ruby objects HEAPS 10 SLOTS 4450607 LIVE 2006769 (45.09%) FREE 2443838 (54.91%) large ruby heap hash 12939 (0.64%) numerous 'node' array 38007 (1.89%) objects- required object 47633 (2.37%) libraries and plugins string 234205 (11.67%) that are no longer in node 1637926 (81.62%) use
  • 90. PERFTOOLS.RB majority of ruby process' time on CPU spent in garbage collection
  • 91. MEMPROF wide distribution of response times expensive controller actions creating many millions of objects per request
  • 92. MEMPROF 37% of response time attributed to garbage collection
  • 93. BEFORE Time taken for tests: 20.156 seconds Complete requests: 100 Requests per second: 4.96 [#/sec] (mean) Time per request: 201.555 [ms] (mean) AFTER Time taken for tests: 8.100 seconds Complete requests: 100 Requests per second: 12.35 [#/sec] (mean) Time per request: 81.000 [ms] (mean) 2.5x improvement in throughput after addressing some of these issues and tuning GC
  • 94. QUESTIONS? Aman Gupta @tmm1 http://scr.bi/debuggingruby