summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsebres <sebres@users.sourceforge.net>2017-07-03 13:27:20 (GMT)
committersebres <sebres@users.sourceforge.net>2017-07-03 13:27:20 (GMT)
commitd21bae7857c761d57f933bcc4b2256edd5fe7e11 (patch)
tree6b4dd176f55141325a76eeb96fbfe22eb20580f0
parenta07a5d700e82162dc377db840df58e437da1a8f9 (diff)
downloadtcl-d21bae7857c761d57f933bcc4b2256edd5fe7e11.zip
tcl-d21bae7857c761d57f933bcc4b2256edd5fe7e11.tar.gz
tcl-d21bae7857c761d57f933bcc4b2256edd5fe7e11.tar.bz2
added performance test-cases to cover timer-events speed resp. event-driven tcl-handling
(cherry-picked and back-ported from tclSE-9)
-rw-r--r--tests-perf/test-performance.tcl121
-rw-r--r--tests-perf/timer-event.perf.tcl149
2 files changed, 270 insertions, 0 deletions
diff --git a/tests-perf/test-performance.tcl b/tests-perf/test-performance.tcl
new file mode 100644
index 0000000..b0cbb17
--- /dev/null
+++ b/tests-perf/test-performance.tcl
@@ -0,0 +1,121 @@
+# ------------------------------------------------------------------------
+#
+# test-performance.tcl --
+#
+# This file provides common performance tests for comparison of tcl-speed
+# degradation or regression by switching between branches.
+#
+# To execute test case evaluate direct corresponding file "tests-perf\*.perf.tcl".
+#
+# ------------------------------------------------------------------------
+#
+# Copyright (c) 2014 Serg G. Brester (aka sebres)
+#
+# See the file "license.terms" for information on usage and redistribution
+# of this file.
+#
+
+namespace eval ::tclTestPerf {
+# warm-up interpeter compiler env, calibrate timerate measurement functionality:
+
+# if no timerate here - import from unsupported:
+if {[namespace which -command timerate] eq {}} {
+ namespace inscope ::tcl::unsupported {namespace export timerate}
+ namespace import ::tcl::unsupported::timerate
+}
+
+# if not yet calibrated:
+if {[lindex [timerate {} 10] 6] >= (10-1)} {
+ puts -nonewline "Calibration ... "; flush stdout
+ puts "done: [lrange \
+ [timerate -calibrate {}] \
+ 0 1]"
+}
+
+proc {**STOP**} {args} {
+ return -code error -level 4 "**STOP** in [info level [expr {[info level]-2}]] [join $args { }]"
+}
+
+proc _test_get_commands {lst} {
+ regsub -all {(?:^|\n)[ \t]*(\#[^\n]*|\msetup\M[^\n]*|\mcleanup\M[^\n]*)(?=\n\s*(?:[\{\#]|setup|cleanup|$))} $lst "\n{\\1}"
+}
+
+proc _test_out_total {} {
+ upvar _ _
+
+ set tcnt [llength $_(itm)]
+ if {!$tcnt} {
+ puts ""
+ return
+ }
+
+ set mintm 0x7fffffff
+ set maxtm 0
+ set nett 0
+ set wtm 0
+ set wcnt 0
+ set i 0
+ foreach tm $_(itm) {
+ if {[llength $tm] > 6} {
+ set nett [expr {$nett + [lindex $tm 6]}]
+ }
+ set wtm [expr {$wtm + [lindex $tm 0]}]
+ set wcnt [expr {$wcnt + [lindex $tm 2]}]
+ set tm [lindex $tm 0]
+ if {$tm > $maxtm} {set maxtm $tm; set maxi $i}
+ if {$tm < $mintm} {set mintm $tm; set mini $i}
+ incr i
+ }
+
+ puts [string repeat ** 40]
+ set s [format "%d cases in %.2f sec." $tcnt [expr {([clock milliseconds] - $_(starttime)) / 1000.0}]]
+ if {$nett > 0} {
+ append s [format " (%.2f nett-sec.)" [expr {$nett / 1000.0}]]
+ }
+ puts "Total $s:"
+ lset _(m) 0 [format %.6f $wtm]
+ lset _(m) 2 $wcnt
+ lset _(m) 4 [format %.3f [expr {$wcnt / (($nett ? $nett : ($tcnt * $_(reptime))) / 1000.0)}]]
+ if {[llength $_(m)] > 6} {
+ lset _(m) 6 [format %.3f $nett]
+ }
+ puts $_(m)
+ puts "Average:"
+ lset _(m) 0 [format %.6f [expr {[lindex $_(m) 0] / $tcnt}]]
+ lset _(m) 2 [expr {[lindex $_(m) 2] / $tcnt}]
+ if {[llength $_(m)] > 6} {
+ lset _(m) 6 [format %.3f [expr {[lindex $_(m) 6] / $tcnt}]]
+ lset _(m) 4 [format %.0f [expr {[lindex $_(m) 2] / [lindex $_(m) 6] * 1000}]]
+ }
+ puts $_(m)
+ puts "Min:"
+ puts [lindex $_(itm) $mini]
+ puts "Max:"
+ puts [lindex $_(itm) $maxi]
+ puts [string repeat ** 40]
+ puts ""
+}
+
+proc _test_run {reptime lst {outcmd {puts $_(r)}}} {
+ upvar _ _
+ array set _ [list itm {} reptime $reptime starttime [clock milliseconds]]
+
+ foreach _(c) [_test_get_commands $lst] {
+ puts "% [regsub -all {\n[ \t]*} $_(c) {; }]"
+ if {[regexp {^\s*\#} $_(c)]} continue
+ if {[regexp {^\s*(?:setup|cleanup)\s+} $_(c)]} {
+ puts [if 1 [lindex $_(c) 1]]
+ continue
+ }
+ if {$reptime > 1} {; #if not once:
+ set _(r) [if 1 $_(c)]
+ if {$outcmd ne {}} $outcmd
+ }
+ puts [set _(m) [timerate $_(c) $reptime]]
+ lappend _(itm) $_(m)
+ puts ""
+ }
+ _test_out_total
+}
+
+}; # end of namespace ::tclTestPerf
diff --git a/tests-perf/timer-event.perf.tcl b/tests-perf/timer-event.perf.tcl
new file mode 100644
index 0000000..fdca695
--- /dev/null
+++ b/tests-perf/timer-event.perf.tcl
@@ -0,0 +1,149 @@
+#!/usr/bin/tclsh
+
+# ------------------------------------------------------------------------
+#
+# timer-event.perf.tcl --
+#
+# This file provides performance tests for comparison of tcl-speed
+# of timer events (event-driven tcl-handling).
+#
+# ------------------------------------------------------------------------
+#
+# Copyright (c) 2014 Serg G. Brester (aka sebres)
+#
+# See the file "license.terms" for information on usage and redistribution
+# of this file.
+#
+
+
+if {![namespace exists ::tclTestPerf]} {
+ source [file join [file dirname [info script]] test-performance.tcl]
+}
+
+
+namespace eval ::tclTestPerf-Timer-Event {
+
+namespace path {::tclTestPerf}
+
+proc test-queue {howmuch} {
+
+ # because of extremely short measurement times by tests below, wait a little bit (warming-up),
+ # to minimize influence of the time-gradation (just for better dispersion resp. result-comparison)
+ timerate {after 0} 156
+
+ puts "*** $howmuch events ***"
+ _test_run 0 [string map [list \$howmuch $howmuch \\# \#] {
+ # update / after idle:
+ setup {puts [time {after idle {set foo bar}} $howmuch]}
+ {update; \# $howmuch idle-events}
+ # update idletasks / after idle:
+ setup {puts [time {after idle {set foo bar}} $howmuch]}
+ {update idletasks; \# $howmuch idle-events}
+
+ # update / after 0:
+ setup {puts [time {after 0 {set foo bar}} $howmuch]}
+ {update; \# $howmuch timer-events}
+ # update / after 1:
+ setup {puts [time {after 1 {set foo bar}} $howmuch]; after 1}
+ {update; \# $howmuch timer-events}
+
+ # cancel forwards "after idle" / $howmuch idle-events in queue:
+ setup {set i 0; time {set ev([incr i]) [after idle {set foo bar}]} $howmuch}
+ {set i 0; time {after cancel $ev([incr i])} $howmuch}
+ cleanup {update}
+ # cancel backwards "after idle" / $howmuch idle-events in queue:
+ setup {set i 0; time {set ev([incr i]) [after idle {set foo bar}]} $howmuch}
+ {incr i; time {after cancel $ev([incr i -1])} $howmuch}
+ cleanup {update}
+
+ # cancel forwards "after 0" / $howmuch timer-events in queue:
+ setup {set i 0; time {set ev([incr i]) [after 0 {set foo bar}]} $howmuch}
+ {set i 0; time {after cancel $ev([incr i])} $howmuch}
+ cleanup {update}
+ # cancel backwards "after 0" / $howmuch timer-events in queue:
+ setup {set i 0; time {set ev([incr i]) [after 0 {set foo bar}]} $howmuch}
+ {incr i; time {after cancel $ev([incr i -1])} $howmuch}
+ cleanup {update}
+ # end $howmuch events.
+ }]
+}
+
+proc test-exec {{reptime 1000}} {
+ _test_run $reptime {
+ # after idle + after cancel
+ {after cancel [after idle {set foo bar}]}
+ # after 0 + after cancel
+ {after cancel [after 0 {set foo bar}]}
+ # after idle + update idletasks
+ {after idle {set foo bar}; update idletasks}
+ # after idle + update
+ {after idle {set foo bar}; update}
+ # immediate: after 0 + update
+ {after 0 {set foo bar}; update}
+ # delayed: after 1 + update
+ {after 1 {set foo bar}; update}
+ # empty update:
+ {update}
+ # empty update idle tasks:
+ {update idletasks}
+ }
+}
+
+proc test-exec-new {{reptime 1000}} {
+ _test_run $reptime {
+ # conditional update pure idle only (without window):
+ {update -idle}
+ # conditional update without idle events:
+ {update -noidle}
+ # conditional update timers only:
+ {update -timer}
+ # conditional update AIO only:
+ {update -async}
+
+ # conditional vwait with zero timeout: pure idle only (without window):
+ {vwait -idle 0 x}
+ # conditional vwait with zero timeout: without idle events:
+ {vwait -noidle 0 x}
+ # conditional vwait with zero timeout: timers only:
+ {vwait -timer 0 x}
+ # conditional vwait with zero timeout: AIO only:
+ {vwait -async 0 x}
+ }
+}
+
+proc test-long {{reptime 1000}} {
+ _test_run $reptime {
+ # in-between important event by amount of idle events:
+ {time {after idle {after 30}} 10; after 1 {set important 1}; vwait important;}
+ cleanup {foreach i [after info] {after cancel $i}}
+ # in-between important event (of new generation) by amount of idle events:
+ {time {after idle {after 30}} 10; after 1 {after 0 {set important 1}}; vwait important;}
+ cleanup {foreach i [after info] {after cancel $i}}
+ }
+}
+
+proc test {{reptime 1000}} {
+ test-exec $reptime
+ if {![catch {update -noidle}]} {
+ test-exec-new $reptime
+ }
+ test-long $reptime
+
+ puts ""
+ foreach howmuch { 10000 20000 40000 60000 } {
+ test-queue $howmuch
+ }
+
+ puts \n**OK**
+}
+
+}; # end of ::tclTestPerf-Timer-Event
+
+# ------------------------------------------------------------------------
+
+# if calling direct:
+if {[info exists ::argv0] && [file tail $::argv0] eq [file tail [info script]]} {
+ array set in {-time 500}
+ array set in $argv
+ ::tclTestPerf-Timer-Event::test $in(-time)
+}