Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

Re: command completion taking ages



Oliver Kiddle wrote:

> If I press tab in a position where all commands are completed, I get a
> very long delay.

And of course we should have a look why this is so slow...

It turned out that one of the main reasons was that permalloc()
(called from the function that does $compstate[nmatches]) got called
very often and re-calculated the list of matches again and again (of
course).

The patch below at least makes it re-use already calculated and
perm-alloc'ed groups again if they didn't change. This already makes
it more than twice as fast as it was before for me. It won't have much 
effect for people who don't use the group-name style, though. I played
a bit with re-using already perm-alloc'ed matches, but that had
surprisingly little effect, so I took it out again.


Has anyone ever had a look at the output of `mem' (with zsh's
allocation routines) after doing completion in command position with
an empty prefix? Very interesting. I get some 300KB of free (i.e.
unused) memory. Urgh.

Maybe we should make it calculate the amount of memory needed for each 
group (there wouldn't be much overhead for this, I think), allocate
only one big block and write everything in it. And then we could think 
about giving support for such relatively-short-lived-but-still-zalloc'ed
blocks in mem.c, allocating them out of the way of normal zalloc'ed
memory (e.g. using mmap() if available, like we do it for heaps).


The hunks in mem.c just add some more information a bit of information 
to the output of `mem' that I've been missing once too often now.

Bye
 Sven

diff -ru ../z.old/Src/Zle/comp.h Src/Zle/comp.h
--- ../z.old/Src/Zle/comp.h	Wed Mar 15 12:53:10 2000
+++ Src/Zle/comp.h	Wed Mar 15 13:49:04 2000
@@ -73,6 +73,8 @@
     int *widths;		/* column widths for listpacked */
     int totl;			/* total length */
     int shortest;		/* length of shortest match */
+    Cmgroup perm;		/* perm. alloced version of this group */
+    int new;			/* new matches since last permalloc() */
 };
 
 
diff -ru ../z.old/Src/Zle/compcore.c Src/Zle/compcore.c
--- ../z.old/Src/Zle/compcore.c	Wed Mar 15 12:53:10 2000
+++ Src/Zle/compcore.c	Wed Mar 15 13:53:45 2000
@@ -2174,6 +2174,7 @@
     addlinknode((alt ? fmatches : matches), cm);
 
     newmatches = 1;
+    mgroup->new = 1;
 
     if (!complastprompt || !*complastprompt)
 	dolastprompt = 0;
@@ -2262,6 +2263,8 @@
     mgroup->matches = NULL;
     mgroup->ylist = NULL;
     mgroup->expls = NULL;
+    mgroup->perm = NULL;
+    mgroup->new = 0;
 
     mgroup->lexpls = expls = newlinklist();
     mgroup->lmatches = matches = newlinklist();
@@ -2519,12 +2522,12 @@
 mod_export int
 permmatches(int last)
 {
-    Cmgroup g = amatches, n;
+    Cmgroup g = amatches, n, opm;
     Cmatch *p, *q;
     Cexpl *ep, *eq, e, o;
     LinkList mlist;
     static int fi = 0;
-    int nn, nl, ll, gn = 1, mn = 1, rn;
+    int nn, nl, ll, gn = 1, mn = 1, rn, ofi = fi;
 
     if (pmatches && !newmatches) {
 	if (last && fi)
@@ -2533,9 +2536,7 @@
     }
     newmatches = fi = 0;
 
-    if (pmatches)
-	freematches(pmatches);
-
+    opm = pmatches;
     pmatches = lmatches = NULL;
     nmatches = smatches = 0;
 
@@ -2545,68 +2546,87 @@
 	fi = 1;
     }
     while (g) {
-	if (fi)
-	    /* We have no matches, try ignoring fignore. */
-	    mlist = g->lfmatches;
-	else
-	    mlist = g->lmatches;
-
-	g->matches = makearray(mlist, 1, g->flags, &nn, &nl, &ll);
-	g->mcount = nn;
-	if ((g->lcount = nn - nl) < 0)
-	    g->lcount = 0;
-	g->llcount = ll;
-	if (g->ylist) {
-	    g->lcount = arrlen(g->ylist);
-	    smatches = 2;
-	}
-	g->expls = (Cexpl *) makearray(g->lexpls, 0, 0, &(g->ecount),
-				       NULL, NULL);
+	if (fi != ofi || !g->perm || g->new) {
+	    if (fi)
+		/* We have no matches, try ignoring fignore. */
+		mlist = g->lfmatches;
+	    else
+		mlist = g->lmatches;
+
+	    g->matches = makearray(mlist, 1, g->flags, &nn, &nl, &ll);
+	    g->mcount = nn;
+	    if ((g->lcount = nn - nl) < 0)
+		g->lcount = 0;
+	    g->llcount = ll;
+	    if (g->ylist) {
+		g->lcount = arrlen(g->ylist);
+		smatches = 2;
+	    }
+	    g->expls = (Cexpl *) makearray(g->lexpls, 0, 0, &(g->ecount),
+					   NULL, NULL);
 
-	g->ccount = 0;
+	    g->ccount = 0;
 
-	nmatches += g->mcount;
-	smatches += g->lcount;
+	    nmatches += g->mcount;
+	    smatches += g->lcount;
 
-	n = (Cmgroup) zcalloc(sizeof(struct cmgroup));
-
-	if (!lmatches)
-	    lmatches = n;
-	if (pmatches)
-	    pmatches->prev = n;
-	n->next = pmatches;
-	pmatches = n;
-	n->prev = 0;
-	n->num = gn++;
-
-	n->flags = g->flags;
-	n->mcount = g->mcount;
-	n->matches = p = (Cmatch *) zcalloc((n->mcount + 1) * sizeof(Cmatch));
-	n->name = ztrdup(g->name);
-	for (q = g->matches; *q; q++, p++)
-	    *p = dupmatch(*q, nbrbeg, nbrend);
-	*p = NULL;
-
-	n->lcount = g->lcount;
-	n->llcount = g->llcount;
-	if (g->ylist)
-	    n->ylist = zarrdup(g->ylist);
-	else
-	    n->ylist = NULL;
+	    n = (Cmgroup) zcalloc(sizeof(struct cmgroup));
 
-	if ((n->ecount = g->ecount)) {
-	    n->expls = ep = (Cexpl *) zcalloc((n->ecount + 1) * sizeof(Cexpl));
-	    for (eq = g->expls; (o = *eq); eq++, ep++) {
-		*ep = e = (Cexpl) zcalloc(sizeof(struct cexpl));
-		e->count = (fi ? o->fcount : o->count);
-		e->str = ztrdup(o->str);
+	    if (g->perm) {
+		g->perm->next = NULL;
+		freematches(g->perm);
 	    }
-	    *ep = NULL;
-	} else
-	    n->expls = NULL;
+	    g->perm = n;
 
-	n->widths = NULL;
+	    if (!lmatches)
+		lmatches = n;
+	    if (pmatches)
+		pmatches->prev = n;
+	    n->next = pmatches;
+	    pmatches = n;
+	    n->prev = NULL;
+	    n->num = gn++;
+	    n->flags = g->flags;
+	    n->mcount = g->mcount;
+	    n->matches = p = (Cmatch *) zcalloc((n->mcount + 1) * sizeof(Cmatch));
+	    n->name = ztrdup(g->name);
+	    for (q = g->matches; *q; q++, p++)
+		*p = dupmatch(*q, nbrbeg, nbrend);
+	    *p = NULL;
+
+	    n->lcount = g->lcount;
+	    n->llcount = g->llcount;
+	    if (g->ylist)
+		n->ylist = zarrdup(g->ylist);
+	    else
+		n->ylist = NULL;
+
+	    if ((n->ecount = g->ecount)) {
+		n->expls = ep = (Cexpl *) zcalloc((n->ecount + 1) * sizeof(Cexpl));
+		for (eq = g->expls; (o = *eq); eq++, ep++) {
+		    *ep = e = (Cexpl) zcalloc(sizeof(struct cexpl));
+		    e->count = (fi ? o->fcount : o->count);
+		    e->str = ztrdup(o->str);
+		}
+		*ep = NULL;
+	    } else
+		n->expls = NULL;
 
+	    n->widths = NULL;
+	} else {
+	    if (!lmatches)
+		lmatches = g->perm;
+	    if (pmatches)
+		pmatches->prev = g->perm;
+	    g->perm->next = pmatches;
+	    pmatches = g->perm;
+	    g->perm->prev = NULL;
+
+	    nmatches += g->mcount;
+	    smatches += g->lcount;
+	    g->num = gn++;
+	}
+	g->new = 0;
 	g = g->next;
     }
     for (g = pmatches; g; g = g->next) {
@@ -2664,7 +2684,7 @@
 
     while (g) {
 	n = g->next;
-	
+
 	for (m = g->matches; *m; m++)
 	    freematch(*m, g->nbrbeg, g->nbrend);
 
diff -ru ../z.old/Src/mem.c Src/mem.c
--- ../z.old/Src/mem.c	Wed Mar 15 12:53:07 2000
+++ Src/mem.c	Wed Mar 15 14:26:18 2000
@@ -1219,7 +1219,7 @@
     int i, ii, fi, ui, j;
     struct m_hdr *m, *mf, *ms;
     char *b, *c, buf[40];
-    long u = 0, f = 0;
+    long u = 0, f = 0, to, cu;
 
     if (ops['v']) {
 	printf("The lower and the upper addresses of the heap. Diff gives\n");
@@ -1242,13 +1242,15 @@
 	printf("values, i.e. the number of blocks of that size that is\n");
 	printf("currently allocated. Total is the product of size and diff,\n");
 	printf("i.e. the number of bytes that are allocated for blocks of\n");
-	printf("this size.\n");
+	printf("this size. The last field gives the accumulated number of\n");
+	printf("bytes for all sizes.\n");
     }
-    printf("\nsize\tmalloc\tfree\tdiff\ttotal\n");
-    for (i = 0; i < 1024; i++)
+    printf("\nsize\tmalloc\tfree\tdiff\ttotal\tcum\n");
+    for (i = 0, cu = 0; i < 1024; i++)
 	if (m_m[i] || m_f[i])
-	    printf("%ld\t%d\t%d\t%d\t%ld\n", (long)i * M_ISIZE, m_m[i], m_f[i],
-		   m_m[i] - m_f[i], (long)i * M_ISIZE * (m_m[i] - m_f[i]));
+	    printf("%ld\t%d\t%d\t%d\t%ld\t%ld\n",
+		   (long)i * M_ISIZE, m_m[i], m_f[i], m_m[i] - m_f[i],
+		   (to = (long) i * M_ISIZE * (m_m[i] - m_f[i])), (cu += to));
 
     if (m_m[i] || m_f[i])
 	printf("big\t%d\t%d\t%d\n", m_m[i], m_f[i], m_m[i] - m_f[i]);

--
Sven Wischnowsky                         wischnow@xxxxxxxxxxxxxxxxxxxxxxx



Messages sorted by: Reverse Date, Date, Thread, Author