DTrace Topics Quick Wins

From Siwiki

Jump to: navigation, search

Contents

[edit] DTrace Topics: Quick Wins

This article is about DTrace Quick Wins, and is part of the DTrace Topics collection. A general understanding of DTrace is assumed knowledge, which can be studied from the DTrace Topics: Intro section.

DTrace is a dynamic troubleshooting and analysis tool first introduced in the Solaris 10 and OpenSolaris operating systems.

Completion Image:trafficlight_yellow02.png
Difficulty Image:coffeemug01.png Image:coffeemug01.png
Audience New DTrace users

[edit] DTrace Quick Wins

DTrace is a comprehensive tracing framework that can examine the entire software stack, including the kernel. That's the good news. The bad news is that this is an overwhelming amount of visibility, leaving many new users feeling helpless and lost.

There has been much effort to make DTrace more approachable, such as the creation of stable high level providers, and the numerous examples in both the DTrace Guide and the DTraceToolkit. However I am still often asked,

"Just tell me the top things to try"

This isn't easy to answer for the following reasons:

[edit] The Good

  • You may get some quick performance wins
  • A very practical way to indroduce you to DTrace

[edit] The Bad

  • Can only introduce you to a fraction of the field of DTrace
  • Every site is different, there is no one-size-fits-all set of scripts
  • Somewhat ill-conceived; DTrace wins often aren't that quick

[edit] The Ugly

  • A customer declaring that "DTrace found nothing" after only trying the quick wins


We hope that some of this quick wins do work for you, and that they introduce you to DTrace. They are very generic, and only a fraction of what DTrace can do (see DTrace Topics).

[edit] Process Execution

[edit] How

Trace the creation of new processes using this one-liner,

# dtrace -n 'proc:::exec-success { trace(curpsinfo->pr_psargs); }'

[edit] Examples

The following output caught the execution of man ls, and all the processes which it creates,

dtrace: description 'proc:::exec-success ' matched 1 probe
CPU     ID                    FUNCTION:NAME
  0  13772         exec_common:exec-success   man ls                           
  0  13772         exec_common:exec-success   sh -c cd /usr/man; tbl /usr/man/man1/ls.1 |neqn /usr/share/lib/pub/eqnchar - |n
  0  13772         exec_common:exec-success   tbl /usr/man/man1/ls.1           
  0  13772         exec_common:exec-success   neqn /usr/share/lib/pub/eqnchar -
  0  13772         exec_common:exec-success   nroff -u0 -Tlp -man -            
  0  13772         exec_common:exec-success   col -x                           
  0  13772         exec_common:exec-success   sh -c trap  1 15; /usr/bin/mv -f /tmp/mpY7aGaF /usr/man/cat1/ls.1 2> /dev/nul
  0  13772         exec_common:exec-success   /usr/bin/mv -f /tmp/mpY7aGaF /usr/man/cat1/ls.1
  0  13772         exec_common:exec-success   sh -c more /tmp/mpY7aGaF
  0  13772         exec_common:exec-success   more /tmp/mpY7aGaF
^C

[edit] What to check

  • Frequency of process creation
    Process creation costs CPU. Frequent process creation (more than 100 per second) can be a performance issue.
  • Process arguments
    Checking the arguments to processes can be a great source for troubleshooting

[edit] Application CPU Sampling

While DTrace is used mostly for tracing, there is plenty of value to be found by using DTrace for sampling. The following samples what an application is doing when it is on-CPU, by aggregating its user-level stack trace.

[edit] How

The following samples the stack trace of processes called top at 1001 Hertz. 1001 Hertz is used so that each sample is roughly equal to 1 millisecond, and to reduce the potential problem of synching with a thread that may fire every second.

# dtrace -n 'profile-1001 /execname == "top"/ { @[ustack()] = count(); }'
  • For C++ applications, save the output and translate using c++filt.
  • For Java applications, use jstack() instead of ustack().

[edit] Examples

dtrace: description 'profile-1001 ' matched 1 probe
^C
[...]
              libc.so.1`__open+0x7
              libc.so.1`open+0x97
              top`getptable+0xe5
              top`get_process_info+0x14
              top`main+0x695
              top`_start+0x80
               36

              libc.so.1`getdents64+0x7
              libc.so.1`readdir+0x20
              top`getptable+0x1f7
              top`get_process_info+0x14
              top`main+0x695
              top`_start+0x80
               64

              libc.so.1`_read+0x7
              top`getptable+0x101
              top`get_process_info+0x14
              top`main+0x695
              top`_start+0x80
              287

The above output shows stack traces along with a count of times seen while DTrace was sampling.
The bottom stack was seen 287 times, and the next was seen 64 times. By reading through both stacks carefully, we can see that both were in the top function getptable() - which shows in terms of the top code where CPU time was spent.

[edit] What to Check

  • Counts of the most frequent stack traces
    The accuracy of sampling may be sufficient to identify code bottlenecks, which will be seen as either one stack with the largest count, or several stacks which have a common function name and which add to a large count.

[edit] Caveats

  • Sampling may miss fleeting events
  • Application latency is often caused by time spent off the CPU (due to I/O requests or mutex lock contention), not on the CPU, which won't be identified by on-CPU sampling

Both issues can be solved with additional DTrace commands to trace events.

[edit] Kernel CPU Sampling

While DTrace is used mostly for tracing, there is plenty of value to be found by using DTrace for sampling. The following samples what the kernel is doing when it is on-CPU, by aggregating its kernel-level stack trace.

[edit] How

This one-liner samples the kernel stack trace at 1001 Hertz.

# dtrace -n 'profile-1001 /arg0/ { @[stack()] = count(); }'

[edit] Examples

dtrace: description 'profile-1001 ' matched 1 probe
^C
[...]
              unix`bcopy+0xa
              nge`nge_m_tx+0x58
              dls`dls_tx+0x1d
              dld`dld_tx_single+0x2a
              dld`str_mdata_fastpath_put+0x7f
              ip`tcp_send_data+0x889
              ip`tcp_send+0xa7b
              ip`tcp_wput_data+0x77f
              ip`tcp_rput_data+0x2bb0
              ip`squeue_enter_chain+0x11d
              ip`ip_input+0x985
              dls`i_dls_link_rx+0x2af
              mac`mac_rx+0x71
              nge`nge_receive+0x47
              nge`nge_intr_handle+0xb0
              nge`nge_chip_intr+0x6f
              unix`av_dispatch_autovect+0x78
              unix`dispatch_hardint+0x2f
              unix`switch_sp_and_call+0x13
              86

              unix`kcopy+0x2c
              genunix`uiomove+0x8e
              genunix`mcopyinuio+0x132
              sockfs`sostream_direct+0xd9
              sockfs`sotpi_sendmsg+0x3a7
              sockfs`sosendmsg+0x1e
              iscsi`iscsi_net_tx+0x93
              iscsi`iscsi_tx_pdu+0x248
              iscsi`iscsi_tx_data+0x153
              iscsi`iscsi_tx_r2t+0x64
              iscsi`iscsi_tx_cmd+0x50
              iscsi`iscsi_cmd_state_pending+0x14d
              iscsi`iscsi_cmd_state_machine+0x83
              iscsi`iscsi_tx_thread+0x86
              iscsi`iscsi_threads_entry+0x15
              genunix`taskq_thread+0x1a7
              unix`thread_start+0x8
              98
 
              unix`mach_cpu_idle+0x6
              unix`cpu_idle+0xc8
              unix`idle+0x10e
              unix`thread_start+0x8
              4321

The above output shows kernel stack traces with a count of times seen while DTrace was sampling.
The most frequest stack trace was caused the cpu_idle() function (idle CPUs) at 4321 samples, followed by iscsi code with 98 samples, and then the TCP/IP stack with 86 samples.

[edit] What to Check

  • Most frequent stack trace
    The stack traces contain raw kernel function names, which can be deciphered with some research. This will provide a rough idea of where the kernel is spending CPU time.

[edit] Caveats

  • Sampling may miss fleeting events

This can be solved using additional DTrace commands to trace rather than sample.

[edit] Physical I/O bytes by process

The following measures requested I/O bytes by using the DTrace io provider. The io provider traces,

  • I/O to physical disks
  • I/O to disk volumes
  • I/O to NFS mounts

These are I/O events from the kernel drivers, and can be described as physical I/O (rather than logical I/O seen at the application level). Additional DTrace syntax can be used to print or filter I/O types.

[edit] How

Trace requested I/O bytes by process using this one liner,

# dtrace -n 'io:::start { @[pid, execname] = sum(args[0]->b_bcount); }'

[edit] Examples

The following output traced disk I/O from both a tar and a find command,

dtrace: description 'io:::start ' matched 6 probes
^C

        0  sched                                                       2372608
      971  find                                                        3014656
      970  tar                                                         4530176

The output columns are PID, process name, and requested I/O bytes while DTrace was tracing.
The tar command requested 4.53 Mbytes of I/O, and the find command requested 3.01 Mbytes. sched represents the kernel and its drivers, which would include file system events such as asynchronous data writes to disk.

[edit] What to Check

  • Top byte counts for an interval
    While the performance impact is better measured in units of time consumed, the rate of bytes transferred may be better understood by sysadmins and developers.
    Check who the top processes are which caused I/O, and what their I/O rates are. Any they reasonable considering what work the application and system is performing?
  • An unexpected process
    Regular tools like iostat don't tell you who is causing disk I/O. You may find a process chewing disks that shouldn't be running at all, such as someone running a backup running during business hours.

[edit] Physical I/O byte sizes

The following measures requested I/O bytes using the io provider, which measures the I/O events described in the previous section. Here we use the DTrace quantize aggregating function to print a distribution plot.

[edit] How

# dtrace -n 'io:::start { @[execname] = quantize(args[0]->b_bcount); }'

[edit] Examples

dtrace: description 'io:::start ' matched 6 probes
^C

 sched                                             
          value  ------------- Distribution ------------- count    
            256 |                                         0        
            512 |@                                        14       
           1024 |@@@@                                     42       
           2048 |@@@@@@                                   61       
           4096 |@@@@@@                                   57       
           8192 |@@@@                                     39       
          16384 |@@                                       24       
          32768 |                                         5        
          65536 |@@@@@@@@@@@@@@@                          150      
         131072 |@@                                       17       
         262144 |                                         0        

 tar                                               
          value  ------------- Distribution ------------- count    
           1024 |                                         0        
           2048 |@                                        13       
           4096 |@@                                       18       
           8192 |@@@                                      30       
          16384 |@@@@@@@@                                 87       
          32768 |@@@                                      31       
          65536 |@@@@@@@@@@@@@@@@@@@@@@@@                 277      
         131072 |@                                        8        
         262144 |                                         0        

 dd                                                
          value  ------------- Distribution ------------- count    
          65536 |                                         0        
         131072 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 395      
         262144 |                                         0    

The above output shows the process name and a distribution plot with the requested I/O transaction size as the "value" and the number of occurances as the "count".
The output shows a dd command requesting 128 Kbyte physical reads, and a tar command requesting a variety of sized reads - mostly in the 64 Kbyte to 128 Kbyte distribution bucket. There was also some activity from sched, the kernel, which can be explained in further detail using additional DTrace commands.

[edit] What to Check

  • Most frequent size of I/O
    Physical I/O events have a minimum cost due to various driver and device overheads, and a variable cost due to the transaction size. The best performance is usually found by choosing the largest I/O size. If the distributions show that an application is accessing the disks using many small transactions, it should be worth checking if the application can be tuned to use a larger I/O size.
  • Scattered I/O sizes
    This could mean random I/O, which can degrade performance on physical disks. Additional DTrace commands can measure the randomness of disk activity.
Solaris Internals
Personal tools
The Books
The Ads