Hello, I attach patch that needs one problem to be resolved. Gains for following test code: test_fun() { arr[20000]="" repeat 10000; do arr[10000]="x" done } are huge: 37969 ms with no optimization, 244 ms with optimization. The screensaver runs for 495 sec without optimization, 51 sec with opt (still slower than hash which runs for 23 sec). I changed: if (v->end <= pre_assignment_length) post_assignment_length += pre_assignment_length - v->end + 1; to: if (v->end <= pre_assignment_length) post_assignment_length += pre_assignment_length - v->end; And this allows to test post* == pre*. I think the "+ 1" isn't needed, v->end can be treated as "number of elements affected already". Subtracting the number of elements from pre_assignment_length gives correct value: elements that will be copied from old. The thing that has to be resolved: special setters. The patch contains one special handler tested: if ( pre_assignment_length != post_assignment_length || v->pm->gsu.a->setfn == set_region_active ) { But this doesn't work as the symbol `set_region_active` isn't available. How to solve this, and what are other special handlers? One test is failing (A06) – append to typeset -U array, because the special setter isn't called. -- Sebastian Gniazdowski psprint@xxxxxxxxxxxx
diff --git a/Src/params.c b/Src/params.c index ef72cba..e23a0af 100644 --- a/Src/params.c +++ b/Src/params.c @@ -2654,24 +2654,34 @@ setarrvalue(Value v, char **val) v->end = v->start; post_assignment_length = v->start + arrlen(val); - if (v->end <= pre_assignment_length) - post_assignment_length += pre_assignment_length - v->end + 1; - - p = new = (char **) zshcalloc(sizeof(char *) - * (post_assignment_length + 1)); - - for (i = 0; i < v->start; i++) - *p++ = i < pre_assignment_length ? ztrdup(*q++) : ztrdup(""); - for (r = val; *r;) { - /* Give away ownership of the string */ - *p++ = *r++; - } - if (v->end < pre_assignment_length) - for (q = old + v->end; *q;) - *p++ = ztrdup(*q++); - *p = NULL; - v->pm->gsu.a->setfn(v->pm, new); + if (v->end <= pre_assignment_length) + post_assignment_length += pre_assignment_length - v->end; + + if ( pre_assignment_length != post_assignment_length || v->pm->gsu.a->setfn == set_region_active ) { + p = new = (char **) zshcalloc(sizeof(char *) + * (post_assignment_length + 1)); + + for (i = 0; i < v->start; i++) + *p++ = i < pre_assignment_length ? ztrdup(*q++) : ztrdup(""); + for (r = val; *r;) { + /* Give away ownership of the string */ + *p++ = *r++; + } + if (v->end < pre_assignment_length) + for (q = old + v->end; *q;) + *p++ = ztrdup(*q++); + *p = NULL; + + v->pm->gsu.a->setfn(v->pm, new); + } else { + /* v->start is 0-based */ + p = old + v->start; + for (r = val; *r;) { + /* Give away ownership of the string */ + *p++ = *r++; + } + } /* Ownership of all strings has been * given away, can plainly free */
Attachment:
testopt7.zsh
Description: Binary data