Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Changes In Branch sebres-8-6-clock-speedup-cr2 Through [a011e0dddc] Excluding Merge-Ins
This is equivalent to a diff from 0c840ffac5 to a011e0dddc
|
2018-05-29
| ||
| 17:03 | Added max permitted threshold (buffer size > result size) in percent, to directly return the buffer ... check-in: 2f98e44d4b user: sebres tags: sebres-8-6-clock-speedup-cr2 | |
| 17:02 | further optimization: better cache for GMT-timezone + minimize (re)allocation of buffers check-in: a011e0dddc user: sebres tags: sebres-8-6-clock-speedup-cr2 | |
| 17:01 | code review: micro optimizations check-in: f5e76e52be user: sebres tags: sebres-8-6-clock-speedup-cr2 | |
| 16:40 | tests-perf\test-performance.tcl: ported from sebres-8-6-event-perf-branch (common test performance f... check-in: a08a2e912f user: sebres tags: sebres-8-6-clock-speedup-cr2 | |
|
2017-10-20
| ||
| 12:36 | Merge core-8-6-branch (execpt file win/makefile.vc) Closed-Leaf check-in: 0c840ffac5 user: dgp tags: sebres-8-6-clock-speedup-cr1 | |
|
2017-10-19
| ||
| 09:28 | Oops; put the code in the wrong place. Mixins have priority when deciding method visibility. check-in: 4140046408 user: dkf tags: core-8-6-branch | |
|
2017-08-08
| ||
| 15:19 | fixed overflow of year (resp. julianday), closes ticket [16e4fc3096]; test cases adjusted. check-in: 3efed18ef8 user: sebres tags: sebres-8-6-clock-speedup-cr1 | |
Changes to generic/tclClock.c.
| ︙ | ︙ | |||
234 235 236 237 238 239 240 241 242 243 244 245 246 247 |
data->yearOfCenturySwitch = ClockDefaultCenturySwitch;
data->systemTimeZone = NULL;
data->systemSetupTZData = NULL;
data->gmtSetupTimeZoneUnnorm = NULL;
data->gmtSetupTimeZone = NULL;
data->gmtSetupTZData = NULL;
data->lastSetupTimeZoneUnnorm = NULL;
data->lastSetupTimeZone = NULL;
data->lastSetupTZData = NULL;
data->prevSetupTimeZoneUnnorm = NULL;
data->prevSetupTimeZone = NULL;
data->prevSetupTZData = NULL;
| > | 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 |
data->yearOfCenturySwitch = ClockDefaultCenturySwitch;
data->systemTimeZone = NULL;
data->systemSetupTZData = NULL;
data->gmtSetupTimeZoneUnnorm = NULL;
data->gmtSetupTimeZone = NULL;
data->gmtSetupTZData = NULL;
data->gmtTZName = NULL;
data->lastSetupTimeZoneUnnorm = NULL;
data->lastSetupTimeZone = NULL;
data->lastSetupTZData = NULL;
data->prevSetupTimeZoneUnnorm = NULL;
data->prevSetupTimeZone = NULL;
data->prevSetupTZData = NULL;
|
| ︙ | ︙ | |||
306 307 308 309 310 311 312 313 314 315 316 317 318 319 |
data->lastTZEpoch = 0;
Tcl_UnsetObjRef(data->systemTimeZone);
Tcl_UnsetObjRef(data->systemSetupTZData);
Tcl_UnsetObjRef(data->gmtSetupTimeZoneUnnorm);
Tcl_UnsetObjRef(data->gmtSetupTimeZone);
Tcl_UnsetObjRef(data->gmtSetupTZData);
Tcl_UnsetObjRef(data->lastSetupTimeZoneUnnorm);
Tcl_UnsetObjRef(data->lastSetupTimeZone);
Tcl_UnsetObjRef(data->lastSetupTZData);
Tcl_UnsetObjRef(data->prevSetupTimeZoneUnnorm);
Tcl_UnsetObjRef(data->prevSetupTimeZone);
Tcl_UnsetObjRef(data->prevSetupTZData);
| > | 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 |
data->lastTZEpoch = 0;
Tcl_UnsetObjRef(data->systemTimeZone);
Tcl_UnsetObjRef(data->systemSetupTZData);
Tcl_UnsetObjRef(data->gmtSetupTimeZoneUnnorm);
Tcl_UnsetObjRef(data->gmtSetupTimeZone);
Tcl_UnsetObjRef(data->gmtSetupTZData);
Tcl_UnsetObjRef(data->gmtTZName);
Tcl_UnsetObjRef(data->lastSetupTimeZoneUnnorm);
Tcl_UnsetObjRef(data->lastSetupTimeZone);
Tcl_UnsetObjRef(data->lastSetupTZData);
Tcl_UnsetObjRef(data->prevSetupTimeZoneUnnorm);
Tcl_UnsetObjRef(data->prevSetupTimeZone);
Tcl_UnsetObjRef(data->prevSetupTZData);
|
| ︙ | ︙ | |||
1227 1228 1229 1230 1231 1232 1233 |
Tcl_Obj *timezoneObj)
{
ClockClientData *dataPtr = clientData;
int loaded;
Tcl_Obj *callargs[2];
/* if cached (if already setup this one) */
| > | > > > | < > | | | < | 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 |
Tcl_Obj *timezoneObj)
{
ClockClientData *dataPtr = clientData;
int loaded;
Tcl_Obj *callargs[2];
/* if cached (if already setup this one) */
if ( timezoneObj == dataPtr->literals[LIT_GMT]
&& dataPtr->gmtSetupTZData != NULL
) {
return timezoneObj;
}
if ( ( timezoneObj == dataPtr->lastSetupTimeZone
|| timezoneObj == dataPtr->lastSetupTimeZoneUnnorm
) && dataPtr->lastSetupTimeZone != NULL
) {
return dataPtr->lastSetupTimeZone;
}
if ( ( timezoneObj == dataPtr->prevSetupTimeZone
|| timezoneObj == dataPtr->prevSetupTimeZoneUnnorm
) && dataPtr->prevSetupTimeZone != NULL
) {
return dataPtr->prevSetupTimeZone;
}
/* differentiate normalized (last, GMT and system) zones, because used often and already set */
callargs[1] = NormTimezoneObj(dataPtr, timezoneObj, &loaded);
/* if loaded (setup already called for this TZ) */
|
| ︙ | ︙ | |||
1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 |
* Convert to Julian or Gregorian calendar.
*/
GetGregorianEraYearDay(fields, changeover);
GetMonthDay(fields);
GetYearWeekDay(fields, changeover);
return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
* ClockGetjuliandayfromerayearmonthdayObjCmd --
| > > > > > > > > > | 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 |
* Convert to Julian or Gregorian calendar.
*/
GetGregorianEraYearDay(fields, changeover);
GetMonthDay(fields);
GetYearWeekDay(fields, changeover);
/*
* Seconds of the day.
*/
fields->secondOfDay = (int)(fields->localSeconds % SECONDS_PER_DAY);
if (fields->secondOfDay < 0) {
fields->secondOfDay += SECONDS_PER_DAY;
}
return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
* ClockGetjuliandayfromerayearmonthdayObjCmd --
|
| ︙ | ︙ | |||
2105 2106 2107 2108 2109 2110 2111 |
{
ClockClientData *dataPtr = clientData;
Tcl_Obj *tzdata; /* Time zone data */
int rowc; /* Number of rows in tzdata */
Tcl_Obj **rowv; /* Pointers to the rows */
/* fast phase-out for shared GMT-object (don't need to convert UTC 2 UTC) */
| | < < > > > | | | | > > | | 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 |
{
ClockClientData *dataPtr = clientData;
Tcl_Obj *tzdata; /* Time zone data */
int rowc; /* Number of rows in tzdata */
Tcl_Obj **rowv; /* Pointers to the rows */
/* fast phase-out for shared GMT-object (don't need to convert UTC 2 UTC) */
if (timezoneObj == dataPtr->literals[LIT_GMT]) {
fields->localSeconds = fields->seconds;
fields->tzOffset = 0;
if (dataPtr->gmtTZName == NULL) {
Tcl_Obj *tzName;
tzdata = ClockGetTZData(clientData, interp, timezoneObj);
if ( TclListObjGetElements(interp, tzdata, &rowc, &rowv) != TCL_OK
|| Tcl_ListObjIndex(interp, rowv[0], 3, &tzName) != TCL_OK) {
return TCL_ERROR;
}
Tcl_SetObjRef(dataPtr->gmtTZName, tzName);
}
Tcl_SetObjRef(fields->tzName, dataPtr->gmtTZName);
return TCL_OK;
}
/*
* Check cacheable conversion could be used
* (last-period UTC2Local cache within the same TZ)
*/
|
| ︙ | ︙ | |||
2606 2607 2608 2609 2610 2611 2612 |
static void
GetMonthDay(
TclDateFields *fields) /* Date to convert */
{
int day = fields->dayOfYear;
int month;
| | > > > > > > > > > > > > | > > | | > > | 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 |
static void
GetMonthDay(
TclDateFields *fields) /* Date to convert */
{
int day = fields->dayOfYear;
int month;
const int *dipm = daysInPriorMonths[IsGregorianLeapYear(fields)];
/*
* Estimate month by calculating `dayOfYear / (365/12)`
*/
month = (day*12) / dipm[12];
/* then do forwards backwards correction */
while (1) {
if (day > dipm[month]) {
if (month >= 11 || day <= dipm[month+1]) {
break;
}
month++;
} else {
if (month == 0) {
break;
}
month--;
}
}
day -= dipm[month];
fields->month = month+1;
fields->dayOfMonth = day;
}
/*
*----------------------------------------------------------------------
*
|
| ︙ | ︙ | |||
3256 3257 3258 3259 3260 3261 3262 |
Tcl_SetObjResult(interp, Tcl_NewStringObj("cannot use -gmt and -timezone in same call", -1));
Tcl_SetErrorCode(interp, "CLOCK", "gmtWithTimezone", NULL);
return TCL_ERROR;
}
if (gmtFlag) {
opts->timezoneObj = dataPtr->literals[LIT_GMT];
}
| | < | 3289 3290 3291 3292 3293 3294 3295 3296 3297 3298 3299 3300 3301 3302 3303 3304 |
Tcl_SetObjResult(interp, Tcl_NewStringObj("cannot use -gmt and -timezone in same call", -1));
Tcl_SetErrorCode(interp, "CLOCK", "gmtWithTimezone", NULL);
return TCL_ERROR;
}
if (gmtFlag) {
opts->timezoneObj = dataPtr->literals[LIT_GMT];
}
else
/* If time zone not specified use system time zone */
if ( opts->timezoneObj == NULL
|| TclGetString(opts->timezoneObj) == NULL
|| opts->timezoneObj->length == 0
) {
opts->timezoneObj = ClockGetSystemTimeZone(opts->clientData, interp);
if (opts->timezoneObj == NULL) {
return TCL_ERROR;
|
| ︙ | ︙ | |||
4230 4231 4232 4233 4234 4235 4236 |
{
static char* tzWas = INT2PTR(-1); /* Previous value of TZ, protected by
* clockMutex. */
static long tzLastRefresh = 0; /* Used for latency before next refresh */
static size_t tzWasEpoch = 0; /* Epoch, signals that TZ changed */
static size_t tzEnvEpoch = 0; /* Last env epoch, for faster signaling,
that TZ changed via TCL */
| < > | 4262 4263 4264 4265 4266 4267 4268 4269 4270 4271 4272 4273 4274 4275 4276 4277 4278 4279 4280 4281 4282 4283 4284 4285 4286 4287 4288 |
{
static char* tzWas = INT2PTR(-1); /* Previous value of TZ, protected by
* clockMutex. */
static long tzLastRefresh = 0; /* Used for latency before next refresh */
static size_t tzWasEpoch = 0; /* Epoch, signals that TZ changed */
static size_t tzEnvEpoch = 0; /* Last env epoch, for faster signaling,
that TZ changed via TCL */
const char *tzIsNow; /* Current value of TZ */
/*
* Prevent performance regression on some platforms by resolving of system time zone:
* small latency for check whether environment was changed (once per second)
* no latency if environment was chaned with tcl-env (compare both epoch values)
*/
Tcl_Time now;
Tcl_GetTime(&now);
if (now.sec == tzLastRefresh && tzEnvEpoch == TclEnvEpoch) {
return tzWasEpoch;
}
tzEnvEpoch = TclEnvEpoch;
tzLastRefresh = now.sec;
/* check in lock */
Tcl_MutexLock(&clockMutex);
tzIsNow = getenv("TCL_TZ");
if (tzIsNow == NULL) {
|
| ︙ | ︙ |
Changes to generic/tclClockFmt.c.
| ︙ | ︙ | |||
2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 |
-1));
Tcl_SetErrorCode(opts->interp, "CLOCK", "badInputString", NULL);
done:
return ret;
}
static inline int
FrmResultAllocate(
register DateFormat *dateFmt,
int len)
{
int needed = dateFmt->output + len - dateFmt->resEnd;
if (needed >= 0) { /* >= 0 - regards NTS zero */
int newsize = dateFmt->resEnd - dateFmt->resMem
| > > > | > > > > > > > > > | | | > | 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 |
-1));
Tcl_SetErrorCode(opts->interp, "CLOCK", "badInputString", NULL);
done:
return ret;
}
#define FrmResultIsAllocated(dateFmt) \
(dateFmt->resEnd - dateFmt->resMem > MIN_FMT_RESULT_BLOCK_ALLOC)
static inline int
FrmResultAllocate(
register DateFormat *dateFmt,
int len)
{
int needed = dateFmt->output + len - dateFmt->resEnd;
if (needed >= 0) { /* >= 0 - regards NTS zero */
int newsize = dateFmt->resEnd - dateFmt->resMem
+ needed + MIN_FMT_RESULT_BLOCK_ALLOC*2;
char *newRes;
/* differentiate between stack and memory */
if (!FrmResultIsAllocated(dateFmt)) {
newRes = ckalloc(newsize);
if (newRes == NULL) {
return TCL_ERROR;
}
memcpy(newRes, dateFmt->resMem, dateFmt->output - dateFmt->resMem);
} else {
newRes = ckrealloc(dateFmt->resMem, newsize);
if (newRes == NULL) {
return TCL_ERROR;
}
}
dateFmt->output = newRes + (dateFmt->output - dateFmt->resMem);
dateFmt->resMem = newRes;
dateFmt->resEnd = newRes + newsize;
}
return TCL_OK;
}
|
| ︙ | ︙ | |||
2957 2958 2959 2960 2961 2962 2963 2964 2965 2966 2967 2968 2969 2970 2971 2972 2973 2974 2975 |
ClockFormat(
register DateFormat *dateFmt, /* Date fields used for parsing & converting */
ClockFmtScnCmdArgs *opts) /* Command options */
{
ClockFmtScnStorage *fss;
ClockFormatToken *tok;
ClockFormatTokenMap *map;
/* get localized format */
if (ClockLocalizeFormat(opts) == NULL) {
return TCL_ERROR;
}
if ( !(fss = ClockGetOrParseFmtFormat(opts->interp, opts->formatObj))
|| !(tok = fss->fmtTok)
) {
return TCL_ERROR;
}
| > < < < < < < > > > | > | | | > < | 2970 2971 2972 2973 2974 2975 2976 2977 2978 2979 2980 2981 2982 2983 2984 2985 2986 2987 2988 2989 2990 2991 2992 2993 2994 2995 2996 2997 2998 2999 3000 3001 3002 3003 3004 3005 3006 3007 |
ClockFormat(
register DateFormat *dateFmt, /* Date fields used for parsing & converting */
ClockFmtScnCmdArgs *opts) /* Command options */
{
ClockFmtScnStorage *fss;
ClockFormatToken *tok;
ClockFormatTokenMap *map;
char resMem[MIN_FMT_RESULT_BLOCK_ALLOC];
/* get localized format */
if (ClockLocalizeFormat(opts) == NULL) {
return TCL_ERROR;
}
if ( !(fss = ClockGetOrParseFmtFormat(opts->interp, opts->formatObj))
|| !(tok = fss->fmtTok)
) {
return TCL_ERROR;
}
/* result container object */
dateFmt->resMem = resMem;
dateFmt->resEnd = dateFmt->resMem + sizeof(resMem);
if (fss->fmtMinAlloc > sizeof(resMem)) {
dateFmt->resMem = ckalloc(fss->fmtMinAlloc);
dateFmt->resEnd = dateFmt->resMem + fss->fmtMinAlloc;
if (dateFmt->resMem == NULL) {
return TCL_ERROR;
}
}
dateFmt->output = dateFmt->resMem;
*dateFmt->output = '\0';
/* do format each token */
for (; tok->map != NULL; tok++) {
map = tok->map;
switch (map->type)
{
|
| ︙ | ︙ | |||
3078 3079 3080 3081 3082 3083 3084 |
}
}
goto done;
error:
| > | > > > > | > > > > > | | | > > > > > > > | 3090 3091 3092 3093 3094 3095 3096 3097 3098 3099 3100 3101 3102 3103 3104 3105 3106 3107 3108 3109 3110 3111 3112 3113 3114 3115 3116 3117 3118 3119 3120 3121 3122 3123 3124 3125 3126 3127 3128 3129 3130 3131 3132 |
}
}
goto done;
error:
if (dateFmt->resMem != resMem) {
ckfree(dateFmt->resMem);
}
dateFmt->resMem = NULL;
done:
if (dateFmt->resMem) {
size_t size;
Tcl_Obj * result = Tcl_NewObj();
result->length = dateFmt->output - dateFmt->resMem;
size = result->length+1;
if (dateFmt->resMem == resMem) {
result->bytes = ckalloc(size);
if (result->bytes == NULL) {
return TCL_ERROR;
}
memcpy(result->bytes, dateFmt->resMem, size);
} else {
result->bytes = ckrealloc(dateFmt->resMem, size);
if (result->bytes == NULL) {
result->bytes = dateFmt->resMem;
}
}
/* save last used buffer length */
if ( dateFmt->resMem != resMem
&& fss->fmtMinAlloc < size + MIN_FMT_RESULT_BLOCK_DELTA
) {
fss->fmtMinAlloc = size + MIN_FMT_RESULT_BLOCK_DELTA;
}
result->bytes[result->length] = '\0';
Tcl_SetObjResult(opts->interp, result);
return TCL_OK;
}
return TCL_ERROR;
|
| ︙ | ︙ |
Changes to generic/tclDate.h.
| ︙ | ︙ | |||
289 290 291 292 293 294 295 296 297 298 299 300 301 302 |
int currentYearCentury;
int yearOfCenturySwitch;
Tcl_Obj *systemTimeZone;
Tcl_Obj *systemSetupTZData;
Tcl_Obj *gmtSetupTimeZoneUnnorm;
Tcl_Obj *gmtSetupTimeZone;
Tcl_Obj *gmtSetupTZData;
Tcl_Obj *lastSetupTimeZoneUnnorm;
Tcl_Obj *lastSetupTimeZone;
Tcl_Obj *lastSetupTZData;
Tcl_Obj *prevSetupTimeZoneUnnorm;
Tcl_Obj *prevSetupTimeZone;
Tcl_Obj *prevSetupTZData;
| > | 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 |
int currentYearCentury;
int yearOfCenturySwitch;
Tcl_Obj *systemTimeZone;
Tcl_Obj *systemSetupTZData;
Tcl_Obj *gmtSetupTimeZoneUnnorm;
Tcl_Obj *gmtSetupTimeZone;
Tcl_Obj *gmtSetupTZData;
Tcl_Obj *gmtTZName;
Tcl_Obj *lastSetupTimeZoneUnnorm;
Tcl_Obj *lastSetupTimeZone;
Tcl_Obj *lastSetupTZData;
Tcl_Obj *prevSetupTimeZoneUnnorm;
Tcl_Obj *prevSetupTimeZone;
Tcl_Obj *prevSetupTZData;
|
| ︙ | ︙ | |||
379 380 381 382 383 384 385 |
unsigned short int minSize;
unsigned short int maxSize;
unsigned short int offs;
ClockScanTokenProc *parser;
const void *data;
} ClockScanTokenMap;
| | | | > | 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 |
unsigned short int minSize;
unsigned short int maxSize;
unsigned short int offs;
ClockScanTokenProc *parser;
const void *data;
} ClockScanTokenMap;
struct ClockScanToken {
ClockScanTokenMap *map;
struct {
const char *start;
const char *end;
} tokWord;
unsigned short int endDistance;
unsigned short int lookAhMin;
unsigned short int lookAhMax;
unsigned short int lookAhTok;
};
#define MIN_FMT_RESULT_BLOCK_ALLOC 80
#define MIN_FMT_RESULT_BLOCK_DELTA 30
typedef struct DateFormat {
char *resMem;
char *resEnd;
char *output;
TclDateFields date;
|
| ︙ | ︙ | |||
428 429 430 431 432 433 434 |
unsigned short int flags;
unsigned short int divider;
unsigned short int divmod;
unsigned short int offs;
ClockFormatTokenProc *fmtproc;
void *data;
} ClockFormatTokenMap;
| > | | | > | | 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 |
unsigned short int flags;
unsigned short int divider;
unsigned short int divmod;
unsigned short int offs;
ClockFormatTokenProc *fmtproc;
void *data;
} ClockFormatTokenMap;
struct ClockFormatToken {
ClockFormatTokenMap *map;
struct {
const char *start;
const char *end;
} tokWord;
};
typedef struct ClockFmtScnStorage ClockFmtScnStorage;
struct ClockFmtScnStorage {
int objRefCount; /* Reference count shared across threads */
ClockScanToken *scnTok;
unsigned int scnTokC;
unsigned int scnSpaceCount; /* Count of mandatory spaces used in format */
ClockFormatToken *fmtTok;
unsigned int fmtTokC;
#if CLOCK_FMT_SCN_STORAGE_GC_SIZE > 0
ClockFmtScnStorage *nextPtr;
ClockFmtScnStorage *prevPtr;
#endif
size_t fmtMinAlloc;
#if 0
+Tcl_HashEntry hashEntry /* ClockFmtScnStorage is a derivate of Tcl_HashEntry,
* stored by offset +sizeof(self) */
#endif
};
/*
* Prototypes of module functions.
*/
MODULE_SCOPE int ToSeconds(int Hours, int Minutes,
int Seconds, MERIDIAN Meridian);
|
| ︙ | ︙ |
Changes to generic/tclStrIdxTree.c.
| ︙ | ︙ | |||
82 83 84 85 86 87 88 |
TclStrIdx **foundItem, /* Return value of found item */
TclStrIdxTree *tree, /* Index tree will be browsed */
const char *start, /* UTF string to find in tree */
const char *end) /* End of string */
{
TclStrIdxTree *parent = tree, *prevParent = tree;
TclStrIdx *item = tree->firstPtr, *prevItem = NULL;
| | | 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 |
TclStrIdx **foundItem, /* Return value of found item */
TclStrIdxTree *tree, /* Index tree will be browsed */
const char *start, /* UTF string to find in tree */
const char *end) /* End of string */
{
TclStrIdxTree *parent = tree, *prevParent = tree;
TclStrIdx *item = tree->firstPtr, *prevItem = NULL;
const char *s = start, *f, *cin, *cinf, *prevf = NULL;
int offs = 0;
if (item == NULL) {
goto done;
}
/* search in tree */
|
| ︙ | ︙ | |||
271 272 273 274 275 276 277 |
/* ignore element if fulfilled or ambigous */
if (f == e) {
continue;
}
/* if shortest key was found with the same value,
* just replace its current key with longest key */
if ( foundItem->value == val
| | > | 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 |
/* ignore element if fulfilled or ambigous */
if (f == e) {
continue;
}
/* if shortest key was found with the same value,
* just replace its current key with longest key */
if ( foundItem->value == val
&& foundItem->length <= lwrv[i]->length
&& foundItem->length <= (f - s) /* only if found item is covered in full */
&& foundItem->childTree.firstPtr == NULL
) {
Tcl_SetObjRef(foundItem->key, lwrv[i]);
foundItem->length = lwrv[i]->length;
continue;
}
/* split tree (e. g. j->(jan,jun) + jul == j->(jan,ju->(jun,jul)) )
|
| ︙ | ︙ |
Changes to tests-perf/clock.perf.tcl.
| ︙ | ︙ | |||
12 13 14 15 16 17 18 | # Copyright (c) 2014 Serg G. Brester (aka sebres) # # See the file "license.terms" for information on usage and redistribution # of this file. # | | | > | < < < | < < | > > | < < < < < | > < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
# Copyright (c) 2014 Serg G. Brester (aka sebres)
#
# See the file "license.terms" for information on usage and redistribution
# of this file.
#
## common test performance framework:
if {![namespace exists ::tclTestPerf]} {
source [file join [file dirname [info script]] test-performance.tcl]
}
namespace eval ::tclTestPerf-TclClock {
namespace path {::tclTestPerf}
## set testing defaults:
set ::env(TCL_TZ) :CET
# warm-up interpeter compiler env, clock platform-related features:
## warm-up test-related features (load clock.tcl, system zones, locales, etc.):
clock scan "" -gmt 1
clock scan ""
clock scan "" -timezone :CET
clock scan "" -format "" -locale en
clock scan "" -format "" -locale de
## ------------------------------------------
proc test-format {{reptime 1000}} {
_test_run $reptime {
# Format : short, week only (in gmt)
{clock format 1482525936 -format "%u" -gmt 1}
# Format : short, week only (system zone)
{clock format 1482525936 -format "%u"}
# Format : short, week only (CEST)
|
| ︙ | ︙ | |||
478 479 480 481 482 483 484 |
test-add $reptime
test-convert [expr {$reptime / 2}]; #fast enough
test-other $reptime
puts \n**OK**
}
| > | > > > > > > > > | 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 |
test-add $reptime
test-convert [expr {$reptime / 2}]; #fast enough
test-other $reptime
puts \n**OK**
}
}; # end of ::tclTestPerf-TclClock
# ------------------------------------------------------------------------
# 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-TclClock::test $in(-time)
}
|
Added tests-perf/test-performance.tcl.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 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
|
Changes to tests/clock.test.
| ︙ | ︙ | |||
27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
package require msgcat 1.4
testConstraint detroit \
[expr {![catch {clock format 0 -timezone :America/Detroit -format %z}]}]
testConstraint y2038 \
[expr {[clock format 2158894800 -format %z -timezone :America/Detroit] eq {-0400}}]
# TEST PLAN
# clock-0:
# several base test-cases
#
# clock-1:
| > > | 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
package require msgcat 1.4
testConstraint detroit \
[expr {![catch {clock format 0 -timezone :America/Detroit -format %z}]}]
testConstraint y2038 \
[expr {[clock format 2158894800 -format %z -timezone :America/Detroit] eq {-0400}}]
testConstraint no_tclclockmod \
[expr {[namespace which -command ::tcl::clock::configure] eq {}}]
# TEST PLAN
# clock-0:
# several base test-cases
#
# clock-1:
|
| ︙ | ︙ | |||
251 252 253 254 255 256 257 |
return -code error "test case attempts to read unknown registry entry $path $key"
}
return [dict get $reg $path $key]
}
# Base test cases:
| | | 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 |
return -code error "test case attempts to read unknown registry entry $path $key"
}
return [dict get $reg $path $key]
}
# Base test cases:
test clock-0.1 "initial: auto-loading of ensemble and stubs on demand" no_tclclockmod {
set i [interp create]; # because clock can be used somewhere, test it in new interp:
set ret [$i eval {
lappend ret ens:[namespace ensemble exists ::clock]
clock seconds; # init ensemble (but not yet stubs, loading of clock.tcl retarded)
lappend ret ens:[namespace ensemble exists ::clock]
|
| ︙ | ︙ | |||
35183 35184 35185 35186 35187 35188 35189 35190 35191 35192 35193 35194 35195 35196 |
-format {%J %Ol:%M:%S %P}
} 86399
test clock-29.1800 {time parsing} {
clock scan {2440588 xi:lix:lix pm} \
-gmt true -locale en_US_roman \
-format {%J %Ol:%OM:%OS %P}
} 86399
# END testcases29
# BEGIN testcases30
# Test [clock add]
test clock-30.1 {clock add years} {
| > > > > > > > > > > > > > > > > > > > > > > > | 35185 35186 35187 35188 35189 35190 35191 35192 35193 35194 35195 35196 35197 35198 35199 35200 35201 35202 35203 35204 35205 35206 35207 35208 35209 35210 35211 35212 35213 35214 35215 35216 35217 35218 35219 35220 35221 |
-format {%J %Ol:%M:%S %P}
} 86399
test clock-29.1800 {time parsing} {
clock scan {2440588 xi:lix:lix pm} \
-gmt true -locale en_US_roman \
-format {%J %Ol:%OM:%OS %P}
} 86399
test clock-29.1811 {parsing of several localized formats} {
set res {}
foreach loc {en de fr} {
foreach fmt {"%x %X" "%X %x"} {
lappend res [clock scan \
[clock format 0 -format $fmt -locale $loc -gmt 1] \
-format $fmt -locale $loc -gmt 1]
}
}
set res
} [lrepeat 6 0]
test clock-29.1812 {parsing of several localized formats} {
set res {}
foreach loc {en de fr} {
foreach fmt {"%a %d-%m-%Y" "%a %b %x-%X" "%a, %x %X" "%b, %x %X"} {
lappend res [clock scan \
[clock format 0 -format $fmt -locale $loc -gmt 1] \
-format $fmt -locale $loc -gmt 1]
}
}
set res
} [lrepeat 12 0]
# END testcases29
# BEGIN testcases30
# Test [clock add]
test clock-30.1 {clock add years} {
|
| ︙ | ︙ |