summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--generic/tclCmdMZ.c39
-rw-r--r--generic/tclPort.h3
-rw-r--r--tests/cmdMZ.test27
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