Profiling with NSF ================== NSF offers the following built-in options for profiling, which apply to methods (all instance and per class methods of XOTcl, NX, ...) and to nsf::procs. Preliminaries: -------------- - make sure nsf is compiled with "--enable-profile" - if you are not sure, check the file config.log in the source directory, where nsf was compiled. You find a line looking like $ ./configure .... near to the top of the file. If the configure line does not contain "--enable-profile", run the configure command with "--enable-profile" added, then make clean; make; sudo make install - to check, if the version you are using is complied properly check the global Tcl array ::nsf::config, e.g. with $ nxsh % parray ::nsf::config Profiling: ---------- From nsf profiling supports 1) detailed profiling about a full run, or 2) selective profiling Dtrace: ------- Alternatively dtrace [2] can be used to obtain profiling information from nsf (and Tcl as well).... but this depends on the operating system support (Solaris heritage). ========================================================================================================= # # Sample script and helper procs to show, how profiling/tracing works # in NSF with the not widely advertised profiling support based on # # ::nsf::__profile # # Gustaf Neumann # package require nx # # Helper function for in-memory profiling # proc mini-profile {cmd} { if {[nsf::pkgconfig get profile]} { try { nsf::__profile_clear nsf::__profile_trace -enable true uplevel $cmd } on error {errorMsg} { error $errorMsg } finally { nsf::__profile_trace -enable false } # # The collected profile data contains: # # totalMicroSec: measured time since profile start # # overallTime: aggregated time from traces # # objectData list of lists, where every element contains # {object class method} aggregated_time number_of_calls # # methodData list of lists, where every element contains # {method class} {callerMethod callerClass} aggregated_time number_of_calls # # procData list of lists, where every element contains # {proc aggregated_time number_of_calls} # # trace new-line separated entries containing call, exit, and time # lassign [::nsf::__profile_get] totalMicroSec overallTime objectData methodData procData trace # Output profile data... or do something else with it... # puts "Profile Data:\n===================" foreach v {totalMicroSec overallTime objectData methodData procData trace} { set break [expr {$v eq "trace" ? "\n" : "\t"} ] puts "$v$break[set $v]" } puts "===================" } else { puts stderr "NSF is not compiled with profiling support" uplevel $cmd } } nsf::proc bar {x:integer} { return $x } nx::Class create C { # # Naive version of factorial # :public method fact {n} { if {$n < 2} { return 1 } else { return [expr {$n * [:fact [expr {$n-1}]]}] } } :public method foo {n} { bar 1 return [:fact $n] } } C create c1 ####################################################### # Plain run ####################################################### puts "factorial of 6 = [c1 foo 6]" ####################################################### # Run the same command with profiling, # collect the profile data in memory ####################################################### mini-profile {c1 foo 6} puts "\nTrace profiling information to output" puts "===================" nsf::__profile_trace -enable true -dontsave true -verbose 1 c1 foo 6 nsf::__profile_trace -enable false puts "===================" ####################################################### # Define custom logger to handle e.g. trace output ####################################################### proc ::nsf::log {level msg} { puts stderr "MY-logger: $level: $msg" } puts "\nTrace profiling information to output (with extra logger)" puts "===================" nsf::__profile_trace -enable true -dontsave true -verbose 1 c1 foo 6 nsf::__profile_trace -enable false puts "===================" ####################################################### # Selective profiling and tracing # Define custom debug commands ####################################################### proc ::nsf::debug::call {level objectInfo methodInfo arglist} { nsf::log Debug "MY call($level) - $objectInfo $methodInfo $arglist" } proc ::nsf::debug::exit {level objectInfo methodInfo result usec} { nsf::log Debug "MY exit($level) - $objectInfo $methodInfo $usec usec -> $result" } # # Select methods to be traced (could be also done with the # flag "-debug" in the source # ::nsf::method::property C fact debug true ::nsf::method::property C ::bar debug true puts "\nSelective profiling (with extra logger, debug, and custom debug messages)" puts "===================" c1 foo 6 puts "==================="