Performance Improvement and Script Optimization
The Tcl/Tk language support in HyperMesh allows you to perform many complex operations by developing Tcl based procedures. While this flexibility provides the means to develop a wide range of solutions, there are some performance issues associated with graphics operations when interacting with HyperMesh. These issues arise due to the time required to perform actions including displaying messages, changing of the mouse cursor, and the pre-highlighting of entities during mark operations.
*evaltclstring string 0
*evaltclscript proc_name 0
*retainmarkselections state
*entityhighlighting state
hm_commandfilestate state
hm_blockmessages state
hwbrowsermanager view flush state
These last five should be reset when leaving a Tcl script as these can effect the user interaction with HyperMesh.
Tcl scripts should be written in a way that aids efficient execution. Based on research related to Tcl/Tk perfomance, a test was written comparing different approaches.
The times listed below are based on using the Tcl time command using 10000 iterations, on a 266mhz Pentium based computer.
Variable assignments outside of the current scope
uplevel w/level: | 66 microseconds per iteration |
uplevel: | 55 microseconds per iteration |
upvar: | 55 microseconds per iteration |
global: | 60 microseconds per iteration |
global namespace: | 50 microseconds per iteration |
local: | 39 microseconds per iteration |
Variable addition and subtraction
expr: | 55 microseconds per iteration |
incr: | 11 microseconds per iteration |
difference: | 5.00x |
Braced expression calls
w/o braces: | 143 microseconds per iteration |
w/ braces | 55 microseconds per iteration |
difference: | 2.60x |
Returning from a procedure
return: | 39 microseconds per iteration |
set | 5 microseconds per iteration |
difference: | 7.80x |
List Parsing
for/lindex: | 159 microseconds per iteration |
while/lindex: | 115 microseconds per iteration |
foreach: | 66 microseconds per iteration |
Variable initialization
inline: | 110000 microseconds |
proc based: | 50000 microseconds |
Arrays vs. lists
For large list searches, it may be more efficient to use arrays. List searches are sequential searches and may not be very efficient for large lists. Instead of adding items to a list, set the indices of an array to the item name.
set a "1 2 3 4 5 6 7 8 9 0";
if {[lsearch $a 9] != -1} {
…command body…
}
set a(1) 1;
set a(2) 2;
…
set a(9) 9;
set a(0) 0;
if {[info exist a(9)] == 1} {
…command body…
}
For sorted lists, it may be more efficient to use the -sorted option to lsearch, along with -ascii, -decreasing, -dictionary, -increasing, -integer, and/or -real, depending on the list type.
Example
set vals {10 20 30 40 50 60 70 80 90};
proc sum {} {
global vals;
set sum 0;
for { set i 0 } { $i < [ llength $vals ] } { incr i } {
set curVal [ lindex $vals $i ];
set sum [ expr $sum + $curVal ];
}
return $sum;
}
proc fasterSum {} {
set sum 0;
foreach val $::vals {
incr sum $val;
}
set sum;
}
sum: 829
fasterSum: 83
difference: 9.99x