From: Andreas Leitgeb on 12 Sep 2009 04:21 Andreas Leitgeb <avl(a)gamma.logic.tuwien.ac.at> wrote: > Uwe Klein <uwe_klein_habertwedt(a)t-online.de> wrote: >>>>>>set newpath [eval [linsert $components 0 file join]] >>>> you can have it faster even: >>>> set newpath [if true [linsert $components 0 file join]]] >>> As I understand it, both invocations cause an evaluation of the same >>> body. So, how come that the latter is faster? >> [eval] is supposed to shimmer to string to list tokens >> while [if] takes the list without further ado. >> at least that is the explanation that was given some years ago. > > Also some years ago there was a statement, that eval recognizes list > Tcl_Obj's (internally) and avoids the string/script detour then. I did an experiment now: proc f1 {l} {eval [linsert $l 0 list]} proc f2 {l} {if 1 [linsert $l 0 list]} set l [lrepeat 1000 x]; llength $l time {f1 $l} 10000;# 116.3 µs time {f2 $l} 10000;# 1146.115 µs So, "if" in this case is ten times slower! PS: the timings were taken on a netbook with atom processor, so on normal PC's the timings are (probably proportionally) much smaller.
From: Erik Leunissen on 12 Sep 2009 08:40 Andreas Leitgeb wrote: > ... > proc f1 {l} {eval [linsert $l 0 list]} > proc f2 {l} {if 1 [linsert $l 0 list]} > set l [lrepeat 1000 x]; llength $l > time {f1 $l} 10000;# 116.3 µs > time {f2 $l} 10000;# 1146.115 µs > > So, "if" in this case is ten times slower! > > PS: the timings were taken on a netbook with atom processor, so > on normal PC's the timings are (probably proportionally) much > smaller. > Yes, but surprisingly, the relative timings are also different. Yours differ by a factor 10 (roughly), mine by a factor of 3. Maybe we are using different Tcl versions. % time {f1 $l} 10000 15.7694 microseconds per iteration % time {f2 $l} 10000 49.0552 microseconds per iteration % parray tcl_platform tcl_platform(byteOrder) = littleEndian tcl_platform(machine) = x86_64 tcl_platform(os) = Linux tcl_platform(osVersion) = 2.6.25.20-0.5-default tcl_platform(platform) = unix tcl_platform(pointerSize) = 8 tcl_platform(user) = erik tcl_platform(wordSize) = 8 % set tcl_version 8.5 Erik. -- leunissen@ nl | Merge the left part of these two lines into one, e. hccnet. | respecting a character's position in a line.
From: Arndt Roger Schneider on 12 Sep 2009 13:25 Uwe Klein schrieb: > Jonathan Bromley wrote: > >> On 11 Sep 2009 10:09:48 GMT, Andreas Leitgeb wrote: >> >> >>> I'd most suggest trying to get unstuck and upgrade to 8.5 >> >> >> >> When Tcl is embedded in a commercial tool, I don't have >> that luxury :-( >> >> >>> treat the arguments to eval such, that it will be safe and >>> not all that slow: >>> >>> set newpath [eval [linsert $components 0 file join]] >> >> >> >> ah, yes, that's nicer. Every Script Is A List. > > > you can have it faster even: > > set newpath [if true [linsert $components 0 file join]]] > > uwe Very nice indeed! Tcl 8.4 PPC: set komponents [list a b c] % time {::eval [linsert $komponents 0 file join]} 173868 microseconds per iteration % time {::eval [linsert $komponents 0 file join]} 60 microseconds per iteration % time {::eval [concat [list file join] $komponents]} 102590 microseconds per iteration % time {::eval [concat [list file join] $komponents]} 69 microseconds per iteration % ::eval [concat [list file join] $komponents] a/b/c % time { if 1 [linsert $komponents 0 file join]} 58558 microseconds per iteration % time { if 1 [concat [list file join] $komponents] } 106 microseconds per iteration .... so whatever these time numbers mean. On concat: concat takes two forms one working on strings the other on lists, If the first argument is a list, then the list form is being aplied. It seems to be faster than linsert, too. And is better readable than linsert. -roger
From: Jonathan Bromley on 12 Sep 2009 14:35 On 12 Sep 2009 03:02:22 GMT, Joe English wrote: >> Joe English wrote: >>>What you can say is: "A canonical-form list, when parsed as a script, >>>will be interpreted as a single command whose words are the elements >>>of the list." That's about the only relationship between lists >>>and scripts I can think of... >> >> I'm not sure about "single command": >> >> % set L {puts a ; puts b} >> % llength $L >> => 5 >> % eval $L >> => a >> b > >Ah, but that's not a *canonical-form* list. > > % set L {puts a ; puts b} > % lrange $L 0 end > ==> "puts a {;} puts b" > ............^^^ note quoting oooooh, that's embarrassing. Two fundamental goofs in one thread. Thanks for the kindly correction. How many times have I told people "never create a list except by using the list commands..."? And then I go and say something stupid like that. >That's why the [eval [linsert ...]] idiom is recommended for >callbacks: [linsert] returns a canonical-form list, so >you don't need to worry about quoting Tcl syntax characters. Indeed. -- Jonathan Bromley, Consultant DOULOS - Developing Design Know-how VHDL * Verilog * SystemC * e * Perl * Tcl/Tk * Project Services Doulos Ltd., 22 Market Place, Ringwood, BH24 1AW, UK jonathan.bromley(a)MYCOMPANY.com http://www.MYCOMPANY.com The contents of this message may contain personal views which are not the views of Doulos Ltd., unless specifically stated.
From: Andreas Leitgeb on 12 Sep 2009 17:02
Arndt Roger Schneider <arndt.roger(a)web.de> wrote: > On concat: concat takes two forms one working on > strings the other on lists, If the first argument > is a list, then the list form is being aplied. No, only if *all* the arguments are pure lists, then the result also will be one, otherwise not. e.g: concat [list foo bar] \; > It seems to be faster than linsert, too. > And is better readable than linsert. never trust "time" about microseconds when you don't specify a larger number of iterations (like 1000). |