Version 6 of Ttrace

Updated 2018-06-01 01:23:08 by AMG

See the manual


AMG: Is there really only the briefest mention of [thread::ttrace] on the Tcler's Wiki? Does no one use this command? It seems like it would be a great way to accelerate initializing many worker threads. Does it live up to that promise? Or does it have some overhead that makes it less attractive than simply loading the required packages into each thread's interpreter? Perhaps it's limited in what it supports, e.g. maybe it doesn't recognize TclOO. I see it provides a means to extend its capabilities, and maybe that's good enough. But again, there's no discussion that I can find, so I don't know answers to any of these questions. I'm thinking about trying it out myself to see how it stacks up.


AMG: Okay, a little test.

% package require Ttrace
2.8.2
% ttrace::eval {package require sha256}
1.0.3
% thread::create {package require Ttrace; thread::wait}
Error from thread tid0x6555b70
can't rename "::sha2::SHA224Final-tcl": command doesn't exist
    while executing
"::rename ::sha2::SHA224Final-tcl {::sha2::SHA224Final}"
    ("uplevel" body line 880)
    invoked from within
"uplevel [getscript]"
    (procedure "::ttrace::update" line 10)
    invoked from within
"::ttrace::update"
    (lambda term "{dir} {
    if {[info exists ::env(TCL_THREAD_LIBRARY)] &&
        ..." line 11)
    invoked from within
"::apply {{dir} {
    if {[info exists ::env(TCL_THREAD_LIBRARY)] &&
        [file readable $::env(TCL_THREAD_LIBRARY)/ttrace.tcl]} {
        source $::env(TCL_THREA..."
    ("package ifneeded Ttrace 2.8.2" script)
    invoked from within
"package require Ttrace"

Apparently Ttrace doesn't like the rename-fu employed by sha256.tcl [L1 ]. Maybe [ttrace::addtrace] could be used to teach Ttrace about [rename], but I really don't know.


AMG: Here's another problem with Ttrace. It can't be used to load packages into new threads when the packages have already been loaded into the current interpreter. For this test, I have two packages called list and dict. Only the latter gets loaded into the threads because the former is already loaded into the main interpreter.

% package require Ttrace
2.8.2
% package require list
0.1
% ttrace::eval {package require list; package require dict}
0.1
% set t [thread::create {package require Ttrace; thread::wait}]
tid0x5dd8b70
% thread::send $t {info commands dict::*}
::dict::updatePath ::dict::default ::dict::mergePath ::dict::unpack ::dict::null ::dict::pack
% thread::send $t {info commands list::*}

To work around this issue, run [ttrace::eval] inside a new, temporary interpreter:

% package require Thread
2.8.2
% package require list
0.1
% set slave [interp create]
interp0
% $slave eval [list set auto_path $auto_path]
...
% $slave eval {
package require Ttrace
ttrace::eval {package require list; package require dict}
}
0.1
% interp delete $slave
% set t [thread::create {package require Ttrace; thread::wait}]
tid0x6807b70
% thread::send $t {info commands dict::*}
::dict::updatePath ::dict::default ::dict::mergePath ::dict::unpack ::dict::null ::dict::pack
% thread::send $t {info commands list::*}
::list::scavenge ::list::disjoint ::list::intersect ::list::sub ::list::conj ::list::remove

It's never necessary to load the Ttrace package into the main interpreter, only into the temporary interpreter and the threads.


AMG: Ttrace doesn't support variables.

% package require Ttrace
2.8.2
% ttrace::eval {set x 999}
999
% set t [thread::create]
tid0x50b9b70
% thread::send $t {package require Ttrace; set x}
can't read "x": no such variable
% set x
999

That last line is a little reminder that everything done inside [ttrace::eval] is done in the current interpreter and namespace, possibly also procedure frame, hence the issue with loading a package that's already loaded.

Well, it turns out Ttrace does support variables a tiny bit. When created with [variable], it knows they should exist, but it doesn't keep track of their initial value, should one be supplied.

% package require Ttrace
2.8.2
% ttrace::eval {namespace eval foo {variable x 999}}
999
% set t [thread::create]
tid0x50b9b70
% thread::send $t {package require Ttrace}
% thread::send $t {info vars ::foo::*}
::foo::x
% thread::send $t {set ::foo::x}
can't read "::foo::x": no such variable

Replacing [variable] with [set] in the above code causes the call to [info vars] to return empty, suggesting that Ttrace doesn't even create the empty namespace variable slot when [set] is used.