From: Sebastian Gniazdowski <psprint3@fastmail.com>
To: zsh-workers@zsh.org
Subject: Re: [PATCH] zrealloc on array+=( )
Date: Sat, 04 Mar 2017 05:47:39 -0800 [thread overview]
Message-ID: <1488635259.1730344.900251328.5D6F1325@webmail.messagingengine.com> (raw)
[-- Attachment #1: Type: text/plain, Size: 793 bytes --]
Hello,
I revisited the patch, tested with debug prints, added test cases that
stress things out. No code changes.
Thought to test how Bash (3.2) performs on appends:
# fun() { local -a arr; i=5001; while (( -- i )); do arr+=( "The
appended test string of medium length" ); done; }
# time fun
real 0m0.221s
user 0m0.214s
sys 0m0.004s
So it's 200 ms. The same test with no-zrealloc-Zsh is 2.94 s. With the
patch it's 116 ms (using time tool, typeset -F SECONDS reveals it's 4
ms). So this can be a motivation to apply the patch. We can leverage the
fact that operating system has size of the array and can extend it, and
this way beat Bash. Of course, the real deal here is to be able to do
data processing, e.g. log gathering, etc.
--
Sebastian Gniazdowski
psprint3@fastmail.com
[-- Attachment #2: array_zrealloc2.diff --]
[-- Type: text/plain, Size: 4240 bytes --]
diff --git a/Src/params.c b/Src/params.c
index 19cbb1c..8942fef 100644
--- a/Src/params.c
+++ b/Src/params.c
@@ -2723,24 +2723,57 @@ setarrvalue(Value v, char **val)
*p++ = *r++;
}
} else {
- p = new = (char **) zalloc(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;
+ /* arr+=( ... )
+ * arr[${#arr}+x,...]=( ... ) */
+ if (post_assignment_length > pre_assignment_length &&
+ pre_assignment_length <= v->start &&
+ pre_assignment_length > 0 &&
+ v->pm->gsu.a->setfn == arrsetfn)
+ {
+ p = new = (char **) zrealloc(old, sizeof(char *)
+ * (post_assignment_length + 1));
+
+ p += pre_assignment_length; /* after old elements */
+
+ /* Consider 1 < 0, case for a=( 1 ); a[1,..] =
+ * 1 < 1, case for a=( 1 ); a[2,..] = */
+ if (pre_assignment_length < v->start) {
+ for (i = pre_assignment_length; i < v->start; i++) {
+ *p++ = ztrdup("");
+ }
+ }
+
+ for (r = val; *r;) {
+ /* Give away ownership of the string */
+ *p++ = *r++;
+ }
+
+ /* v->end doesn't matter:
+ * a=( 1 2 ); a[4,100]=( a b ); echo "${(q@)a}"
+ * 1 2 '' a b */
+ *p = NULL;
+
+ v->pm->u.arr = NULL;
+ v->pm->gsu.a->setfn(v->pm, new);
+ } else {
+ p = new = (char **) zalloc(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);
+ }
DPUTS2(p - new != post_assignment_length, "setarrvalue: wrong allocation: %d 1= %lu",
post_assignment_length, (unsigned long)(p - new));
-
- v->pm->gsu.a->setfn(v->pm, new);
}
/* Ownership of all strings has been
diff --git a/Test/A06assign.ztst b/Test/A06assign.ztst
index bf39aee..fd2b417 100644
--- a/Test/A06assign.ztst
+++ b/Test/A06assign.ztst
@@ -133,6 +133,72 @@
>1 2 42 43 44 5
>1 2 42 100 99 5
+# (subsection: append to array)
+
+ array=( )
+ array[5,6]=( 1 2 3 )
+ print $array
+ print "${(q@)array}"
+0:Append to empty array by range
+>1 2 3
+>'' '' '' '' 1 2 3
+
+ array=( a )
+ array[5,6]=( 1 2 3 )
+ print $array
+ print "${(q@)array}"
+0:Append to 1-element array by range
+>a 1 2 3
+>a '' '' '' 1 2 3
+
+ array=( a b )
+ array[5,6]=( 1 2 3 )
+ print $array
+ print "${(q@)array}"
+0:Append to 2-element array by range
+>a b 1 2 3
+>a b '' '' 1 2 3
+
+ array=( a b )
+ array[5,5]=( 1 2 3 )
+ print $array
+ print "${(q@)array}"
+0:Append to 2-element array by [a,a] range
+>a b 1 2 3
+>a b '' '' 1 2 3
+
+ array=( a b c d )
+ array[5,6]=( 1 2 3 )
+ print $array
+ print "${(q@)array}"
+0:Append array by range, continuously
+>a b c d 1 2 3
+>a b c d 1 2 3
+
+ array=( a b c d )
+ array[5,5]=( 1 2 3 )
+ print $array
+ print "${(q@)array}"
+0:Append array by [a,a] range, continuously
+>a b c d 1 2 3
+>a b c d 1 2 3
+
+ array=( )
+ array+=( 1 2 3 )
+ print $array
+ print "${(q@)array}"
+0:Append empty array via +=
+>1 2 3
+>1 2 3
+
+ array=( a )
+ array+=( 1 2 3 )
+ print $array
+ print "${(q@)array}"
+0:Append 1-element array via +=
+>a 1 2 3
+>a 1 2 3
+
# tests of var+=scalar
s+=foo
next reply other threads:[~2017-03-04 13:47 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-03-04 13:47 Sebastian Gniazdowski [this message]
2017-03-04 17:22 ` Bart Schaefer
-- strict thread matches above, loose matches on Subject: below --
2017-02-26 12:06 Sebastian Gniazdowski
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1488635259.1730344.900251328.5D6F1325@webmail.messagingengine.com \
--to=psprint3@fastmail.com \
--cc=zsh-workers@zsh.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this public inbox
https://git.vuxu.org/mirror/zsh/
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).