dtrace(n) 0.5 "TclDTrace extension"

Name

dtrace - TclDTrace extension: Tcl front-end to the DTrace facility

Table Of Contents

Synopsis

Description

DTrace is a system profiling suite created by Sun Microsystems. It allows the user to profile a program without modifying its text, or even without the need to distract it if it is running. It consists of a set of library hooks called providers, a set of tools, a C API (libdtrace) and its own specially crafted scripting language called D.

TclDTrace is a Tcl binding to libdtrace. It allows users to run D scripts and process their results directly from Tcl. Together with DTrace providers already present in Tcl, it forms an efficient and convenient tool for performance analysis and has the potential to increase the productivity of Tcl developers.

Commands

All TclDTrace commands are in the dtrace namespace.

dtrace::open ?-option value ...? ?instrument?

Returns handle. Opens DTrace. If everything went OK, then handle gets returned. If instrument is 0, then no instrumentation will be possible. This can be useful to just check if a script compiles. Initial configuration options may be passed, see the dtrace::configure call below for the options.

Side note: the name open is derived from the fact that it internally opens /dev/dtrace/ devices.

dtrace::configure handle

Closes DTrace. Tidies up. If you forget to do it, it will be fired automatically on Tcl exit. Calling this explicitly when your program is running may come handy if you want to release resources - this is the only way to free claimed memory.

dtrace::configure handle
dtrace::configure handle -option
dtrace::configure handle -option value ?-option value ...?

If no options are supplied, the command returns a list containing alternating option names and values. If -option is supplied but no value then the command returns the current value of the given option. If one or more pairs of -option and value are supplied, the command sets each of the named -options to the corresponding value; in this case the return value is an empty string.

For binary options you can use the values 1 and 0. For complete options list consider LibDTrace Options - note that you can use every option of the underlaying libdtrace api, just prepend it with a -.

List of basic options (these get returned in the alternating list by the first type of invocation):

-flowindent 1/0

Makes libdtrace handle flow indenting.

-quiet 1/0

Sets quiet mode.

-bufsize integer

Sets the buffer size.

-libdir string

Set path for DTrace libraries.

-foldpdesc 1/0

Whether probe descriptions should be folded into a string (on 1), or given as an alternating list (on 0). See Callbacks. This is TclDTrace specific and defaults to 1.

-arch string

SPECIFIC TO MAC OS X: The target architecture, possible values i386/x86_64/ppc/ppc64. This should be given during initial configuration (see dtrace::open).

libdtrace options may also be changed from within the scripts using a #pragma directive.

Lear more: Solaris Dynamic Tracing Guide

dtrace::grab handle pid

Grabs the process identified by pid. If it's a first call to dtrace::grab, then the $target macro will be set to pid. You should run dtrace::go quickly, as it's the command to continue the grabbed processes.

dtrace::launch handle cmd

This creates a grabbed process by executing cmd and grabbing it immediately. Unlike a call to Tcl's exec and then dtrace::grab, this does not create race conditions. Like in dtrace::grab, process is continued on dtrace::go.

dtrace::compile handle program ?argument0 argument1 ...?

Compiles D program, which should be in the same format as a file passed to dtrace(1) -s. You can pass additional string arguments to the program. Returns a handle compiled_program if successful.

dtrace::exec compiled_program

Executes the compiled_program (enables instrumentation points). This might be called multiple times, all the programs will get run (i.e. generate data for processing) after dtrace::go. Returns an alternating name/value list of program info:

aggregates int

the number of aggregates associated with this program

recgens int

the number of record generating probes associated with this program

matches int

the number of probes matched by this program

speculations int

the number of speculations specified by this program

dtrace::info compiled_program

Returns an alternating name/value list of program info for the compiled_program (this is the same as previous call, but it doesn't enable the instrumentation - can be used for handles with instrument set to 0):

aggregates int

the number of aggregates associated with this program

recgens int

the number of record generating probes associated with this

matches int

the number of probes matched by this program

speculations int

the number of speculations specified by this program

dtrace::go handle ?callback {proc ?arg?} ...?

Enables tracing. This is more or less equal to actually running the executed programs - without it you will not get any data from them. Furthermore this command continues the grabbed processes.

It also registers callbacks. For each callback you need to specify a list containing the callback proc name and possible additional argument. Learn more about callbacks at Callbacks. Possible callbacks names are:

  • probe_desc

  • probe_output

  • drop

  • error

  • proc

dtrace::stop handle

Stops things ticking.

dtrace::process handle ?sleep?

If sleep is set to 1 sleeps a while. Wakes up if something interesting happens. Note that eventually it will not be necessary to use this kind of sleeping - event loop will do. But, at the moment, you need to manually schedule dtrace::process frequently enough to avoid drops (buffer holds around 60K records), or even DTrace aborting (after 30secs without a call to dtrace::process). This should change in future versions.

This command triggers processing data accumulated in the buffer. For each record a relevant Callbacks is called.

dtrace::aggregations handle

Returns a list containing alternating tuple - value pairs. Tuples are what is found in script between [ and ]. In this list, each tuple is represented by a simple list, whose members are the tuple members, divided by , in D code. Values are simple numerics. dtrace::aggregations output can (and should) be interpreted as a Tcl dict.

dtrace::list compiled_program list_callback handle

For each of the probes matched by the compiled_program, runs the list_callback.

Callbacks

list_callback probe arg

This returns a probe description. If -foldpdesc is set to 1, it is a single string with format [[[provider:] module:] function:] name [[predicate] action]. If -foldpdesc is set to 0, this is an alternating list containing:

id int

the numerical probe id

provider string

the provider

module string

the module

function string

the function

name string

the name

probe_desc probe cpu id arg

This is called for each firing probe. Meaning of the arguments:

probe

the probe description string (see list_callback)

cpu

on which cpu did the probe fire

id

the probe id number

arg

extra argument, empty string if none

probe_output probe cpu id arg type data

This is called for each probe that produced some output. That may be just a trace, printfed string or a stack. At present the output is returned directly as the string given by libdtrace and needs to be parsed by the user. Meaning of the arguments:

probe

the probe description string (see list_callback)

cpu

on which cpu did the probe fire

id

the probe id number

arg

extra argument, empty string if none

type

the output type (see LibDTrace Buffered Output), without the DTRACEACT_ prefix.

data

the actual output data

Some of the most interesting output types are:

USTACK

result of ustack()

JSTACK

result of jstack()

STACK

result of stack()

PRINTF

result of printf()

drop cpu kind count message arg

Meaning of the arguments:

cpu

on which cpu did the drop occur

kind

what kind of drop it is (see below)

messge

message preconstructed for you by libdtrace

arg

extra argument, empty string if none

Kind is a string meaning:

AGGREGATION

drop to aggregation buffer

DYNAMIC

dynamic drop

DYNRINSE

dyn drop due to rinsing

DYNDIRTY

dyn drop due to dirty

SPEC

speculative drop

SPECBUSY

spec drop due to busy

SPECUNAVAIL

spec drop due to unavail

STKSTROVERFLOW

stack string tab overflow

DBLERROR

error in ERROR probe

error probe cpu message arg

Meaning of the arguments:

probe

the probe description string (see list_callback)

cpu

on which cpu did the probe fire

message

message preconstructed for you by libdtrace

arg

extra argument, empty string if none

proc pid message arg

Meaning of the arguments:

pid

pid of the process the message is about

messge

message preconstructed for you by libdtrace

arg

extra argument, empty string if none

Examples

Basic Sample Program

package require Tcl 8.5
package require dtrace
# Display instructions
puts {Please input probes in the standard one-liner format:}
puts {[[[provider:] module:] function:] name [[predicate] action]}
puts {Empty probe (just enter) ends the input,}
# Get sources
set probes_sources [list]
set probes_count 1
puts "probe $probes_count:"
gets stdin probe_line
while {$probe_line != ""} {
        set probes_sources [linsert $probes_sources end $probe_line]
        set probes_count [expr {$probes_count + 1}]
        puts "probe $probes_count:"
        gets stdin probe_line
}
set probes_count [expr {$probes_count - 1}]
# Get them compiled and executed
set dhandle [dtrace open -foldpdesc 1]
set OK_count 0
set i 1
set compiled_probes [list]
foreach probe_line $probes_sources {
        if { [ catch {
                puts -nonewline "Processing probe $i: $probe_line "
                set i [expr {$i + 1}]
                puts -nonewline .
                set compiled [dtrace compile $dhandle $probe_line]
                puts -nonewline .
                set running [dtrace exec $compiled]
                puts -nonewline .
                set OK_count [expr {$OK_count + 1}]
                puts -nonewline " OK"
        } ] } { puts -nonewline "FAILED"}
        puts {}
}
if {$OK_count == 0} {
        puts "No probes run - exiting."
        dtrace close $dhandle
        exit
}
# Simple to show the output
puts "CPU\tProbe"
proc callback {probe cpu id args} {
        puts "$cpu\t$probe"
}
# Go go go!
dtrace go $dhandle probe_desc {callback {}}
set counter 10
while {$counter} {
        dtrace process $dhandle 1
        set counter [expr {$counter - 1}]
}
dtrace stop $dhandle
dtrace close $dhandle

Network DTrace Server

One of the good features of Tcl is really easy networking. So here you go: an example of how easy it is to create a telnet-operated DTrace server for multiple clients.

Usage: Run the script with DTrace privileges. Then connect to the port 1986 with something telnet-compatible. Now you can enter your script. Enter a line containing just GO to finish and enable tracing. Disconnect (close the application) to finish - the server cleans up by itself.

package require Tcl 8.5
package require dtrace
proc accept {sock addr port} {
    global handles scripts
    set handles($sock) [::dtrace::open -foldpdesc 1]
    set scripts($sock) ""
    fconfigure $sock -buffering line
    fileevent $sock readable [list receive $sock $addr $port]
    puts "Client connected from $addr:$port"
}
proc receive {sock addr port} {
    global handles scripts
    if {[eof $sock] || [catch {gets $sock line}]} {
        close $sock
        ::dtrace::close $handles($sock)
        unset handles($sock) scripts($sock)
        puts "Client $addr:$port disconnected"
    } else {
        if {[string equal $line "GO"]} {
            ::dtrace::exec [::dtrace::compile $handles($sock) $scripts($sock)]
            ::dtrace::go $handles($sock) probe_desc [list callback $sock]
            puts $sock "CPU\tid\tprobe"
            dtraceLoop $sock
            puts "Tracing for $addr:$port started"
        } else {
            set scripts($sock) "$scripts($sock)\n$line"
        }
    }
}
proc callback {probe cpu id sock} {
    puts $sock "$cpu\t$id\t$probe"
}
proc dtraceLoop {sock} {
    global handles
    catch {::dtrace::process $handles($sock)}
    after 300 dtraceLoop $sock
}
socket -server accept 1986
vwait forever

See Also

dtrace(1)

Keywords

dtrace