4 proc bench
{title script
} {
5 global benchmarks batchmode
7 set Title
[string range
"$title " 0 20]
9 set failed
[catch {time $script} res
]
11 if {!$batchmode} {puts "$Title - This test can't run on this interpreter"}
12 lappend benchmarks
$title F
15 lappend benchmarks
$title $t
17 set ts
[string range
$ts [expr {[string length
$ts]-10}] end
]
18 if {!$batchmode} {puts "$Title -$ts microseconds per iteration"}
22 ### BUSY LOOP ##################################################################
24 proc whilebusyloop
{} {
26 while {$i < 1850000} {
32 for {set i
0} {$i < 1850000} {incr i
} {}
35 ### FIBONACCI ##################################################################
41 expr {[fibonacci
[expr {$x-1}]] + [fibonacci
[expr {$x-2}]]}
45 ### HEAPSORT ###################################################################
53 proc make_gen_random
{} {
55 set params
[list IM
$IM IA
$IA IC
$IC]
56 set body
[string map
$params {
58 expr {($max * [set last
[expr {($last * IA
+ IC
) % IM
}]]) / IM
}
60 proc gen_random
{max
} $body
63 proc heapsort
{ra_name
} {
67 set ir
[expr {$n - 1}]
70 set rra
[lindex $ra [incr l
-1]]
72 set rra
[lindex $ra $ir]
73 lset ra
$ir [lindex $ra 0]
74 if {[incr ir
-1] == 0} {
80 set j
[expr {(2 * $l) + 1}]
82 set tmp
[lindex $ra $j]
84 if {$tmp < [lindex $ra [expr {$j + 1}]]} {
85 set tmp
[lindex $ra [incr j
]]
98 proc heapsort_main
{} {
103 for {set i
1} {$i <= $n} {incr i
} {
104 lappend data
[gen_random
1.0]
109 ### SIEVE ######################################################################
115 for {set i
2} {$i <= 8192} {incr i
} {
118 for {set i
2} {$i <= 8192} {incr i
} {
119 if {$flags($i) == 1} {
120 # remove all multiples of prime: i
121 for {set k
[expr {$i+$i}]} {$k <= 8192} {incr k
$i} {
131 proc sieve_dict
{num
} {
135 for {set i
2} {$i <= 8192} {incr i
} {
138 for {set i
2} {$i <= 8192} {incr i
} {
139 if {[dict get
$flags $i] == 1} {
140 # remove all multiples of prime: i
141 for {set k
[expr {$i+$i}]} {$k <= 8192} {incr k
$i} {
151 ### ARY ########################################################################
154 for {set i
0} {$i < $n} {incr i
} {
157 set last
[expr {$n - 1}]
158 for {set j
$last} {$j >= 0} {incr j
-1} {
163 ### REPEAT #####################################################################
165 proc repeat
{n body
} {
166 for {set i
0} {$i < $n} {incr i
} {
173 repeat
{1000000} {incr x
}
176 ### UPVAR ######################################################################
178 proc myincr varname
{
185 for {set x
0} {$x < 100000} {myincr x
} {
190 ### NESTED LOOPS ###############################################################
192 proc nestedloops
{} {
197 while {[incr a
-1]} {
199 while {[incr b
-1]} {
201 while {[incr c
-1]} {
203 while {[incr d
-1]} {
205 while {[incr e
-1]} {
207 while {[incr f
-1]} {
217 ### ROTATE #####################################################################
219 proc rotate
{count
} {
221 for {set n
0} {$n < $count} {incr n
} {
222 set v
[expr {$v <<< 1}]
226 ### DYNAMICALLY GENERATED CODE #################################################
229 for {set i
0} {$i < 100000} {incr i
} {
230 set script
"lappend foo $i"
235 proc dyncode_list
{} {
236 for {set i
0} {$i < 100000} {incr i
} {
237 set script
[list lappend foo
$i]
242 ### PI DIGITS ##################################################################
246 set LEN
[expr {10*$N/3}]
249 set a
[string repeat
" 2" $LEN]
254 set i0
[expr {$LEN+1}]
255 set quot0
[expr {2*$LEN+1}]
256 for {set j
0} {$j<$N} {incr j
} {
262 set x
[expr {10*$apos + $q * [incr i
-1]}]
263 lset a
[incr pos
] [expr {$x % [incr quot
-2]}]
264 set q
[expr {$x / $quot}]
266 lset a end
[expr {$q % 10}]
267 set q
[expr {$q / 10}]
269 append result
$predigit $nines
275 append result
[expr {$predigit+1}][string map
{9 0} $nines]
280 #puts $result$predigit
283 ### EXPAND #####################################################################
286 for {set i
0} {$i < 100000} {incr i
} {
287 set a
[list a b c d e f
]
292 ### MINLOOPS ###################################################################
295 for {set i
0} {$i < 100000} {incr i
} {
297 for {set j
0} {$j < 10} {incr j
} {
298 # something of more or less real
304 ### wiki.tcl.tk/8566 ###########################################################
306 # Internal procedure that indexes into the 2-dimensional array t,
307 # which corresponds to the sequence y, looking for the (i,j)th element.
309 proc Index
{ t y i j
} {
310 set indx
[expr { ([llength $y] + 1) * ($i + 1) + ($j + 1) }]
311 return [lindex $t $indx]
314 # Internal procedure that implements Levenshtein to derive the longest
315 # common subsequence of two lists x and y.
317 proc ComputeLCS
{ x y
} {
319 for { set i
-1 } { $i < [llength $y] } { incr i
} {
322 for { set i
0 } { $i < [llength $x] } { incr i
} {
324 for { set j
0 } { $j < [llength $y] } { incr j
} {
325 if { [string equal
[lindex $x $i] [lindex $y $j]] } {
326 set lastT
[Index
$t $y [expr { $i - 1 }] [expr {$j - 1}]]
327 set nextT
[expr {$lastT + 1}]
329 set lastT1
[Index
$t $y $i [expr { $j - 1 }]]
330 set lastT2
[Index
$t $y [expr { $i - 1 }] $j]
331 if { $lastT1 > $lastT2 } {
343 # Internal procedure that traces through the array built by ComputeLCS
344 # and finds a longest common subsequence -- specifically, the one that
345 # is lexicographically first.
347 proc TraceLCS
{ t x y
} {
349 set i
[expr { [llength $x] - 1 }]
350 set j
[expr { [llength $y] - 1 }]
351 set k
[expr { [Index
$t $y $i $j] - 1 }]
352 while { $i >= 0 && $j >= 0 } {
353 set im1
[expr { $i - 1 }]
354 set jm1
[expr { $j - 1 }]
355 if { [Index
$t $y $i $j] == [Index
$t $y $im1 $jm1] + 1
356 && [string equal
[lindex $x $i] [lindex $y $j]] } {
357 lappend trace xy
[list $i $j]
360 } elseif
{ [Index
$t $y $im1 $j] > [Index
$t $y $i $jm1] } {
379 # list::longestCommonSubsequence::compare --
381 # Compare two lists for the longest common subsequence
384 # x, y - Two lists of strings to compare
385 # matched - Callback to execute on matched elements, see below
386 # unmatchedX - Callback to execute on unmatched elements from the
387 # first list, see below.
388 # unmatchedY - Callback to execute on unmatched elements from the
389 # second list, see below.
395 # Whatever the callbacks do.
397 # The 'compare' procedure compares the two lists of strings, x and y.
398 # It finds a longest common subsequence between the two. It then walks
399 # the lists in order and makes the following callbacks:
401 # For an element that is common to both lists, it appends the index in
402 # the first list, the index in the second list, and the string value of
403 # the element as three parameters to the 'matched' callback, and executes
406 # For an element that is in the first list but not the second, it appends
407 # the index in the first list and the string value of the element as two
408 # parameters to the 'unmatchedX' callback and executes the result.
410 # For an element that is in the second list but not the first, it appends
411 # the index in the second list and the string value of the element as two
412 # parameters to the 'unmatchedY' callback and executes the result.
416 unmatchedX unmatchedY
} {
417 set t
[ComputeLCS
$x $y]
418 set trace [TraceLCS
$t $x $y]
419 set i
[llength $trace]
421 set indices
[lindex $trace [incr i
-1]]
422 set type
[lindex $trace [incr i
-1]]
423 switch -exact -- $type {
426 eval lappend c
$indices
427 lappend c
[lindex $x [lindex $indices 0]]
433 lappend c
[lindex $x $indices]
439 lappend c
[lindex $y $indices]
447 proc umx
{ index value
} {
450 append xlines
"< " $value \n
454 proc umy
{ index value
} {
457 append ylines
"> " $value \n
461 proc matched
{ index1 index2 value
} {
466 if { [info exists lastx
] && [info exists lasty
] } {
467 #puts "[expr { $lastx + 1 }],${index1}c[expr {$lasty + 1 }],${index2}"
468 #puts -nonewline $xlines
470 #puts -nonewline $ylines
471 } elseif
{ [info exists lastx
] } {
472 #puts "[expr { $lastx + 1 }],${index1}d${index2}"
473 #puts -nonewline $xlines
474 } elseif
{ [info exists lasty
] } {
475 #puts "${index1}a[expr {$lasty + 1 }],${index2}"
476 #puts -nonewline $ylines
478 catch { unset lastx
}
479 catch { unset xlines
}
480 catch { unset lasty
}
481 catch { unset ylines
}
484 # Really, we should read the first file in like this:
485 # set f0 [open [lindex $argv 0] r]
486 # set x [split [read $f0] \n]
488 # But I'll just provide some sample lines:
490 proc commonsub_test
{} {
492 for { set i
0 } { $i < 20 } { incr i
} {
493 lappend x a r a d e d a b r a x
496 # The second file, too, should be read in like this:
497 # set f1 [open [lindex $argv 1] r]
498 # set y [split [read $f1] \n]
500 # Once again, I'll just do some sample lines.
503 for { set i
0 } { $i < 20 } { incr i
} {
504 lappend y a b r a c a d a b r a
507 compare
$x $y matched umx umy
508 matched
[llength $x] [llength $y] {}
511 ### MANDEL #####################################################################
513 proc mandel
{xres yres infx infy supx supy
} {
514 set incremx
[expr {(0.0+$supx-$infx)/$xres}]
515 set incremy
[expr {(0.0+$supy-$infy)/$yres}]
517 for {set j
0} {$j < $yres} {incr j
} {
518 set cim
[expr {$infy+($incremy*$j)}]
520 for {set i
0} {$i < $xres} {incr i
} {
524 set cre
[expr {$infx+($incremx*$i)}]
525 while {$counter < 255} {
526 set dam
[expr {$zre*$zre-$zim*$zim+$cre}]
527 set zim
[expr {2*$zim*$zre+$cim}]
529 if {$zre*$zre+$zim*$zim > 4} break
537 ### RUN ALL ####################################################################
539 if {[string compare
[lindex $argv 0] "-batch"] == 0} {
543 bench
{[while] busy loop
} {whilebusyloop
}
544 bench
{[for] busy loop
} {forbusyloop
}
545 bench
{mini loops
} {miniloops
}
546 bench
{fibonacci
(25)} {fibonacci
25}
547 bench
{heapsort
} {heapsort_main
}
548 bench
{sieve
} {sieve
10}
549 bench
{sieve
[dict
]} {sieve_dict
10}
550 bench
{ary
} {ary
100000}
551 bench
{repeat
} {use_repeat
}
552 bench
{upvar} {upvartest
}
553 bench
{nested loops
} {nestedloops
}
554 bench
{rotate
} {rotate
100000}
555 bench
{dynamic code
} {dyncode
}
556 bench
{dynamic code
(list)} {dyncode_list
}
557 bench
{PI digits
} {pi_digits
}
558 bench
{expand
} {expand
}
559 bench
{wiki.tcl.
tk/8566} {commonsub_test
}
560 bench
{mandel
} {mandel
60 60 -2 -1.5
1 1.5}
563 return [expr {![catch {info tclversion
}]}]
567 if {[catch {info patchlevel
} ver
]} {
568 set ver Jim
[info version
]
570 puts [list $ver $benchmarks]