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 ($res)"}
12 lappend benchmarks
$title F
14 set t
[expr [lindex $res 0] / 1000]
15 lappend benchmarks
$title $t
17 set ts
[string range
$ts [expr {[string length
$ts]-10}] end
]
18 if {!$batchmode} {puts "$Title -$ts ms per iteration"}
23 ### BUSY LOOP ##################################################################
25 proc whilebusyloop
{} {
27 while {$i < 1850000} {
34 for {set i
0} {$i < 1850000} {incr i
} {
39 ### FIBONACCI ##################################################################
45 expr {[fibonacci
[expr {$x-1}]] + [fibonacci
[expr {$x-2}]]}
49 ### HEAPSORT ###################################################################
57 proc make_gen_random
{} {
59 set params
[list IM
$IM IA
$IA IC
$IC]
60 set body
[string map
$params {
62 expr {($max * [set last
[expr {($last * IA
+ IC
) % IM
}]]) / IM
}
64 proc gen_random
{max
} $body
67 proc heapsort
{ra_name
} {
71 set ir
[expr {$n - 1}]
74 set rra
[lindex $ra [incr l
-1]]
76 set rra
[lindex $ra $ir]
77 lset ra
$ir [lindex $ra 0]
78 if {[incr ir
-1] == 0} {
84 set j
[expr {(2 * $l) + 1}]
86 set tmp
[lindex $ra $j]
88 if {$tmp < [lindex $ra [expr {$j + 1}]]} {
89 set tmp
[lindex $ra [incr j
]]
102 proc heapsort_main
{} {
107 for {set i
1} {$i <= $n} {incr i
} {
108 lappend data
[gen_random
1.0]
113 ### SIEVE ######################################################################
119 for {set i
2} {$i <= 8192} {incr i
} {
122 for {set i
2} {$i <= 8192} {incr i
} {
123 if {$flags($i) == 1} {
124 # remove all multiples of prime: i
125 for {set k
[expr {$i+$i}]} {$k <= 8192} {incr k
$i} {
135 proc sieve_dict
{num
} {
139 for {set i
2} {$i <= 8192} {incr i
} {
142 for {set i
2} {$i <= 8192} {incr i
} {
143 if {[dict get
$flags $i] == 1} {
144 # remove all multiples of prime: i
145 for {set k
[expr {$i+$i}]} {$k <= 8192} {incr k
$i} {
155 ### ARY ########################################################################
158 for {set i
0} {$i < $n} {incr i
} {
161 set last
[expr {$n - 1}]
162 for {set j
$last} {$j >= 0} {incr j
-1} {
168 for {set i
0} {$i < $n} {incr i
} {
171 set last
[expr {$n - 1}]
172 for {set j
$last} {$j >= 0} {incr j
-1} {
178 for {set i
0} {$i < $n} {incr i
} {
184 ### REPEAT #####################################################################
186 proc repeat
{n body
} {
187 for {set i
0} {$i < $n} {incr i
} {
194 repeat
{1000000} {incr x
}
197 ### UPVAR ######################################################################
199 proc myincr varname
{
206 for {set x
0} {$x < 100000} {myincr x
} {
211 ### NESTED LOOPS ###############################################################
213 proc nestedloops
{} {
218 while {[incr a
-1]} {
220 while {[incr b
-1]} {
222 while {[incr c
-1]} {
224 while {[incr d
-1]} {
226 while {[incr e
-1]} {
228 while {[incr f
-1]} {
238 ### ROTATE #####################################################################
240 proc rotate
{count
} {
242 for {set n
0} {$n < $count} {incr n
} {
243 set v
[expr {$v <<< 1}]
247 ### DYNAMICALLY GENERATED CODE #################################################
250 for {set i
0} {$i < 100000} {incr i
} {
251 set script
"lappend foo $i"
256 proc dyncode_list
{} {
257 for {set i
0} {$i < 100000} {incr i
} {
258 set script
[list lappend foo
$i]
263 ### PI DIGITS ##################################################################
266 set n
[expr {$N * 3}]
269 for { set b
0 } { $b <= $n } { incr b
} {
272 for { set c
$n } { $c > 0 } { incr c
-14 } {
274 set g
[expr { $c * 2 }]
277 incr d
[expr { [lindex $f $b] * 10000 }]
278 lset f
$b [expr {$d % [incr g
-1]}]
279 set d
[expr { $d / $g }]
281 if { [incr b
-1] == 0 } break
282 set d
[expr { $d * $b }]
284 append result
[string range
0000[expr { $e + $d / 10000 }] end-3 end
]
285 set e
[expr { $d % 10000 }]
290 ### EXPAND #####################################################################
293 set a
[list a b c d e f
]
294 for {set i
0} {$i < 100000} {incr i
} {
299 ### MINLOOPS ###################################################################
302 for {set i
0} {$i < 100000} {incr i
} {
304 for {set j
0} {$j < 10} {incr j
} {
305 # something of more or less real
311 ### wiki.tcl.tk/8566 ###########################################################
313 # Internal procedure that indexes into the 2-dimensional array t,
314 # which corresponds to the sequence y, looking for the (i,j)th element.
316 proc Index
{ t y i j
} {
317 set indx
[expr { ([llength $y] + 1) * ($i + 1) + ($j + 1) }]
318 return [lindex $t $indx]
321 # Internal procedure that implements Levenshtein to derive the longest
322 # common subsequence of two lists x and y.
324 proc ComputeLCS
{ x y
} {
326 for { set i
-1 } { $i < [llength $y] } { incr i
} {
329 for { set i
0 } { $i < [llength $x] } { incr i
} {
331 for { set j
0 } { $j < [llength $y] } { incr j
} {
332 if { [string equal
[lindex $x $i] [lindex $y $j]] } {
333 set lastT
[Index
$t $y [expr { $i - 1 }] [expr {$j - 1}]]
334 set nextT
[expr {$lastT + 1}]
336 set lastT1
[Index
$t $y $i [expr { $j - 1 }]]
337 set lastT2
[Index
$t $y [expr { $i - 1 }] $j]
338 if { $lastT1 > $lastT2 } {
350 # Internal procedure that traces through the array built by ComputeLCS
351 # and finds a longest common subsequence -- specifically, the one that
352 # is lexicographically first.
354 proc TraceLCS
{ t x y
} {
356 set i
[expr { [llength $x] - 1 }]
357 set j
[expr { [llength $y] - 1 }]
358 set k
[expr { [Index
$t $y $i $j] - 1 }]
359 while { $i >= 0 && $j >= 0 } {
360 set im1
[expr { $i - 1 }]
361 set jm1
[expr { $j - 1 }]
362 if { [Index
$t $y $i $j] == [Index
$t $y $im1 $jm1] + 1
363 && [string equal
[lindex $x $i] [lindex $y $j]] } {
364 lappend trace xy
[list $i $j]
367 } elseif
{ [Index
$t $y $im1 $j] > [Index
$t $y $i $jm1] } {
386 # list::longestCommonSubsequence::compare --
388 # Compare two lists for the longest common subsequence
391 # x, y - Two lists of strings to compare
392 # matched - Callback to execute on matched elements, see below
393 # unmatchedX - Callback to execute on unmatched elements from the
394 # first list, see below.
395 # unmatchedY - Callback to execute on unmatched elements from the
396 # second list, see below.
402 # Whatever the callbacks do.
404 # The 'compare' procedure compares the two lists of strings, x and y.
405 # It finds a longest common subsequence between the two. It then walks
406 # the lists in order and makes the following callbacks:
408 # For an element that is common to both lists, it appends the index in
409 # the first list, the index in the second list, and the string value of
410 # the element as three parameters to the 'matched' callback, and executes
413 # For an element that is in the first list but not the second, it appends
414 # the index in the first list and the string value of the element as two
415 # parameters to the 'unmatchedX' callback and executes the result.
417 # For an element that is in the second list but not the first, it appends
418 # the index in the second list and the string value of the element as two
419 # parameters to the 'unmatchedY' callback and executes the result.
423 unmatchedX unmatchedY
} {
424 set t
[ComputeLCS
$x $y]
425 set trace [TraceLCS
$t $x $y]
426 set i
[llength $trace]
428 set indices
[lindex $trace [incr i
-1]]
429 set type
[lindex $trace [incr i
-1]]
430 switch -exact -- $type {
433 eval lappend c
$indices
434 lappend c
[lindex $x [lindex $indices 0]]
440 lappend c
[lindex $x $indices]
446 lappend c
[lindex $y $indices]
454 proc umx
{ index value
} {
457 append xlines
"< " $value \n
461 proc umy
{ index value
} {
464 append ylines
"> " $value \n
468 proc matched
{ index1 index2 value
} {
473 if { [info exists lastx
] && [info exists lasty
] } {
474 #puts "[expr { $lastx + 1 }],${index1}c[expr {$lasty + 1 }],${index2}"
475 #puts -nonewline $xlines
477 #puts -nonewline $ylines
478 } elseif
{ [info exists lastx
] } {
479 #puts "[expr { $lastx + 1 }],${index1}d${index2}"
480 #puts -nonewline $xlines
481 } elseif
{ [info exists lasty
] } {
482 #puts "${index1}a[expr {$lasty + 1 }],${index2}"
483 #puts -nonewline $ylines
485 catch { unset lastx
}
486 catch { unset xlines
}
487 catch { unset lasty
}
488 catch { unset ylines
}
491 # Really, we should read the first file in like this:
492 # set f0 [open [lindex $argv 0] r]
493 # set x [split [read $f0] \n]
495 # But I'll just provide some sample lines:
497 proc commonsub_test
{} {
499 for { set i
0 } { $i < 20 } { incr i
} {
500 lappend x a r a d e d a b r a x
503 # The second file, too, should be read in like this:
504 # set f1 [open [lindex $argv 1] r]
505 # set y [split [read $f1] \n]
507 # Once again, I'll just do some sample lines.
510 for { set i
0 } { $i < 20 } { incr i
} {
511 lappend y a b r a c a d a b r a
514 compare
$x $y matched umx umy
515 matched
[llength $x] [llength $y] {}
518 ### MANDEL #####################################################################
520 proc mandel
{xres yres infx infy supx supy
} {
521 set incremx
[expr {(0.0+$supx-$infx)/$xres}]
522 set incremy
[expr {(0.0+$supy-$infy)/$yres}]
524 for {set j
0} {$j < $yres} {incr j
} {
525 set cim
[expr {$infy+$incremy*$j}]
527 for {set i
0} {$i < $xres} {incr i
} {
531 set cre
[expr {$infx+$incremx*$i}]
532 while {$counter < 255} {
533 set dam
[expr {$zre*$zre-$zim*$zim+$cre}]
534 set zim
[expr {2*$zim*$zre+$cim}]
536 if {$zre*$zre+$zim*$zim > 4} break
544 ### RUN ALL ####################################################################
546 if {[string compare
[lindex $argv 0] "-batch"] == 0} {
548 set argv
[lrange $argv 1 end
]
550 set ver
[lindex $argv 0]
552 bench
{[while] busy loop
} {whilebusyloop
}
553 bench
{[for] busy loop
} {forbusyloop
}
554 bench
{mini loops
} {miniloops
}
555 bench
{fibonacci
(25)} {fibonacci
25}
556 bench
{heapsort
} {heapsort_main
}
557 bench
{sieve
} {sieve
10}
558 bench
{sieve
[dict
]} {sieve_dict
10}
559 bench
{ary
} {ary
100000}
560 bench
{ary
[dict
]} {ary_dict
100000}
561 bench
{ary
[static
]} {ary_static
1000000}
562 bench
{repeat
} {use_repeat
}
563 bench
{upvar} {upvartest
}
564 bench
{nested loops
} {nestedloops
}
565 bench
{rotate
} {rotate
100000}
566 bench
{dynamic code
} {dyncode
}
567 bench
{dynamic code
(list)} {dyncode_list
}
568 bench
{PI digits
} {pi_digits
300}
569 bench
{expand
} {expand
}
570 bench
{wiki.tcl.
tk/8566} {commonsub_test
}
571 bench
{mandel
} {mandel
60 60 -2 -1.5
1 1.5}
575 if {[catch {info patchlevel
} ver
]} {
576 set ver Jim
[info version
]
579 puts [list $ver $benchmarks]