diff options
| -rw-r--r-- | generic/tclCmdMZ.c | 39 | ||||
| -rw-r--r-- | generic/tclPort.h | 3 | ||||
| -rw-r--r-- | tests/cmdMZ.test | 27 |
3 files changed, 53 insertions, 16 deletions
diff --git a/generic/tclCmdMZ.c b/generic/tclCmdMZ.c index cb44e08..ba86203 100644 --- a/generic/tclCmdMZ.c +++ b/generic/tclCmdMZ.c @@ -3986,8 +3986,10 @@ Tcl_TimeRateObjCmd( register int result, i; Tcl_Obj *calibrate = NULL, *direct = NULL; Tcl_WideUInt count = 0; /* Holds repetition count */ - Tcl_WideInt maxms = -0x7FFFFFFFFFFFFFFFL; + Tcl_WideInt maxms = WIDE_MIN; /* Maximal running time (in milliseconds) */ + Tcl_WideUInt maxcnt = WIDE_MAX; + /* Maximal count of iterations. */ Tcl_WideUInt threshold = 1; /* Current threshold for check time (faster * repeat count without time check) */ Tcl_WideUInt maxIterTm = 1; /* Max time of some iteration as max threshold @@ -4036,24 +4038,32 @@ Tcl_TimeRateObjCmd( } } - if (i >= objc || i < objc-2) { + if (i >= objc || i < objc-3) { usage: - Tcl_WrongNumArgs(interp, 1, objv, "?-direct? ?-calibrate? ?-overhead double? command ?time?"); + Tcl_WrongNumArgs(interp, 1, objv, "?-direct? ?-calibrate? ?-overhead double? command ?time ?max-count??"); return TCL_ERROR; } objPtr = objv[i++]; - if (i < objc) { - result = Tcl_GetWideIntFromObj(interp, objv[i], &maxms); + if (i < objc) { /* max-time */ + result = Tcl_GetWideIntFromObj(interp, objv[i++], &maxms); if (result != TCL_OK) { return result; } + if (i < objc) { /* max-count*/ + Tcl_WideInt v; + result = Tcl_GetWideIntFromObj(interp, objv[i], &v); + if (result != TCL_OK) { + return result; + } + maxcnt = (v > 0) ? v : 0; + } } /* if calibrate */ if (calibrate) { /* if no time specified for the calibration */ - if (maxms == -0x7FFFFFFFFFFFFFFFL) { + if (maxms == WIDE_MIN) { Tcl_Obj *clobjv[6]; Tcl_WideInt maxCalTime = 5000; double lastMeasureOverhead = measureOverhead; @@ -4083,7 +4093,7 @@ usage: clobjv[i++] = objPtr; /* set last measurement overhead to max */ - measureOverhead = (double)0x7FFFFFFFFFFFFFFFL; + measureOverhead = (double)UWIDE_MAX; /* calibration cycle until it'll be preciser */ maxms = -1000; @@ -4117,14 +4127,14 @@ usage: /* if time is negative - make current overhead more precise */ if (maxms > 0) { /* set last measurement overhead to max */ - measureOverhead = (double)0x7FFFFFFFFFFFFFFFL; + measureOverhead = (double)UWIDE_MAX; } else { maxms = -maxms; } } - if (maxms == -0x7FFFFFFFFFFFFFFFL) { + if (maxms == WIDE_MIN) { maxms = 1000; } if (overhead == -1) { @@ -4157,6 +4167,7 @@ usage: #endif /* start measurement */ + if (maxcnt > 0) while (1) { /* eval single iteration */ count++; @@ -4175,7 +4186,7 @@ usage: } /* force stop immediately */ threshold = 1; - stop = -0x7FFFFFFFFFFFFFFFL; + maxcnt = 0; result = TCL_OK; } @@ -4189,7 +4200,7 @@ usage: Tcl_GetTime(&now); middle = now.sec; middle *= 1000000; middle += now.usec; #endif - if (middle >= stop) { + if (middle >= stop || count >= maxcnt) { break; } @@ -4224,6 +4235,10 @@ usage: if (threshold > 100000) { /* fix for too large threshold */ threshold = 100000; } + /* consider max-count */ + if (threshold > maxcnt - count) { + threshold = maxcnt - count; + } } { @@ -4276,7 +4291,7 @@ usage: /* calculate speed as rate (count) per sec */ if (!middle) middle++; /* +1 ms, just to avoid divide by zero */ - if (count < (0x7FFFFFFFFFFFFFFFL / 1000000)) { + if (count < (WIDE_MAX / 1000000)) { val = (count * 1000000) / middle; if (val < 100000) { if (val < 100) { fmt = "%.3f"; } else diff --git a/generic/tclPort.h b/generic/tclPort.h index 12a60db..9485567 100644 --- a/generic/tclPort.h +++ b/generic/tclPort.h @@ -39,5 +39,8 @@ # define LLONG_MAX (~LLONG_MIN) #endif +#define UWIDE_MAX ((Tcl_WideUInt)-1) +#define WIDE_MAX ((Tcl_WideInt)(UWIDE_MAX >> 1)) +#define WIDE_MIN ((Tcl_WideInt)((Tcl_WideUInt)WIDE_MAX+1)) #endif /* _TCLPORT */ diff --git a/tests/cmdMZ.test b/tests/cmdMZ.test index 08f1ffe..60f6236 100644 --- a/tests/cmdMZ.test +++ b/tests/cmdMZ.test @@ -349,13 +349,19 @@ test cmdMZ-5.7 {Tcl_TimeObjCmd: errors generate right trace} { test cmdMZ-6.1 {Tcl_TimeRateObjCmd: basic format of command} { list [catch {timerate} msg] $msg -} {1 {wrong # args: should be "timerate ?-direct? ?-calibrate? ?-overhead double? command ?time?"}} -test cmdMZ-6.2 {Tcl_TimeRateObjCmd: basic format of command} { +} {1 {wrong # args: should be "timerate ?-direct? ?-calibrate? ?-overhead double? command ?time ?max-count??"}} +test cmdMZ-6.2.1 {Tcl_TimeRateObjCmd: basic format of command} { + list [catch {timerate a b c d} msg] $msg +} {1 {wrong # args: should be "timerate ?-direct? ?-calibrate? ?-overhead double? command ?time ?max-count??"}} +test cmdMZ-6.2.2 {Tcl_TimeRateObjCmd: basic format of command} { list [catch {timerate a b c} msg] $msg -} {1 {wrong # args: should be "timerate ?-direct? ?-calibrate? ?-overhead double? command ?time?"}} -test cmdMZ-6.3 {Tcl_TimeRateObjCmd: basic format of command} { +} {1 {expected integer but got "b"}} +test cmdMZ-6.2.3 {Tcl_TimeRateObjCmd: basic format of command} { list [catch {timerate a b} msg] $msg } {1 {expected integer but got "b"}} +test cmdMZ-6.3 {Tcl_TimeRateObjCmd: basic format of command} { + list [catch {timerate -overhead b {} a b} msg] $msg +} {1 {expected floating-point number but got "b"}} test cmdMZ-6.4 {Tcl_TimeRateObjCmd: compile of script happens even with negative iteration counts} { list [catch {timerate "foreach a {c d e} \{" -12456} msg] $msg } {1 {missing close-brace}} @@ -391,6 +397,19 @@ 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.9 {Tcl_TimeRateObjCmd: max count of iterations} { + set m1 [timerate {} 1000 5]; # max-count wins + set m2 [timerate {after 20} 1 5]; # max-time wins + list [lindex $m1 2] [lindex $m2 2] +} {5 1} +test cmdMZ-6.10 {Tcl_TimeRateObjCmd: huge overhead cause 0us result} { + set m1 [timerate -overhead 1e6 {after 10} 100 1] + list \ + [expr {[lindex $m1 0] == 0.0}] \ + [expr {[lindex $m1 2] == 1}] \ + [expr {[lindex $m1 4] == 1000000}] \ + [expr {[lindex $m1 6] <= 0.001}] +} {1 1 1 1} # The tests for Tcl_WhileObjCmd are in while.test |
