Troubleshooting Here are a selection of issues which should be easy to resolve:
|
Tips and Tricks A selection of random tips:
|
Improving Performance Ticol is a pure interpreted script language. It does not perform any byte-code compilation or dynamic optimisation, so performance will be slower than other Tcl variants such as ActiveState. However, since Ticol was designed for day-to-day administrative script work this should not present any serious problems If performance is an issue then it is recommended to use another such as ActiveState Tcl The Ticol Macro PreProcessor (MPP) is able to statically optimise some aspects of
the script source code but the result will still be interpreted Loop-processing constructs will not be as efficient as a compiled language such as C#. however many of the more complex list-processing or string-splitting operations are quite efficient. Ticol offers a wide range of commands and some plugin libraries which are "closer to C++" and therefore fast and efficient You should avoid single-character loop-processing within Tcl, particularly for loops which require complex branched if statements. Preferably call a dedicated, external DLL function and use Ticol as the 'glue' to hold
together more efficient components. A simple plugin The following commands are offered to enhance performance:
Move proc definition, list evaluation and creation outside of loops if possible. Pre-evaluate lists into variables. Make full use of the macro-PreProcessor to optimise constants during the preprocessing phase Use [concat] when concatenating large strings. Avoid chaining the set operator as the accumulated string passes through the interpreter POOR: set out $out$ch GOOD: concat out $ch Use [cmp], this compares string segments in memory, instead of extracting and then
comparing the resulting extract in an expression. It can POOR: if { eq [mid $data $i 2] "Hi" } { GOOD: if { cmp data "Hi" $i 2 } { When extracting small sections of a string use [setat] to directly slice the section of a string to a variable, thus avoiding the use of the set call. This sets a variable directly with index values located at a specified position and length. Timing tests show [setat] is around 50% faster than using [mids] together with [set] POOR: set ch [mids $data $i 1] GOOD: setat ch $data $i 1 Character replacement can be performed rapidly using [replacechar] rather than re-assigning the result of [string replace] POOR: set s [readfile ticol.man] GOOD: set s [readfile ticol.man] To concatenate strings, particularly large ones or large numbers of small ones use [append] instead of repeated calls to chained [set] commands. The use of [set] chains creates multiple copies of strings whereas append appends directly to the original variable. Append is faster than [lappend] and [store] is about 5 times faster than [append] but less flexible to use POOR: set a "The
quick" GOOD: set a "The
quick" BEST: store "The
quick" A key to interpreter performance is pre-calculating as much as possible outside of intensive loops and making good use of intrinsic functions instead of synthesising them from other commands String comparison for string prefixes should use the [eqn] and [nen] commands which will safely test equality or inequality for a given length. This would be effective in tight loops when comparing large string prefixes than using a compound of [eq] and [string] POOR:
GOOD: set a "The quick
brown fox" Use [for]. For loops are often far more efficient than while {} loops. [loop] is even more efficient For accurate performance timing, use the 'time' command or run Ticol in "graph" mode with the /G command line argument [let] may be used for multiple, simultaneous assignments Use [array_foreach] to iterate arrays if you need simple behaviour Because it is a generalised expression-handler with significant checking-overheads, [expr] may be far slower than decomposing an expression into dedicated component operations with Tcl Polish 'prefix' syntax. The Macro PreProcessor will optimise the [calc] command and expand into raw Tcl statements. If the MPP is disabled then [calc] will be interpreted equivalent to [expr] Example: set src [expr ($x & $y) % 3] # Expression set src [% [& $x $y] 3] # Decomposed expression (~50% faster) set src [calc ($x & $y) % 3] # Expression is optimised by the MPP Move command calls out of loop arguments and bodies where possible to avoid repeated calls to slower evaluation commands Example: option expression off for {set i 1} {< $i [linkedlist count $handle]} {++ i} { # Slower set c [linkedlist count $handle] # Evaluate once for {set i 1} {< $i $c} {++ i} { # Faster |
Debugging (Using the
Debugger) To run in breakpoint/debugging mode use ticol.exe <scriptname> /debug Or use ticol.exe <scriptname> /bp or, in the code, use [option breakpoint on] When a [halt] or error condition arises the debugger menu will launch Consider the following code... cls option expression off option breakpoint on watch add i halt set i 0 for {} {< $ 10} {++ i} { if {> $i 5} { puts "Break condition met at i==$i" break } halt } newline puts "Exit for with i==$i" puts "* Done *" We can run this using: ticol.exe <scriptname> or ticol.exe <scriptname> /NA to avoid running the autoexec.tcl script On running the debugger will be enabled and will halt at the command after first [halt]
instruction Variable i is enabled for a [watch] statement and is curently out of scope Pressing [R] to run will cause execution to resume and then halt again and break at the first command after the next [halt] statement ... Pressing [R] again will run another iteration of the [for] loop and now, variable i is in scope and traces the value 0 ... Pressing [R] repeatedly will resume and run each iteration of the [for] loop and, in this example, will trace the value of variable i ... Pressing [R] repeatedly will evetually result in the loop exiting when variable i is greater than 5 So far we have used [R] to run to the next [halt] statement. Alternatively, the debugger can single-step with either [T] to trace showing the stack or [N] to simply step to and execute the next instruction. The image below shows two [T] trace steps ... Pressing [N] for next, skips all debugging information other than variable watch (if this is enabled) ... [W] will toggle Watch off or on, unless overridden by the [watch] command. See help watch. The script may programatically abandon debugging by either clearing any [halt] command or issuing an [option breakpoint off] command |
Last updated on 04 March 2021 - This page is designed for 1024 x760 and higher resolution displays