From ccc592df50d217757d74cb343d046a92d76860c1 Mon Sep 17 00:00:00 2001 From: sebres Date: Thu, 16 May 2019 17:49:25 +0000 Subject: timerate: allow continue from measurement cycle (used for conditional flow control of iterations); more gentle evaluation behaviour, similar to a cycle now (also avoids extra overhead to set result to interp, etc.); todo: rewrite optimization of INST_DONE using last-instruction pointer or optimization flags for compile of iteration (if sebres's perf-branch gets merged). --- generic/tclCmdMZ.c | 40 +++++++++++++++++++++++++--------------- tests/cmdMZ.test | 8 ++++++++ 2 files changed, 33 insertions(+), 15 deletions(-) diff --git a/generic/tclCmdMZ.c b/generic/tclCmdMZ.c index fe5e51c..6be5087 100644 --- a/generic/tclCmdMZ.c +++ b/generic/tclCmdMZ.c @@ -4193,6 +4193,14 @@ Tcl_TimeRateObjCmd( } codePtr = TclCompileObj(interp, objPtr, NULL, 0); TclPreserveByteCode(codePtr); + /* + * Replace last compiled done instruction with continue: it's a part of + * iteration, this way evaluation will be more similar to a cycle (also + * avoids extra overhead to set result to interp, etc.) + */ + if (codePtr->codeStart[codePtr->numCodeBytes-1] == INST_DONE) { + codePtr->codeStart[codePtr->numCodeBytes-1] = INST_CONTINUE; + } } /* @@ -4237,23 +4245,25 @@ Tcl_TimeRateObjCmd( } else { /* eval */ result = TclEvalObjEx(interp, objPtr, 0, NULL, 0); } - if (result != TCL_OK) { - /* - * Allow break from measurement cycle (used for conditional - * stop). - */ + /* + * Allow break and continue from measurement cycle (used for + * conditional stop and flow control of iterations). + */ - if (result != TCL_BREAK) { + switch (result) { + case TCL_OK: + break; + case TCL_BREAK: + /* + * Force stop immediately. + */ + threshold = 1; + maxcnt = 0; + case TCL_CONTINUE: + result = TCL_OK; + break; + default: goto done; - } - - /* - * Force stop immediately. - */ - - threshold = 1; - maxcnt = 0; - result = TCL_OK; } /* diff --git a/tests/cmdMZ.test b/tests/cmdMZ.test index 4c4f532..09fff07 100644 --- a/tests/cmdMZ.test +++ b/tests/cmdMZ.test @@ -412,6 +412,14 @@ test cmdMZ-6.8 {Tcl_TimeRateObjCmd: allow (conditional) break from timerate} { [expr {[lindex $m1 4] > 1000}] \ [expr {[lindex $m1 6] < 10}] } {1 1 1 1} +test cmdMZ-6.8.1 {Tcl_TimeRateObjCmd: allow (conditional) continue in timerate} { + set m1 [timerate {continue; return -code error "unexpected"} 1000 10] + list \ + [expr {[lindex $m1 0] < 1000}] \ + [expr {[lindex $m1 2] == 10}] \ + [expr {[lindex $m1 4] > 1000}] \ + [expr {[lindex $m1 6] < 100}] +} {1 1 1 1} test cmdMZ-6.9 {Tcl_TimeRateObjCmd: max count of iterations} { set m1 [timerate {} 1000 5]; # max-count wins set m2 [timerate {_nrt_sleep 20} 1 5]; # max-time wins -- cgit v0.12 From 2865a8da13749af3807ff9ea42c079f8c6c73133 Mon Sep 17 00:00:00 2001 From: sebres Date: Thu, 16 May 2019 18:17:52 +0000 Subject: small amend to [ac566e9df84daeab] with rollback of done/continue optimization --- generic/tclCmdMZ.c | 7 +++++++ tests/cmdMZ.test | 6 ++++++ 2 files changed, 13 insertions(+) diff --git a/generic/tclCmdMZ.c b/generic/tclCmdMZ.c index 6be5087..d2485ef 100644 --- a/generic/tclCmdMZ.c +++ b/generic/tclCmdMZ.c @@ -4009,6 +4009,7 @@ Tcl_TimeRateObjCmd( TMRT_EV_DIRECT, TMRT_OVERHEAD, TMRT_CALIBRATE, TMRT_LAST }; ByteCode *codePtr = NULL; + int codeOptimized = 0; for (i = 1; i < objc - 1; i++) { int index; @@ -4200,6 +4201,7 @@ Tcl_TimeRateObjCmd( */ if (codePtr->codeStart[codePtr->numCodeBytes-1] == INST_DONE) { codePtr->codeStart[codePtr->numCodeBytes-1] = INST_CONTINUE; + codeOptimized = 1; } } @@ -4487,6 +4489,11 @@ Tcl_TimeRateObjCmd( done: if (codePtr != NULL) { + if ( codeOptimized + && codePtr->codeStart[codePtr->numCodeBytes-1] == INST_CONTINUE + ) { + codePtr->codeStart[codePtr->numCodeBytes-1] = INST_DONE; + } TclReleaseByteCode(codePtr); } return result; diff --git a/tests/cmdMZ.test b/tests/cmdMZ.test index 09fff07..db72a44 100644 --- a/tests/cmdMZ.test +++ b/tests/cmdMZ.test @@ -433,6 +433,12 @@ test cmdMZ-6.10 {Tcl_TimeRateObjCmd: huge overhead cause 0us result} { [expr {[lindex $m1 4] == 1000000}] \ [expr {[lindex $m1 6] <= 0.001}] } {1 1 1 1} +test cmdMZ-6.11 {Tcl_TimeRateObjCmd: done/continue optimization rollback} { + set m1 {set m2 ok} + if 1 $m1 + timerate $m1 1000 10 + if 1 $m1; # if rollback is missing throws an error: invoked "continue" outside of a loop +} ok # The tests for Tcl_WhileObjCmd are in while.test -- cgit v0.12