egghelp.org community Forum Index
[ egghelp.org home | forum home ]
egghelp.org community
Discussion of eggdrop bots, shell accounts and tcl scripts.
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Tcl performance, script optimization

 
Post new topic   Reply to topic    egghelp.org community Forum Index -> Tcl FAQ
View previous topic :: View next topic  
Author Message
demond
Revered One


Joined: 12 Jun 2004
Posts: 3073
Location: San Francisco, CA

PostPosted: Fri Jul 29, 2005 11:16 pm    Post subject: Tcl performance, script optimization Reply with quote

a fast in-place list update (courtesy of DKF):
Code:

proc K {x y} {set x}
set theList [lreplace [K $theList [set theList {}]] 7 42]


what happens here? when you use [lreplace] the usual way, entire list gets duplicated (not elements though), manipulated and then copied back to the list variable, then the duplicate is destroyed

when you use the above method with so-called K combinator (an important notion in functional programming), list manipulation is done in-place, meaning duplication is eliminated (the K combinator in this case is functioning as get-and-unset proc)

on my machine, it's almost 50 times faster! operating on a big list of course:
Code:

[demond@whitepine demond]$ tclsh8.4
% proc K {a b} {set a}
% for {set i 0} {$i<100000} {incr i} {
   lappend a $i; lappend b $i
}
% time {set a [lreplace $a 40 80]}
24879 microseconds per iteration
% time {set b [lreplace [K $b [set b {}]] 40 80]}
537 microseconds per iteration
Back to top
View user's profile Send private message Visit poster's website
demond
Revered One


Joined: 12 Jun 2004
Posts: 3073
Location: San Francisco, CA

PostPosted: Wed Aug 10, 2005 4:09 am    Post subject: Reply with quote

more performance tips:

Data types in Tcl 8.0 and greater are represented in Tcl_Obj internal object type; don't change the type of that representation if you can, for example use:
Code:

if {[llength $alist] == 0}

and not:
Code:

if {[string compare {} $alist] == 0}

(in the latter expression the internal representation of the argument list $alist is changed to string, which hurts the performance)

this might not be much relevant to eggdrop's bind triggers (which normally wouldn't be a performance bottleneck), but still:
Code:

foreach {foo bar moo} [split $args] {break}

is faster and more compact than:
Code:

set foo [lindex [split $args] 0]
set bar [lindex [split $args] 1]
set moo [lindex [split $args] 2]
Back to top
View user's profile Send private message Visit poster's website
sKy
Op


Joined: 14 Apr 2005
Posts: 194
Location: Germany

PostPosted: Wed Aug 10, 2005 12:51 pm    Post subject: Reply with quote

regular
Code:
set result [expr 1000 + 1000]


Code:
set result [expr {1000 + 1000}]
set result [expr { 1000 + 1000 * 1000 } ]

This will be a little big faster.
Back to top
View user's profile Send private message
demond
Revered One


Joined: 12 Jun 2004
Posts: 3073
Location: San Francisco, CA

PostPosted: Fri Aug 12, 2005 2:38 pm    Post subject: Reply with quote

not only [expr] arguments, but all expressions in Tcl should be enclosed in braces; I've the bad habit to write:
Code:

if [command $x $y $z] {
   # stuff
}

don't do that; use:
Code:

if {[command $x $y $z]} {
   # stuff
}
Back to top
View user's profile Send private message Visit poster's website
demond
Revered One


Joined: 12 Jun 2004
Posts: 3073
Location: San Francisco, CA

PostPosted: Fri Aug 12, 2005 3:32 pm    Post subject: Reply with quote

yet more performance hints:

put everything in a proc, inline Tcl code doesn't get that much optimized like byte-compiled proc does:
Code:

% time {for {set i 0} {$i<10000} {incr i} {lappend a $i}} 100
35300 microseconds per iteration
% proc init_me {} {
          global b
          for {set i 0} {$i<10000} {incr i} {lappend b $i}
      }
% time {init_me} 100
21888 microseconds per iteration


don't use inline regexps too much:
Code:

regexp "\[ \t\n\r\]" $str

instead, save it into variable first and then use that variable:
Code:

set ws "\[ \t\n\r\]"
...
regexp $ws $str

the second form allows storing the compiled regexp in the Tcl_Obj representation of $ws and simply executing it on demand, whereas the first form could lead to compiling that regexp again and again (after interpreter's regexp cache has been exhausted)

don't use [catch] too often, it's slow and should be used only when you are pretty certain that it triggers very rarely; for example, this lazy line of code is 10 times slower than the [info exists] construct that follows it (provided $a doesn't exist):
Code:

catch {set b $a}
Code:

if {[info exists a]} {set b $a}
Back to top
View user's profile Send private message Visit poster's website
sKy
Op


Joined: 14 Apr 2005
Posts: 194
Location: Germany

PostPosted: Sat Aug 13, 2005 8:45 pm    Post subject: Reply with quote

If you want to use the return code from a command/proc serval times i suggest you to use the set command and not to execute it each time.

Examples (just to show you what i mean):
- slow:
Code:
proc te10 { } {
   putlog "te10: [hand2nick $::owner]"
   putlog "te10: [hand2nick $::owner]"
   putlog "te10: [hand2nick $::owner]"
}
- faster:
Code:
proc te10 { } {
   set ownerhand [hand2nick $::owner]
   putlog "te10: $ownerhand"
   putlog "te10: $ownerhand"
   putlog "te10: $ownerhand"
}

Very second i might add, in my personal opinion a script looks more easy and clear if you use the set command more often then executing all this stuff over and over again.
Back to top
View user's profile Send private message
MrStonedOne
Voice


Joined: 25 Feb 2007
Posts: 8

PostPosted: Tue Feb 10, 2009 7:45 am    Post subject: if and set Reply with quote

im not sure how faster this is... but remember, the set command returns what was just set on something. so
Code:
if {[set nick [hand2nick $::owner]] == "blah"}
putlog "$nick"

is faster then
Code:

if {[hand2nick $::owner] == "blah"}
putlog "[hand2nick $::owner]"


and as you see here... using ::varName is faster for accessing globals then to map it with the global command (unless your gonna be accessing a global alot in one proc. then the command is faster)
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    egghelp.org community Forum Index -> Tcl FAQ All times are GMT - 4 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Forum hosting provided by Reverse.net

Powered by phpBB © 2001, 2005 phpBB Group
subGreen style by ktauber