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