Hello There are double strlen() invocations in getstrvalue(). It's not about negative indexes – although they have been optimized too – but about dupstring() and v->end, v->start verification code at the end. Actually a single strlen() call is required. Attached test script runs 1765 ms for optimized Zsh, 1980 ms for no optimizations (minimum obtainable times): strtest() { a="" i=$(( 4000 )) while (( i -- )); do a+="a${a[1,200]}" done } I've used signed size variable but the code did that already. More optimization is possible – dupstring() could do strncpy(), copy only requested number of bytes, e.g. first 200 out of 10000, but the trailing \0 nuances made me wait with this change. -- Sebastian Gniazdowski psprint@xxxxxxxxxxxx
diff --git a/Src/params.c b/Src/params.c index 330f22b..5005042 100644 --- a/Src/params.c +++ b/Src/params.c @@ -2060,6 +2060,7 @@ getstrvalue(Value v) { char *s, **ss; char buf[BDIGBUFSIZE]; + int len = -1; if (!v) return hcalloc(1); @@ -2237,22 +2238,26 @@ getstrvalue(Value v) return s; if (v->start < 0) { - v->start += strlen(s); + v->start += (len=(int)strlen(s)); if (v->start < 0) v->start = 0; } if (v->end < 0) { - v->end += strlen(s); + len = (len >= 0) ? len : (int)strlen(s); + v->end += len; if (v->end >= 0) { char *eptr = s + v->end; if (*eptr) v->end += MB_METACHARLEN(eptr); } } - s = (v->start > (int)strlen(s)) ? dupstring("") : dupstring(s + v->start); + + len = (len >= 0) ? len : (int)strlen(s); + s = (v->start > len) ? dupstring("") : dupstring_wlen(s + v->start, len - v->start); + if (v->end <= v->start) s[0] = '\0'; - else if (v->end - v->start <= (int)strlen(s)) + else if (v->end - v->start <= len - v->start) s[v->end - v->start] = '\0'; return s; diff --git a/Src/string.c b/Src/string.c index 04e7446..b46ea60 100644 --- a/Src/string.c +++ b/Src/string.c @@ -43,6 +43,19 @@ dupstring(const char *s) /**/ mod_export char * +dupstring_wlen(const char *s, unsigned len) +{ + char *t; + + if (!s) + return NULL; + t = (char *) zhalloc(len + 1); + strcpy(t, s); + return t; +} + +/**/ +mod_export char * ztrdup(const char *s) { char *t;
Attachment:
testopt2.zsh
Description: Binary data